单趟排序
归并排序单趟的原理是将两个有序的数组归并为一个有序的序列,通过开辟一个新的空间int * p,存储新的数据,再将p中的数据拷贝到原数组中。
void pastsort3(int* a, int begin1,int end1,int begin2 ,int end2,int*p) //确保m两个的区间[begin1,end1]和[begin2,end2]都是有序的,将两个连续的空间传过来( end1+1 = begin1 )
{
int left = begin1;
int right = begin2;
int Index = begin1;
while (left <=end1 && right <= end2)
{
if (a[left] > a[right]) // 将小的数放入p数组对应的[begin1,end2]区间中
{
p[Index++] = a[right++];
}
else
{
p[Index++] = a[left++];
}
}
while (right <= end2)
{
p[Index++] = a[right++];
}
while (left <= end1)
{
p[Index++] = a[left++];
}
//将p中区间[begin1,end2]的数据拷贝到a[begin1,end2]中
for (int i = begin1; i <= end2; i++)
{
a[i] = p[i];
}
}
这就是单趟排序的过程。
递归函数
void MergeSort(int* a, int left,int right, int* p)
{
if (right-left <= 0) // 完成上半部分的分割
{
return;
}
int mid = (left + right) / 2;
MergeSort(a, left, mid, p);
MergeSort(a, mid+1, right, p); // 先分成长度全部为1的区间
pastsort3(a, left, mid, mid + 1, right, p); //从二叉堆底开始归并,长度为1,必定有序
}
void _MergeSort(int* a, int n)
{
int* p = new int[n];
MergeSort(a, 0,n-1, p);
delete[]p;
}
图示
非递归函数
用迭代方法:如图,直接从递归图的下半部分开始,比递归效率更高,但代码量更多,还要考虑末尾剩下的数。
但不管末尾剩下多少的数,这些数都是有序的,我们只需要在end2大于n-1的时候,将end2改为n-1即可。
令间隔为gap,每一次循环gap要*2(1,2,4,8......),从头开始,每一gap间隔里的数都是有序的,当gap>n的时候结束循环。
void MergeSort2(int* a, int n)
{
int* p = new int[n];
int gap = 1;
while (gap <= n)
{
for (int i = 0; i < n; i += gap*2) // 每次归并两个长度为gap的数列(当gap=2时,i==0归并了下标为0 1 2 3的数)
{
int begin1 = i; // begin1必然有效
int end1 = i + gap - 1;
int begin2 = i + gap;
int end2 = i + gap * 2 - 1; // end2= begin1+gap-1 =i+gap+gap-1=i+gap*2-1
if (begin2 >= n) // 当begin2 >= n时,情况1.(end1==n-1)由于[begin1,end1]已经是有序的,退出循环 情况2. (end1>n-1)[begin1 , n-1]也是有序的
{
break;
}
if (end2 >= n) // 当begin2<n end2>=n ,改变end2==n-1,将[begin1,end1]与[begin2,n-1]合并
{
end2 = n - 1;
}
pastsort3(a, begin1, end1, begin2, end2, p);
}
gap *= 2;
}
delete[]p;
}