合并排序在 React 中没有按预期工作

Merge Sort not working as expected in React

我已经调试这段代码好几个小时了,但没有弄错。 items 是具有随机初始高度的 div 元素的列表。 有人可以帮我吗,我找不到这段代码有什么问题?

mergeSort1(l, r) {
    if (l < r) {
        let mid = Math.floor((l + r) / 2)
        this.mergeSort1(l, mid)
        this.mergeSort1(mid + 1, r)
        this.merge1(l, mid, r)
    }
}
merge1(l, mid, r) {
    let items = document.getElementsByClassName("item")
    items = Array.from(items)
    let left = items.slice(l, mid + 1)
    let right = items.slice(mid + 1, r + 1)
    let I = 0
    let J = 0
    let k = 0
    let t = []
    
    while (I < left.length && J < right.length) {
        if (parseInt(left[I].style.height) < parseInt(right[J].style.height)) {
            t.push(left[I].style.height)
            items[k + l].style.height = left[I].style.height
            I = I + 1
            k++
        } else {
            items[k + l].style.height = right[J].style.height
            t.push(right[J].style.height)
            J = J + 1
            k++
        }
    }
    while (I < left.length) {
        items[k + l].style.height = left[I].style.height
        k++
        t.push(left[I].style.height)
        I = I + 1
    }
    while (J < right.length) {
        items[k + l].style.height = right[J].style.height
        t.push(right[J].style.height)
        J = J + 1
        k++
    }
    console.log(t)
}
this.mergeSort1(0, this.state.arr.length - 1)

arr 初始化于 componentDidMount():

componentDidMount() {
    //this.step(this)
    
    var a = []
    for (var i = 0; i < 200; i++) {
        a.push(Math.round(Math.random() * 80))
    }
    this.setState({
        arr : a
    }, () => console.log(this.state.arr))
}

render方法中:

arr.map((h, i) => {
        return (
            <div className="item" key={i} style={{height:h+'vh'}}>
            </div>)
   })

输入:

arr = [ 52, 68, 34, 60, 60, 42, 72, 70, 76, 52, 53, 51, 62, 47, 73, 44, 30, 0, 27, 25, 45, 40, 39, 12, 33, 33, 41, 74, 10, 30, 48, 17, 21, 7, 29, 33, 32, 56, 79, 29, 36, 16, 79, 68, 44, 37, 34, 36, 4, 35, 59, 54, 2, 11, 56, 78, 25, 16, 9, 69, 39, 80, 48, 5, 34, 68, 68, 21, 48, 42, 75, 57, 8, 76, 20, 76, 59, 50, 3, 52, 13, 7, 19, 6, 20, 72, 76, 46, 23, 10, 43, 16, 50, 16, 15, 58, 63, 53, 11, 52, …]

输出(mergeSort 之后 div 高度的日志):

["0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "0vh", "1vh", "1vh", "1vh", "35vh", "35vh", "66vh", "70vh"]

问题是您试图按高度对 DOM 元素的数组进行排序,这是通过改变其样式中设置的高度来实现的。这会导致两个问题:

  1. Array.fromitems.slice 将创建新数组,但它们不会创建它们包含的 DOM 元素的副本。所以当你分配给一个元素的高度时,你正在改变 items 中其他地方的元素的高度。这可能是一个尚未排序的项目。
  2. 您正在使用 React。你应该让 React 控制 DOM:你告诉你的组件如何在给定状态下渲染它们自己,让 React 弄清楚如何改变 DOM.

但是,如果您将代码重点放在对 this.state.arr 中的数字列表进行排序,那么您的代码就可以工作。在您的 merge1 方法中,删除您的数组 items,将对 items 的任何引用替换为 this.state.arr 并删除对 .style.height 和 [=20 的所有使用=]:

merge1(l, mid, r) {
    let left = this.state.arr.slice(l, mid + 1)
    let right = this.state.arr.slice(mid + 1, r + 1)
    let I = 0
    let J = 0
    let k = 0
    let t = []
    
    while (I < left.length && J < right.length) {
        if (left[I] < right[J]) {
            t.push(left[I])
            this.state.arr[k + l] = left[I]
            I = I + 1
            k++
        } else {
            this.state.arr[k + l] = right[J]
            t.push(right[J])
            J = J + 1
            k++
        }
    }
    while (I < left.length) {
        this.state.arr[k + l] = left[I]
        k++
        t.push(left[I])
        I = I + 1
    }
    while (J < right.length) {
        this.state.arr[k + l] = right[J]
        t.push(right[J])
        J = J + 1
        k++
    }
    console.log(t)
}

您可能还想考虑使用比 IJklrt,并记录您的代码,以明确 mergeSort1merge1 中的参数 r 是 'inclusive',即它指向最后一个元素排序而不是第一个元素。