归并排序的原理网上很多,基本思路是用二分法的思想将整个数列分到直至2位的最小子序列,当然当整个数列总数是奇数时会出现单独一个元素,此种情况在有些人给的代码中并不能达到效果,作为初学者,还是花了一点时间写了一下,测试几个数列后还是可以的,因此记录一下。
递归实现
二分法最容易想到的实现方式就是递归,递归就是自己调用自己,要求各子过程的实现具有相似的实现方法;递归是有去有回,因此只需要考虑如何将问题划分到更小的子过程,实现方式在划分后实施,就可以实现问题到更小的规模,然后计算过程从更小的子过程到整个过程。
对于归并排序的递归实现,我们可以用一个图来表示。
需要注意的是归并排序排序的实施是从左序列的头部与右序列的头部进行比较,较小的值添加入新的序列,然后依次进行这样的比较,直到两个序列为空。
在网上找了一个十分经典的代码,在进行排序处理时非常快捷,代码也比较优雅,count是我自己加的实现次数,实现代码如下:
void sortByArr(int arr[], int temp[], int start, int end, int& count) {
if (end - start <= 0) return;
int mid = (start + end) / 2;
int startL = start, endL = mid;
int startR = mid + 1, endR = end;
count++;
sortByArr(arr, temp, startL, endL, count);
sortByArr(arr, temp, startR, endR, count);
int k = start;
while (startL <= endL && startR <= endR)
temp[k++] = arr[startL] < arr[startR] ? arr[startL++] : arr[startR++];
while (startL <= endL)
temp[k++] = arr[startL++];
while (startR <= endR)
temp[k++] = arr[startR++];
for (int i = start; i <= end; i++)
arr[i] = temp[i];
}
void Sort(int arr[], int len) {
int *temp = new int[len];
int count = 0;
sortByArr(arr, temp, 0, len - 1, count);
cout << "loop count = " << count << endl;
}
迭代实现
网上对于递归实现都很经典,但是迭代实现却有的有问题,迭代实现与递归实现不同,迭代是有去无回,所以对于迭代,我们要从最小的子序列开始实现,逐步到原始序列。迭代的实现过程如下图所示。
我们设置step = 1,这样每次进行step个元素与step个元素的排序。例如第一次step = 1,进行第1个元素与第2个元素的排序,依次进行。进行第二次迭代的时候序列增加一倍,依次进行。需要注意的是进行排序的中间值设置,
因为每次进行运算,数列要完全传承上一次的运算结果,当左序列与右序列数目不等时,中间值不能设置为总数/2,要设置为 mid = start + step - 1,这样可以保证序列的完整。
void Sort(int arr[], int len) {
int *temp = new int[len];
int step = 1;
int count = 0;
while (step <= len) {
for (int i = 0; i < len; i += 2 * step) {
int start = i;
int end = start + 2 * step - 1 < len - 1 ? start + 2 * step - 1 : len - 1; //防止溢出
int mid = start + step - 1 < len - 1 ? start + step - 1: len - 1;
int startL = start, endL = mid;
int startR = mid + 1, endR = end;
int k = start;
while (startL <= endL && startR <= endR)
temp[k++] = arr[startL] < arr[startR] ? arr[startL++] : arr[startR++];
while (startL <= endL)
temp[k++] = arr[startL++];
while (startR <= endR)
temp[k++] = arr[startR++];
count++;
for (int i = start; i <= end; i++) {
arr[i] = temp[i];
//cout << arr[i] << " ";
}
//cout << endl;
}
step *= 2;
}
cout << "loop count = " << count << endl;
delete[]temp;
}
下面给出一个网上的实现过程
void Sort(int arr[], int len) {
int * a = arr;
int * b = (int*)malloc(len * sizeof(int));
int count = 0;
int seg, start;
for (seg = 1; seg < len; seg += seg) {
for (start = 0; start < len; start += seg + seg) {
int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
int k = low;
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
while (start1 < end1)
b[k++] = a[start1++];
while (start2 < end2)
b[k++] = a[start2++];
count++;
/*
for (int i = low; i < high; i++)
cout << b[i] << " ";
cout << endl;*/
}
int *temp = a;
a = b;
b = temp;
}
if (a != arr) {
for (int i = 0; i < len; i++)
b[i] = a[i];
b = a;
}
cout << "loop count = " << count << endl;
free(b);
}