归并排序原理
归并排序建立在归并操作上的一种有效,稳定的排序算法,是采用分治法的一个非常典型的应用。将集合数据拆分成若干个子序列,并使各个子序列有序,依次合并,并进行排序,直到合并为整个数据集合有序。(此处应该有图,但是画图耗时间,先不画了,以后有空再来补。)
归并排序(递归版)实现(升序排列)
归并排序时间复杂度O(nlog n),性能仅低于快速排序。性能比希尔排序更好。根据归并排序原理,每经过合并才做,集合数据都会更接近有序,直到所有子序列合并成一个集合,整个集合数据将会有序。归并排序的过程,很适合使用递归的方式来实现,使用递归实现的缺点为,当数据量太大时,递归层数会过多,可能导致栈溢出,同时,由于往栈中压入和弹出数据也都需要时间,所以降低了效率。代码实现如下:
/*
*@功能说明
* 排序合并数据
*@参数 int * arrLeft <#数组左半部分#>
*@参数 int leftSize <#左半部分长度#>
*@参数 int * arrRight <#数组右半部分#>
*@参数 int rightSize <#右半部分长度#>
*@返回值 <#void#>
*/
void mergeData( int * arrLeft, int leftSize, int * arrRight, int rightSize)
{
int i = 0 , j = 0,idx = 0;
/*此处malloc可以优化,在函数递归之前,分配好跟数据集合大小一样的空间,通过参数传递进来,不用每次合并都重新malloc空间,浪费时间*/
int * tmp = (int *)malloc(sizeof(int) * (leftSize + rightSize));
if(NULL == tmp){
printf("=====> malloc error\n");
return;
}
while(i < leftSize && j < rightSize){
if(arrLeft[i] < arrRight[j]){
tmp[idx++] = arrLeft[i++];
}else{
tmp[idx++] = arrRight[j++];
}
}
while(i < leftSize){
tmp[idx++] = arrLeft[i++];
}
while(j < rightSize){
tmp[idx++] = arrRight[j++];
}
for( i = 0 ; i < idx;i++){
arrLeft[i] = tmp[i];
}
free(tmp);
}
/*
*@功能说明
* 归并排序,递归版本
*@参数 int * array <#待排序数组#>
*@参数 int len <#待排序数组长度#>
*@返回值 <#void#>
*/
void mergeSort(int * array, int len)
{
if(len > 1){
mergeSort(array,(len >> 1));
mergeSort(array + (len >> 1), len - (len >> 1));
mergeData(array,(len >> 1),array + (len >> 1), len - (len >> 1));
}
}
归并排序(迭代版)实现(升序排列)
/*
*@功能说明
* 归并排序,迭代版本
*@参数 int * array <#待排序数组#>
*@参数 int len <#待排序数组长度#>
*@返回值 <#void#>
*/
void mergeSort2(int * array, int len)
{
int i = 0, leftMin = 0 , leftMax = 0, rightMin = 0, rightMax = 0,idx = 0;
int * tmp = (int *) malloc(sizeof(int) * len);
if(NULL == tmp){
printf("=======> malloc error\n");
return ;
}
for( i = 1 ; i < len ; i = (i << 1)){
for(leftMin = 0 ; leftMin < len - i ; leftMin = rightMax){
rightMin = leftMax = (leftMin + i > len ) ? len : (leftMin + i);
rightMax = rightMin + i > len ? len : rightMin + i;
idx = 0;
while(leftMin < leftMax && rightMin < rightMax ){
array[leftMin] < array[rightMin] ? (tmp[idx++] = array[leftMin++]) : (tmp[idx++] = array[rightMin++]);
}
while(leftMin < leftMax){
array[--rightMin] = array[--leftMax];
}
while(idx > 0){
array[--rightMin] = tmp[--idx];
}
}
}
}
总结
归并排序的递归版本比迭代版本容易实现,但是由于递归所存在的缺陷,推荐优先使用迭代版本的实现。