此处C语言参考王道书,此外结合Go语言,一起理解
“归并”的含义是将两个或者两个以上的有序表组合成一个新表,以下的例子都是二路归并为例子。
Go 归并排序
话不多少,先看Go语言版本的参考代码:
package main
import (
"fmt"
)
func main() {
s := []int{6, 7, 8, 10, 4, 6, 99}
res := mergeSort(s)
fmt.Println(res)
}
func mergeSort(s []int) []int {
len := len(s)
if len == 1 {
return s //最后切割只剩下一个元素
}
m := len / 2
leftS := mergeSort(s[:m])
rightS := mergeSort(s[m:])
return merge(leftS, rightS)
}
//把两个有序切片合并成一个有序切片
func merge(l []int, r []int) []int {
lLen := len(l)
rLen := len(r)
res := make([]int, 0)
lIndex, rIndex := 0, 0 //两个切片的下标,插入一个数据,下标加一
for lIndex < lLen && rIndex < rLen {
if l[lIndex] > r[rIndex] {
res = append(res, r[rIndex])
rIndex++
} else {
res = append(res, l[lIndex])
lIndex++
}
}
if lIndex < lLen { //左边的还有剩余元素
res = append(res, l[lIndex:]...)
}
if rIndex < rLen {
res = append(res, r[rIndex:]...)
}
return res
}
代码还是很容易理解的,接下来看C语言版的。
C语言版归并排序
C语言由于没有来计算数组长度很好的函数,一般要标定数组的起始与结束的下标。
已下参考王道书,
ElemType *B = (Elmetype *)malloc((n+1)*sizeof(Elemtype));// 辅助数组 空间复杂度:O(n)
// 合并左右子列
void Merge(Elemtype A[],int low,int mid,int high)
{ int k;
// 将数组B赋值
for (int i = low ;i <= high;i++)
B[i] = A[i];
// B的左右子列比较,覆盖对应的A的位置
for(int i = low,j = mid+1,k = i;i<=mid&&j<=high;k++)
{if(B[i] > B[j])
A[k] = B[j++];
else
A[k] = B[i++];
}
// 以上完成对于A的初步排序,若此时还有i或者j未到达最右端
while(i<=mid) A[k++] = B[i++];
while(j<=high) A[k++] = B[j++];
// 设置k是为了完善A的排序
}
// 递归深度logn,每趟的归并O(n),时间复杂度O(nlogn)
void MergeSort(Elemtype A[],int low,int high)
{
if(low < high)
{ int mid = (low+high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,hign); // 归并
}
}