归并排序C++
归并排序从小到大排序:首先让数组中的每一个数单独成为长度为1的区间,
然后两两一组有序合并,得到长度为2的有序区间,依次进行,直到合成整个区间。
#include <iostream>
using namespace std;
//4 归并排序
/*
归并排序从小到大排序:首先让数组中的每一个数单独成为长度为1的区间,
然后两两一组有序合并,得到长度为2的有序区间,依次进行,直到合成整个区间。
*/
//4.3 核心代码(函数)
//1 递归实现
//函数声明
void MergeSort(int array[]);
void MSort(int array[], int Result[], int start, int end);
void Merge(int array[], int Ans[], int start, int midd, int endd); //将两个排序序列排序 从小到大排序
//函数实现
void MergeSort(int array[])
{
MSort(array, array, 0, 9);
}
void Merge(int array[],int Ans[], int start, int midd, int endd) //将两个排序序列排序 从小到大排序
{
int i = start; //记录前半段的下标
int j ; //记录后半段的下标
int k; //记录结果Ans的下标
for ( j = midd + 1, k = i; i <= midd && j <= endd; k++)
{
if (array[i] > array[j])
{
Ans[k] = array[j];
j++;
}
else
{
Ans[k] = array[i];
i++;
}
}
if (i <= midd) //
{
for (; i <= midd; i++,k++)
{
Ans[k] = array[i];
}
}
if (j <= endd) //
{
for (; j <= endd; j++, k++)
{
Ans[k] = array[j];
}
}
}
void MSort(int array[], int Result[], int start, int end)
{
int Tmp[1000];
if (start == end)
Result[start] = array[start];
else
{
int mid = (start+end) / 2; //中间点的位置,从中间点将数组分成两部分
MSort(array, Tmp, start, mid); //左半部分排序
MSort(array, Tmp, mid + 1, end); //右半部分排序
Merge(Tmp, Result,start, mid, end); //合并
}
}
//2:迭代实现
void MergeSortIter(int k[], int n)
{
int i, next, left_min, left_max, right_min, right_max;
//动态申请一个与原来数组一样大小的空间用来存储
int *temp = (int *)malloc(n * sizeof(int));
//逐级上升,第一次比较2个,第二次比较4个,第三次比较8个。。。
for (i = 1; i<n; i *= 2)
{
//每次都从0开始,数组的头元素开始
for (left_min = 0; left_min<n - i; left_min = right_max)
{
right_min = left_max = left_min + i;
right_max = left_max + i;
//右边的下标最大值只能为n
if (right_max>n)
{
right_max = n;
}
//next是用来标志temp数组下标的,由于每次数据都有返回到K,
//故每次开始得重新置零
next = 0;
//如果左边的数据还没达到分割线且右边的数组没到达分割线,开始循环
while (left_min<left_max&&right_min<right_max)
{
if (k[left_min] < k[right_min])
{
temp[next++] = k[left_min++];
}
else
{
temp[next++] = k[right_min++];
}
}
//上面循环结束的条件有两个,如果是左边的游标尚未到达,那么需要把
//数组接回去,可能会有疑问,那如果右边的没到达呢,其实模拟一下就可以
//知道,如果右边没到达,那么说明右边的数据比较大,这时也就不用移动位置了
while (left_min < left_max)
{
//如果left_min小于left_max,说明现在左边的数据比较大
//直接把它们接到数组的min之前就行
k[--right_min] = k[--left_max];
}
while (next>0)
{
//把排好序的那部分数组返回该k
k[--right_min] = temp[--next];
}
}
}
}
//非递归的方法,避免了递归时深度为log2N的栈空间,
//空间只是用到归并临时申请的跟原来数组一样大小的空间,并且在时间性能上也有一定的提升,
//因此,使用归并排序是,尽量考虑用非递归的方法。
int main( )
{
int array[10] = { 3,5,4,6,9,8,7,1,2,0};
int len = sizeof(array) / sizeof(int);
for (int i = 0; i < len; i++)
cout << array[i] << " ";
cout << endl;
cout << "*************************"<< endl;
//insertSort(array,len); //插入排序
MergeSort(array); //归并排序
//adjust_quicksort(array,10); //快速排序
for (int i = 0; i < len; i++)
cout << array[i] << " ";
cout << endl;
system("pause");
return 0;
}