归并排序的递归算法代码虽然简单,但是递归函数每一次调用自身都会开辟一个栈空间,使它的空间复杂度增加。而非递归算法不会因为函数嵌套次数太多造成栈溢出。
递归算法是通过递归最后分成两个数一组进行排序,非递归是直接把两个数一组进行排序,再分成四个数一组排序,最后把数组分成两组,结束。
非递归算法原理
例如
2 1 5 7 4 3
非递归的思路有点类似希尔排序中的消除逆序对。
假设我们需排序的数字存在数组res[],让dlta=1(dlta是左部分和右部分的元素个数 即子序列长度为2*dlt=2)先用i记录2的下标,消除逆序对2和1后;再移动到5,消除逆序对5和7;再移动到4,消除逆序对4和3;再回到res[0],此时dlta=2(即子序列长度为4),消除2 1 5 7中的逆序对,再移动到4,消除 7 2中的逆序对;再回到a[0],直到dlta>=数组长度,结束。
具体代码
void Mergesort(int res[], int left, int right,int n)//n是要排序的数组长度
{
int t[n];//创立临时数组
int dlta = 1;//希尔排序中dlta是增量 这里是左部分和右部分的元素个数 即子序列长度为2*dlta
while (dlta < n)
{
//排序数组 2 1 5 7 4 3
for (int i = 0; i <= right; i = i + 2 * dlta)
//例如dlta=1,即要先排2 1两个数,i=0,i<right,i=0+2*1=2 即下一个子序列的首元素下标是2
{
//将子序列分成左右两部分
int start1 = i, end1 = i + dlta - 1, mid = i + dlta - 1;
int start2 = mid + 1, end2 = i + 2 * dlta - 1;
int j = i;
if (start2 > right) break;
if (end2 > right) end2 = right;
while (start1 <= end1 && start2 <= end2)//下面与归并排序的递归算法相同
{
if (res[start1] < res[start2]) t[j++] = res[start1++];
else t[j++] = res[start2++];//把最小的先放到临时数组再移动下标
}
while (start1 <= end1)
{
t[j++] = res[start1++];
}
while (start2 <= end2)
{
t[j++] = res[start2++];
}
for (int j = i; j <= end2; j++)//再把临时数组t的元素存回到res[]
{
res[j] = t[j];
}
}
dlta = 2 * dlta;
}
}