英文:
Trouble finding bug in the merge sort algorithm implemented in Go
问题
我想实现一个归并排序算法,但是在找出程序为什么无法正确排序方面遇到了困难。我尝试向ChatGPT寻求一些建议,但它无法帮助找出错误所在。
package main
import (
"fmt"
"sort"
)
// sortable是必须由类型实现的接口,以便通过归并排序进行排序。
type sortable interface {
sort.Interface
Set(i int, x any)
At(i int) any
}
// IntSlice将sortable的方法附加到[]int,以升序排序。
type IntSlice []int
func (x IntSlice) Len() int { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] <= x[j] } // 实际上表示`<=`运算符
func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x IntSlice) Set(i int, a any) { x[i] = a.(int) }
func (x IntSlice) At(i int) any { return x[i] }
// 将两个数组合并为一个
func merge(data sortable, lo, mid, hi int) {
temp := make([]any, hi-lo+1)
for i := lo; i <= hi; i++ {
temp[i-lo] = data.At(i)
}
i, j := lo, mid+1
for k := lo; k <= hi; k++ {
if i > mid {
data.Set(k, temp[j-lo])
j++
} else if j > hi {
data.Set(k, temp[i-lo])
i++
} else if data.Less(i, j) { // 实际上表示`<=`运算符
data.Set(k, temp[i-lo])
i++
} else {
data.Set(k, temp[j-lo])
j++
}
}
}
// 递归解决方法
func mergeSort(data sortable, lo, hi int) {
if hi-lo > 1 {
mid := (lo + hi) / 2
mergeSort(data, lo, mid)
mergeSort(data, mid+1, hi)
merge(data, lo, mid, hi)
} else {
if !data.Less(lo, hi) { // 实际上表示`>`运算符
data.Swap(lo, hi)
}
}
}
func SortTtE(data sortable) {
mergeSort(data, 0, data.Len()-1)
}
func main() {
a := []int{10, 9, 11, 2, 7, 9, 6}
SortTtE(IntSlice(a))
fmt.Println(a)
// 错误的输出: [2 6 9 7 10 11 9]
}
可能是因为我在控制流程中犯了错误,所以我希望有人能帮助我找出错误所在。
这是playground的链接: https://go.dev/play/p/AXZqZH2Ko1E
英文:
I want to implement a merge sort algorithm but was stuck in finding why my program fails to do the right sorting. I had tried to ask ChatGPT for some suggestions on it, but it couldn't help find where the bug is.
package main
import (
"fmt"
"sort"
)
// sortable is the interface that must be implemented by a type to be sorted by the merge sort.
type sortable interface {
sort.Interface
Set(i int, x any)
At(i int) any
}
// IntSlice attaches the methods of sortable to []int, sorting in increasing order.
type IntSlice []int
func (x IntSlice) Len() int { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] <= x[j] } // actually represents the `<=` operator
func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x IntSlice) Set(i int, a any) { x[i] = a.(int) }
func (x IntSlice) At(i int) any { return x[i] }
// merge two arrays into one
func merge(data sortable, lo, mid, hi int) {
temp := make([]any, hi-lo+1)
for i := lo; i <= hi; i++ {
temp[i-lo] = data.At(i)
}
i, j := lo, mid+1
for k := lo; k <= hi; k++ {
if i > mid {
data.Set(k, temp[j-lo])
j++
} else if j > hi {
data.Set(k, temp[i-lo])
i++
} else if data.Less(i, j) { // actually represents the `<=` operator
data.Set(k, temp[i-lo])
i++
} else {
data.Set(k, temp[j-lo])
j++
}
}
}
// recursive solving method
func mergeSort(data sortable, lo, hi int) {
if hi-lo > 1 {
mid := (lo + hi) / 2
mergeSort(data, lo, mid)
mergeSort(data, mid+1, hi)
merge(data, lo, mid, hi)
} else {
if !data.Less(lo, hi) { // actually represents the `>` operator
data.Swap(lo, hi)
}
}
}
func SortTtE(data sortable) {
mergeSort(data, 0, data.Len()-1)
}
func main() {
a := []int{10, 9, 11, 2, 7, 9, 6}
SortTtE(IntSlice(a))
fmt.Println(a)
// the false output: [2 6 9 7 10 11 9]
}
It might because I made mistakes in my control flow, so I was expecting someone to help me find where the bug is.
This is where the playground is: https://go.dev/play/p/AXZqZH2Ko1E
答案1
得分: 1
在merge
函数中,你在检查data.Less
的同时修改了数组data
,这会导致一个未定义的状态,因为此时你的实际数据存储在temp
中。
为了解决这个问题,应该在temp
上进行检查。
func merge(data sortable, lo, mid, hi int) {
temp := make([]int, hi-lo+1)
for i := lo; i <= hi; i++ {
// 注意,我在这里必须进行类型转换,因为temp是[]int类型,
// 而data是一个接口
temp[i-lo] = data.At(i).(int)
}
i, j := lo, mid+1
for k := lo; k <= hi; k++ {
if i > mid {
data.Set(k, temp[j-lo])
j++
} else if j > hi {
data.Set(k, temp[i-lo])
i++
} else if temp[i-lo] <= temp[j-lo] { // <- 在这里,对实际数据进行检查
data.Set(k, temp[i-lo])
i++
} else {
data.Set(k, temp[j-lo])
j++
}
}
}
英文:
In merge
, you are modifying the array data
at the same time you are checking for data.Less
. This leads to an undefined state, because your actual data is stored in temp
at that moment.
To fix this, perform the check on temp
func merge(data sortable, lo, mid, hi int) {
temp := make([]int, hi-lo+1)
for i := lo; i <= hi; i++ {
// Notice I have to cast here, because temp it []int,
// but data is an interface
temp[i-lo] = data.At(i).(int)
}
i, j := lo, mid+1
for k := lo; k <= hi; k++ {
if i > mid {
data.Set(k, temp[j-lo])
j++
} else if j > hi {
data.Set(k, temp[i-lo])
i++
} else if temp[i-lo] <= temp[j-lo] { // <- here, check against the actual data
data.Set(k, temp[i-lo])
i++
} else {
data.Set(k, temp[j-lo])
j++
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论