What is wrong with the following merge sort algorithm?

huangapple go评论96阅读模式
英文:

What is wrong with the following merge sort algorithm?

问题

根据问题描述,我在以下算法中找不到问题所在。这是mergesort的辅助函数,即用于合并排序数组的函数。

func Merge(toSort *[]int, p, q, r int) {
    arr := *toSort
    L := arr[p:q]
    R := arr[q:r+1]
    fmt.Println(L)
    fmt.Println(R)
    i := 0
    j := 0
    
    for index := p; index <= r; index++ {
        if i >= len(L) {
            arr[index] = R[j]
            j += 1
            continue
        } else if j >= len(R) {
            arr[index] = L[i]
            i += 1
            continue
        }
        
        if L[i] > R[j] {
            fmt.Println("right smaller")
            arr[index] = R[j]
            j += 1
            continue
        }
        if L[i] <= R[j] {
            fmt.Println("left smaller")
            arr[index] = L[i]
            i += 1
            continue
        }
        
    }

}

对于arr := []int{1,7,14,15,44,65,79,2,3,6,55,70},它的输出是[1 2 2 2 2 2 2 2 3 6 55 70]

这是问题的Go Playground链接

这个函数的JavaScript等效版本按预期工作,但我不知道为什么它在Go中不起作用。

谢谢

英文:

As the question states, I'm having trouble finding where is the issue within the following algorithm. It is the aux function for mergesort, i.e. the one used for combining sorted arrays.

func Merge(toSort *[]int, p, q, r int) {
	arr := *toSort
	L := arr[p:q]
	R := arr[q:r+1]
	fmt.Println(L)
	fmt.Println(R)
	i := 0
	j := 0
	
	for index := p; index &lt;= r; index++ {
		if i &gt;= len(L) {
			arr[index] = R[j]
			j += 1
			continue
		} else if j &gt;= len(R) {
			arr[index] = L[i]
			i += 1
			continue
		}
		
		if L[i] &gt; R[j] {
			fmt.Println(&quot;right smaller&quot;)
			arr[index] = R[j]
			j += 1
			continue
		}
		if L[i] &lt;= R[j] {
			fmt.Println(&quot;left smaller&quot;)
			arr[index] = L[i]
			i += 1
			continue
		}
		
	}

}

For arr := []int{1,7,14,15,44,65,79,2,3,6,55,70} it gives as output [1 2 2 2 2 2 2 2 3 6 55 70].

Golang Play link

The JavaScript equivalent for this function works as expected, but I don't know why it isn't working in Go

Thank you

答案1

得分: 2

Golang切片是通过引用传递的。因此,你不需要在函数中传递指针,但是你需要显式地复制LR,否则会合并到一个完全不同的切片中。你目前正在写入从中获取值的相同底层内存。

英文:

Golang slices are passed by reference. So you don't need to pass a pointer into the function in the first place, but you do need to take explicit copies of L and R or else merge into a different slice entirely. You are currently writing into the same underlying memory from which you are getting your values.

答案2

得分: 1

代码像 L := arr[p:q] 这样的形式不会创建副本。我猜想你在对 arr 进行赋值时覆盖了 L 和 R 部分。请查看 http://blog.golang.org/slices 了解切片的工作原理(例如,你基本上不会将 toSort *[]int 这样的东西写成 []int,因为 []int 几乎就像是指针)。

这个链接似乎可以解决问题:http://play.golang.org/p/vPo2ZKXtI9

英文:

Code like L := arr[p:q] does not create a copy. I suppose you are overwriting your L and R parts during the assignments to arr. Have a look at http://blog.golang.org/slices to understand how slices work. (E.g. you'll basically never write stuff like toSort *[]int as []int is almost kinda pointer)

This seems to work: http://play.golang.org/p/vPo2ZKXtI9

答案3

得分: 1

你不需要所有的索引:切片已经是数组的视图。下面是一个完整的示例,仅使用切片操作:

package main

import "fmt"

// Merge将两个已排序的递增切片合并成一个已排序的递增切片。
func Merge(a, b []int) []int {
    res := make([]int, 0, len(a)+len(b))
    for len(a) > 0 || len(b) > 0 {
        if len(b) == 0 || len(a) > 0 && a[0] <= b[0] {
            res = append(res, a[0])
            a = a[1:]
        } else {
            res = append(res, b[0])
            b = b[1:]
        }
    }
    return res
}

func main() {
    a := []int{1, 2, 5, 6, 3, 4, 7, 9}
    fmt.Println(Merge(a[:4], a[4:]))
}

这段代码演示了如何使用切片操作来合并两个已排序的递增切片。函数Merge接受两个切片参数ab,并返回一个合并后的已排序递增切片。在Merge函数中,我们使用了切片操作a[:4]a[4:]来将切片a分成两部分。然后,我们调用Merge函数将这两部分切片合并起来,并打印结果。

英文:

You don't need all the indexes: slices are already views into an array. Here's a complete example using purely slice manipulation:

package main

import &quot;fmt&quot;

// Merge takes two sorted, increasing slices of ints and
// returns a slice combining them into a single sorted, increasing
// slice.
func Merge(a, b []int) []int {
	res := make([]int, 0, len(a)+len(b))
	for len(a) &gt; 0 || len(b) &gt; 0 {
		if len(b) == 0 || len(a) &gt; 0 &amp;&amp; a[0] &lt;= b[0] {
			res = append(res, a[0])
			a = a[1:]
		} else {
			res = append(res, b[0])
			b = b[1:]
		}
	}
	return res
}

func main() {
	a := []int{1, 2, 5, 6, 3, 4, 7, 9}
	fmt.Println(Merge(a[:4], a[4:]))
}

huangapple
  • 本文由 发表于 2014年3月28日 08:49:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/22702187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定