算法整理——非递归归并排序

时间:2022-08-12 04:14:15

       递归是个好东西,可以将一个大问题分拆成多个小问题。只要处理好每一个小问题、以及小问题合并成大问题的操作,基本就算是完成了,而程序需要写解决小问题的代码即可。但递归有时候也会有缺陷,如果递归层数控制不好、或者递归过程中生成了大量变量,容易造成栈溢出。尤其在工程中,栈溢出的问题是需要极力避免的。

      常用的归并排序是使用递归的方式,将排序序列一层一层拆分成一半,完成一层的排序后再回调给上一层处理。

      其实归并排序也可以使用非递归的方式,大概的流程如下:

1.循环,划分每一个片区,每一个片区从1开始;

2.将相邻的两个片区按照归并排序的方法放进buffer;

3.将从buffer复制进原片区的位置;

4.返回2直到所有片区合并完;

5.返回1,片区增大至2倍,直到片区大于数组长度。

/**
* param
* arr:数组头指针, len数组长度
*
*/
void merge_sort(int* arr, int len){

int * buff = new int[len]; //buffer空间

//片区的大小
for(int i = 1 ; i < len ; i *= 2){
//排序合并两个区
for(int j = 0 , k = i ; k < len ; j += 2*i, k += 2*i ){
int buffIndex = 0 ; //buffer 的index

//合并
for(int m = j , n = k ; ; ){
if(arr[m] <= arr[n]){
buff[buffIndex++] = arr[m++];

if(m >= k){ // 后半区copy
while(n < k + i && n < len){
buff[buffIndex++] = arr[n++];
}
break;
}
}else{
buff[buffIndex++] = arr[n++];

if(n >= k+i || n >= len){ //前半区copy
while(m < k ){
buff[buffIndex++] = arr[m++];
}
break;
}
}
}

//从buffer区copy到数组
for(int l = 0 ; l < 2*i && j + l < len; l++){
arr[j+l] = buff[l];
}
}
}
delete [] buff;
}