归并排序算法
在排序算法中快速排序的效率是非常高的,但是还有种排序算法的效率可以与之媲美,那就是归并排序;归并排序和快速排序有那么点异曲同工之妙,快速排序:是先把数组粗略的排序成两个子数组,然后递归再粗略分两个子数组,直到子数组里面只有一个元素,那么就自然排好序了,可以总结为先排序再递归;归并排序:先什么都不管,把数组分为两个子数组,一直递归把数组划分为两个子数组,直到数组里只有一个元素,这时候才开始排序,让两个数组间排好序,依次按照递归的返回来把两个数组进行排好序,到最后就可以把整个数组排好序;
归并排序时的时间复杂度为O(nlgn) 其主要思想是分治法(divide and conquer),分就是要将n个元素的序列划分为两个序列,再将两个序列划分为4个序列,直到每个序列只有一个元素,最后,再将两个有序序列归并成一个有序的序列。例如两个序列:
要归并成一个有序的序列,按照我们常规的方法,我们每次从两个列表开头元素选取较小的一个,直到某一个列表到达底部,再将另一个剩下部分顺序取出。其实如果将每个元素最后添加一个最大值,则无需判断是否达到列表尽头。
算法的理解其实可以借助下面这个图:
对于原始的数组2,1,3,8,5,7,6,4,10,在整个过程执行的是顺序是途中红色编号1-20。虽然我们描述中说的是程序先分解,再归并,但实际过程是一边分解一边归并,前半部分分先排好序,后半部分再拍好,最后整个归并为一个完整的序列,途中的merge过程它所在层的两个序列的merge过程:下图展示了每个merge过程对作用于数组的哪部分(红色)。
整个过程就像一个动态的树,执行顺序就是对树的先序遍历顺序。
#include <iostream>
using namespace std;
#define LEN 12
int *tmp = new int[LEN]; //注意tmp数组从递归开始至递归结束都是同一个数组,所以只能设置成全局变量,如果在函数内设置则会错误
// 打印数组
void print_array(int *array)
{
int index = 0;
printf("\narray:\n");
for (; index < 12; index++){
printf(" %d, ", *(array + index));
}
printf("\n");
}
// 把两个有序的数组排序成一个数组
void mergeSortArray(int array[],int start,int mid,int end)
{
int startFirst = start;
int startLast = mid;
int endFirst = mid + 1;
int endLast = end;
//int len = end - start + 1; //注意tmp数组从递归开始至递归结束都是同一个数组,所以只能设置成全局变量,如果在函数内设置则会错误
//int tmp[len] = {};
int index = start;
while((startFirst <= startLast) && (endFirst <= endLast))
{
if(array[startFirst] <= array[endFirst])
tmp[index++] = array[startFirst++];
else
tmp[index++] = array[endFirst++];
}
while(startFirst <= startLast)
{
tmp[index++] = array[startFirst++];
}
while(endFirst <= endLast)
{
tmp[index++] = array[endFirst++];
}
for(startFirst = start; startFirst <= end; startFirst++)
{
array[startFirst] = tmp[startFirst];
}
}
void mergeSort(int array[], int start, int end)
{
if(start < end)
{
int mid = (start + end) / 2;
mergeSort(array,start,mid);
mergeSort(array,mid+1,end);
mergeSortArray(array,start,mid,end);
}
}
int main(void)
{
int array[LEN] = {2, 1, 4, 0, 12, 520, 2, 9, 5, 3, 13, 14};
print_array(array);
mergeSort(array, 0, LEN - 1);
print_array(array);
return 0;
}