在之前的排序中,早就练就了递归的思想,接下来我们就用递归的思想来实现这个归并排序。
首先,我们知道两个有序的数组我们将它合并成一个有序的数组是十分简单的,只需要一个循环和两个指针比较两个数组指针所指向的数,不断的把大的或小的取出,取出数的内个数组指针后移继续比较即可。
举个例子:[1,2,3,4]、[1,3,7,8]这是两个有序数组
有两个指针分别指向二者头部,然后开始循环
我们将较小(或者大)的内个放入新数组(这里左右都行) ,然后含有放入新数组元素的数组指针后移。
最终得:
这样我们就得到了一个有序的数组。
那么这种排序方式首先得得到两个有序的数组,怎么去找这样有序的数组呢,答案是一个数字一定有序,所以我们的想法就是让数组的左半部分归并,再让右半部分归并,最终让整个数组归并就可以了。具体百度百科给出了例子:
分成单独元素就确保该数组有序然后两两归并,然后再两两归并最终得到排序好的数组。
代码:
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
//将一个数组分为两部分,low-mid,mid+1-high,两部分相当于两个有序数组,归并他们
void merge(int a[], int low, int mid, int high) //合并两个有序数组的merge函数
{
int *temp = new int [high - low+1]; //开辟临时数组
int i = low; //左数组的下标指针
int j = mid + 1; //右数组的下标指针
int m = 0; //临时数组的下标指针
while(i<=mid && j<=high) //如果左右都没有超过最大下标,就把小的内个放入新数组
{ //并更新下标
if(a[i]>a[j])
{
temp[m] = a[j];
j++;
}
else
{
temp[m] = a[i];
i++;
}
m++;
}
while(i<=mid) //上一个循环结束至少有一边到达了最大下标
{ //说明另一半元素比已排元素都大且有序,直接丢入新数组
temp[m] = a[i];
i++;
m++;
}
while(j<=high)
{
temp[m] = a[j];
j++;
m++;
}
//memcpy(a + low, temp, sizeof(int) * (high-low+1)); //赋值的一种方法
//delete temp;
//temp = nullptr;
int k = low;
for(int i = 0 ; i < m && k <= high; i++,k++ ) //循环将新数组里的值赋回给原数组
{
a[k]=temp[i];
}
delete[] temp;
}
void merge_sort(int a[],int low,int high)
{
if(low >= high) //如果数组中只有一个元素时返回
{
return;
}
int mid = (high+low)/2; //中间位置(主观将一个数组分为两半)
merge_sort(a,low,mid); //排序左边
merge_sort(a,mid+1,high); //排序右边
merge(a,low,mid,high); //排序整体
}
//像图上一样,会不断递归调用,最终排序完成
int main()
{
int a[] = {1,4,5,6,7,2,8,9,3};
merge_sort(a,0,sizeof(a)/sizeof(int)-1);
for(int i = 0;i<sizeof(a)/sizeof(int);i++)
{
cout<<a[i];
}
}