归并排序
1.排序规则
首先将所有数据默认每个数字单独一个组,接下来两两合并(两个组),当所有数据在一个组内,则排序停止
原始数据: 84 9 18 19 48 12 90 84 8 12
第一次两两合并(2-2): 9 84 18 19 12 48 84 90 8 12 (这里的两两合并指的是两个组合并)
第二次两两合并(4-4): 9 18 19 84 12 48 84 90 8 12
第三次两两合并(8-8): 9 12 18 19 48 84 84 90 8 12
第四次两两合并: 8 9 12 12 18 19 48 84 84 90
二路归并排序:稳定性:稳定
2.代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//一次融合函数 时间复杂度O(n) 空间复杂度O(n)
void Merge(int arr[] , int len, int gap)
{
int low1 = 0;
int high1 = low1 + gap - 1;
int low2 = high1 + 1;
int high2 = low2 + gap - 1 < len ? low2 + gap - 1 : len - 1;
int* brr = (int*) malloc(len * sizeof(int));
assert(brr != NULL);
int i = 0;//i指向辅助空间brr的下标
while (low2 < len)
{
while (low1 <= high1 && low2 <= high2)//保证两个数组都有数据拿来比较
{
if (arr[low1] <= arr[low2])
{
brr[i++] = arr[low1++];
}
else
{
brr[i++]= arr[low2++];
}
}
//里层的while循环结束之后,肯定有一个组是为空的,需要判断一下是左边的组还是右边的组,做对应的出来
while (low1 <= high1)//左边组的数据没空,此时左边数组中的数据向brr中移动
{
brr[i++] = arr[low1++];
}
while (low2 <= high2)//左边组的数据没空,此时左边数组中的数据向brr中移动
{
brr[i++] = arr[low2++];
}
//此时应该,继续向后抓两个组
low1 = high2 + 1;
high1 = low1 + gap - 1;
low2 = high1 + 1;
high2 = low2 + gap - 1 < len ? low2 + gap - 1 : len - 1;
}
//此时最外层while退出,有两种可能性:1.左边数组有数据,右边空了 2.左右都空了
while (low1 < len) //左边数组还有数据,此时将左边数据向brr移动
//不要写成low1<=high1 因为这里没有办法保证high1的合法性
{
brr[i++] = arr[low1++];
}
//最后将brr中的数据全部覆盖到arr里
for (int i = 0; i < len; i++)
{
arr[i] = brr[i];
}
free(brr);
}
//二路归并排序 时间复杂度O(nlogn) 空间复杂度O(n) 稳定性:稳定
void MergeSort(int *arr, int len)
{
for (int i = 1; i < len; i *= 2)//时间复杂度O(logn)
{
Merge(arr, len, i);
}
}
int main()
{
int arr[] = { 12,2,39,88,4,6,25,232,62,221 };
MergeSort(arr, sizeof(arr) / sizeof(arr[0]));
Show(arr, sizeof(arr) / sizeof(arr[0]));
return 0;
}
3.测试结果
4.复杂度分析
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定