合并排序在 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 元素的数组进行排序,这是通过改变其样式中设置的高度来实现的。这会导致两个问题:
Array.from
和 items.slice
将创建新数组,但它们不会创建它们包含的 DOM 元素的副本。所以当你分配给一个元素的高度时,你正在改变 items
中其他地方的元素的高度。这可能是一个尚未排序的项目。
- 您正在使用 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)
}
您可能还想考虑使用比 I
、J
、k
、l
、r
或 t
,并记录您的代码,以明确 mergeSort1
和 merge1
中的参数 r
是 'inclusive',即它指向最后一个元素排序而不是第一个元素。
我已经调试这段代码好几个小时了,但没有弄错。 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 元素的数组进行排序,这是通过改变其样式中设置的高度来实现的。这会导致两个问题:
Array.from
和items.slice
将创建新数组,但它们不会创建它们包含的 DOM 元素的副本。所以当你分配给一个元素的高度时,你正在改变items
中其他地方的元素的高度。这可能是一个尚未排序的项目。- 您正在使用 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)
}
您可能还想考虑使用比 I
、J
、k
、l
、r
或 t
,并记录您的代码,以明确 mergeSort1
和 merge1
中的参数 r
是 'inclusive',即它指向最后一个元素排序而不是第一个元素。