归并排序,又是一种新的排序。其时间复杂度 < O(n ^ 2)。
以前在链表里,我们已经学过,如何把两个有序表合并成一个总的有序表。
在归并排序里,要给一个大表排序,我们就采用了这样的思路:先把表分成两部分分别排好序,再把这两个有序的子表合并在一块。当然这个定义是递归的。当表里只有一个元素时,才不必进行拆分。
归并排序,也可以不用递归的方法。我们直接把表划分成一堆只有一个元素的子表,再对子表进行两两合并,使所有子表都含有两个元素,再对子表进行两两合并,使子表具有4个元素,依次类推,直到合并完后只剩下一个表,至此,排序完毕。
在非递归合并中,若子表数量是奇数,则剩余最后一个子表不参与合并,若子表数量是偶数,但最后一个子表的元素数目不够,依然要对最后两个子表合并。目的是要保证新的一趟合并开始前,所有子表都依然是有序的。
当表的元素数目不是 2 的幂数,则表最终被合并到只剩下两个子表时,俩子表长度是不相等的,这时候需要单独对这俩子表进行一次合并。
b站的归并排序讲解很好。比课本好懂。
下面是全部代码,包括递归和非递归:
#include<iostream>
#include<stdlib.h>
using namespace std;
void dispaly(int array[],int length) {
for (int i = 0; i < length; i++)
cout << array[i] << ' ';
cout << endl;
}
void merge(int array[],int arrayTemp[],int start,int mid,int end) {
int i = start, j = mid + 1, indexTemp = start;
while (i <= mid && j <= end)
if (array[i] <= array[j])
arrayTemp[indexTemp++] = array[i++];
else
arrayTemp[indexTemp++] = array[j++];
if (i <= mid)
while (indexTemp <= end)
arrayTemp[indexTemp++] = array[i++];
if (j <= end)
while (indexTemp <= end)
arrayTemp[indexTemp++] = array[j++];
for (i = start; i <= end; i++)
array[i] = arrayTemp[i];
}
void sort(int array[],int arrayTemp[],int start,int end) {
if (start == end)
return;
int mid = (start + end) / 2;
sort(array,arrayTemp,start,mid);
sort(array,arrayTemp,mid + 1,end);
merge(array,arrayTemp,start,mid,end);
}
void mergeSort(int array[],int length) {
int* arrayTemp = (int*)malloc(length * sizeof(int));
if (arrayTemp != NULL) {
sort(array, arrayTemp, 0, length - 1);
free(arrayTemp);
}
else
cout << "fail to allocate memory !" << endl;
}
void mergeSortNoRecursion(int array[],int length) {
int* arrayTemp = (int*)malloc(length * sizeof(int));
if (arrayTemp == NULL) {
cout << "fail to allocate memory !" << endl;
return;
}
int arrayLength;
int start, mid, end;
for (arrayLength = 1; arrayLength <= length / 2; arrayLength *= 2) {
for (start = 0; start + arrayLength * 2 <= length; start = end + 1) {
mid = start + arrayLength - 1;
end = start + 2 * arrayLength - 1;
merge(array, arrayTemp, start,mid ,end);
}
if (start + arrayLength < length)
merge(array,arrayTemp,start,start + arrayLength - 1,length - 1);
}
if (arrayLength != length)
merge(array,arrayTemp,0,arrayLength - 1,length - 1);
free(arrayTemp);
}
int main() {
int array[] = {2,9,0,6,3,4,8,7,1,5};
int const length = 10;
mergeSort(array,length);
// mergeSortNoRecursion(array,length);
dispaly(array,length);
return 0;
}
测试结果当然是正确的。
谢谢阅读