最基础的实现。 自顶向下归并。 最开始一次性分配和待排序数组大小相同的临时内存。
// 入口
func MergeSort(arr []int) {
l := len(arr)
if l < 2 {
return
}
seg := 1
temp := make([]int, l)
for seg < l {
mergePass(arr, temp, seg)
seg <<= 1
mergePass(temp, arr, seg)
seg <<= 1
}
}
// 一趟整体合并
func mergePass(src, dst []int, seg int) {
l := len(src)
// 计算有多少对相邻的seg长度的区间
c := (l/seg)>>1
var b int
for i := 0; i < c; i++ {
e := b+seg+seg-1 // 相邻两个seg长度的区间的结束位置(含)
merge(src, dst, b, e, seg)
b = e+1 // 后面两个区间的开始位置(含)
}
rest := l - (c<<1)*seg // 计算还剩下多少个元素没处理
if rest > seg { // 还有两个区间没处理,一个长度seg,一个长度小于seg
merge(src, dst, b, l-1, seg)
} else { // 剩下的元素数不足seg
for i := b; i < l; i++ {
dst[i] = src[i]
}
}
}
// 合并相邻的两个区间
func merge(src, dst []int, b, e, seg int) {
var (
i = b
j = b+seg
ie = j-1
k = b
)
// 合并
for i <= ie && j <= e {
if src[i] <= src[j] {
dst[k] = src[i]
i++
} else {
dst[k] = src[j]
j++
}
k++
}
// 处理剩余部分
for i <= ie {
dst[k] = src[i]
i++
k++
}
// 处理剩余部分
for j <= e {
dst[k] = src[j]
j++
k++
}
}