什么是归并排序??
归并排序的实现过程如图:
递归形式的代码如下所示:
#!/usr/bin/python
#coding: utf-8
def Merge_Sort(res):
if len(res) <= 1:
return res
num = len(res) // 2
left = Merge_Sort(res[ : num])
right = Merge_Sort(res[num : ])
return Merge(left, right)
def Merge(left, right):
l, r = 0, 0
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result.extend(left[l : ])
result.extend(right[r : ])
return result
if __name__ == "__main__":
result = [95, 45, 15, 78, 84, 51, 24, 12]
print Merge_Sort(result)
# result = [95, 45, 15, 78, 84, 51, 24, 12]
# print MergeSort(result)
归并排序在用递归实现的过程中,会产生很大的内存开销,可以通过迭代来实现归并排序,减小内存开销
归并排序的另一种实现方式:
对于一个给定的无序数组,把元素实行分组(其实就是在递归过程中的把列表每次平分的过程),开始的时候一个元素一组,然后每次扩大2倍,直到不能实行分组为止,循环结束。
假设分组的步长为i,n个元素,所以每一次分组以后分的组数为 n/i,每次取其中两组进行讨论,把这两组的元素从小到大排序。依次重复这个过程即可。
归并排序迭代实现的C++代码
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void Merge_Sort(int k[], int n)
{
// left_min 和 left_max 分别表示左边分组的最小值和最大值
// right_min 和 right_max 分别表示右边分组的最小值和最大值
int left_min, left_max, right_min, right_max;
// 开辟一个临时数组
int *temp = (int *)malloc(n * sizeof(int));
// i 为迭代的步长
for(int i = 1;i < n;i *= 2)
{
for(left_min = 0;left_min < n - i; left_min = right_max)
{
// 获取左边分组的最大值和最小值
right_min = left_max = left_min + i;
right_max = left_max + i;
// 每一次分组以后各个分组的元素个数可能和最后一个分组不相等,
// 所以要对最后一个分组进行讨论,防止越界
if(right_max > n)
right_max = n;
int next = 0; // 临时数组的下表
// 归并算法的两个分组元素的合并操作
while(left_min < left_max && right_min < right_max)
{
if(k[left_min] < k[right_min])
temp[next ++] = k[left_min ++];
else
temp[next ++] = k[right_min ++];
}
/*
注意:
当上面合并算法结束以后,可能会存在下面的两种情况
1. 左边的分组元素没有取完,右边的分组元素全部取完
此时,要把左边部分没有取到的元素全部后移,放到k数组的结尾
2. 右边的分组元素没有取完,左边的分组元素全部取完
此时, 不需要对没有取到的元素进行讨论,因为这些元素已经在 k 数组的结尾
*/
// 右边的数据取完了,此时 right_min = right_max
// 对上面注意事项中的 1 进行实现
while(left_min < left_max)
k[-- right_min] = k[-- left_max];
//把 temp 临时数组的元素重新放入 k 数组中
// 如果说上面的 while 语句没有执行的话,则证明是注意事项中 2 的这种情况,只需要把temp数组中
// 当前的元素赋值给k数组即可,k数组后面没有变化的元素就是最开始while循环中右边分组没有取完的元素
while(next > 0)
k[-- right_min] = temp[-- next];
}
}
}
int main()
{
int n = 10;
int a[11];
for(int i = 10;i >= 0;i --)
a[10 - i] = i;
printf("排序之前\n");
for(int i = 0;i < 10;i ++)
printf("%d ", a[i]);
printf("\n");
Merge_Sort(a, n);
printf("排序之后\n");
for(int i = 0;i < 10;i ++)
printf("%d ", a[i]);
printf("\n");
return 0;
}