归并排序基础实现

110 阅读1分钟

最基础的实现。 自顶向下归并。 最开始一次性分配和待排序数组大小相同的临时内存。

// 入口
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++
    }
}