1.归并排序
归并排序使用了分治和递归的思想,将具有n的元素的无序序列划分为n个每个含有一个元素的序列,再将n个有序序列采用二路归并等合并方法进行合并排序成一个有序的序列。
2.归并实现步骤
2.1.划分划分左半部分后,合并排序左半部分
2.1.1递归划分左半部分
如图:
从中间划分,之后再从左半部分划分,递归划分左边部分
...... 直至划分为一个子序列
2.1.2合并左半部分的子序列,后面同理
2.1.划分右半部分后,合并排序右半部分
同左半部分
3.代码实现
//归并排序,二路归并排序
void mergeSort(int arr[], int length) {
int* assistArr = (int*)malloc((length) * (sizeof(int)));
if (!assistArr) {
printf("内存分配失败!");
}
mSort(arr,assistArr, 0, length - 1);
free(assistArr);
}
void mSort(int arr[],int* assistArr, int low, int high) {
if (low < high) {
//选出中间点
int mid = (low + high) / 2;
//左递归划分
mSort(arr,assistArr, low, mid);
//右递归划分
mSort(arr,assistArr, mid + 1, high);
//子序列排序
merge(arr,assistArr, low, high, mid);
}
}
void merge(int arr[],int* assistArr , int low, int high, int mid) {
int i=0; //i指针用来标记low所指的位置
int j = 0; //j指针用来标识high指针所指的位置
int k = 0; //k指针用来标识原数组的位置
//将待排序的元素拷贝到辅助数组中
for ( i = low; i <= high; i++) {
assistArr[i] = arr[i];
}
//令 i 指针指向 low , j 指针指向 high ,k指向i
for ( i=low, j = mid+1, k = i; i <= mid && j <= high; k++) {
if (assistArr[i] <= assistArr[j]) { //将待排序的两个序列的首元素比较
arr[k] = assistArr[i++]; //选出小的直接插回原数组中,令指向小元素指针++
}
else {
arr[k] = assistArr[j++];
}
}
while (i <= mid) { //如果两个序列左边的元素个数多于右边的,直接将多的赋值回原数组(此时两个序列分别都是有序的,所以可以直接复制回去)
arr[k++] = assistArr[i++];
}
while (j <= high) { //右边元素多余左边的情况
arr[k++] = assistArr[j++];
}
}
4.测试
因为在排序两个相同的值有特殊处理,所以归并排序是一个稳定的算法。