# 归并排序
归并排序一般是将数组分成两部分,分别进行排序,然后将排好序的两部分合并在一起
# 基本思想
用递归的思想将数组分成两部分,分别进行排序,然后将排好序的两部分合并在一起
# 归并的实现
//举例说明两个有序数组的合并
// int arr=[12, 16, 24, 33, 45, 56, 60]
// int arr1=[7, 10, 21, 24, 37]
// int arr2=[] //用来存储合并后的数组
// 每次循环比较两个数组的第一个元素,将较小的元素放到新的数组中,然后将较小元素所在的数组的下标加1,继续比较,直到其中一个数组的元素全部放到新的数组中,然后将另一个数组的剩余元素全部放到新的数组中
// 举例说明
// 第一趟 12和7比较 7小 放到新的数组中 7所在的数组下标加1 得到 arr2=[7]
// 第二趟 12和10比较 10小 放到新的数组中 10所在的数组下标加1 得到 arr2=[7, 10]
// 第三趟 12和21比较 12小 放到新的数组中 12所在的数组下标加1 得到 arr2=[7, 10, 12]
// ...
//最后一趟将arr 或 arr1中剩余的元素全部放到arr2中
//代码实现
void merge(int *arr, int *arr1, int *arr2, int length, int length1) {
//i用来记录arr的下标,j用来记录arr1的下标,k用来记录arr2的下标
int i = 0, j = 0, k = 0;
//循环比较arr和arr1的元素,将较小的元素放到arr2中
int min=length<length1?length:length1;
for(int m=0;m<min;m++){
if(arr[i]<arr1[j]){
arr2[k++]=arr[i++];
}else{
arr2[k++]=arr1[j++];
}
}
while(i<length){
arr2[k++]=arr[i++];
}
while(j<length1){
arr2[k++]=arr1[j++];
}
}
# 归并排序的实现
int arr[] = {9, 1, 2, 5, 7, 4, 8, 6, 3, 5};
int *B = (int *) malloc(sizeof(int) * 10);
//一般采用递归的思想,将数组分成两部分,分别进行排序,然后将排好序的两部分合并在一起
//low 为数组的第一个元素 high为数组的最后一个元素 mid为数组的中间元素
void Merge(int A[], int low, int x, int high) {
int i, j, k;
// 将A中的数据复制到B中
for (k = low; k <= high; ++k) {
B[k] = A[k];
}
// 将B中的数据按照顺序复制到A中
for (i = low, j = mid + 1, k = i; i <= mid && j <= high; ++k) {
if (B[i] <= B[j]) {
A[k] = B[i++];
} else {
A[k] = B[j++];
}
}
// 将B中剩余的数据复制到A中
while (i <= mid) {
A[k++] = B[i++];
}
while (j <= high) {
A[k++] = B[j++];
}
}
void MergeSort(int 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, high);
}
}
# 算法分析
2路归并的树是一个倒立的二叉树
# 时间复杂度
归并的时间复杂度为O(n)
n个元素进行2路归并排序 需要log2n次
算法的时间复杂度为O(nlog2n)
# 空间复杂度
O(n) 用于辅助的数组长度为n
← 堆排序