基本原理
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
时间复杂度:O(nlog(2)n)
基本思想:分治
(我知道上面这一串说不清楚,所以还是上图吧)
图片来源 — https://baike.sogou.com/v8340582.htm?fromTitle=%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F
如图所示:
不断分解——分别排序——边比较边合并——得到有序数列
具体流程
参数说明:start 为前部分第一个元素的下标,mid为前部分结尾,end为后一部分结尾
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
void merge(ll a[],ll start,ll mid,ll end)//用于合并两数组时不断比较
{
ll i,j,k;//分别指示两部分和临时数组的元素到了哪一个,可理解为指向所用元素的指针,在不断后移
ll *b = (ll *)malloc((end-start+1)*sizeof(ll));//设置一个临时空间,用于存储两数组合并后的状态。
i=start;
j=mid+1;
k=0;
while(i<=mid&&j<=end)
{
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
while(i<=mid) b[k++]=a[i++];
while(j<=end) b[k++]=a[j++];
for(i=0;i<k;i++) a[i+start]=b[i];
free(b);
}
void sort(ll a[],ll start,ll end)//不断分割原数组
{
ll mid=(start+end)/2;
if(a==NULL||start>=end) return;
sort(a,start,mid);
sort(a,mid+1,end); //分别对两边继续分割
merge(a,start,mid,end);
}
int main()
{
ll a[8]={10,6,7,1,3,9,4,2};
sort(a,0,7);
for(int i=0;i<8;i++)
{
printf("%d ",a[i]);
}
return 0;
}
- 第一步:进入sort函数,递归将数组分割,再将其两部分继续分割,这样无限分割下去,直至start>=end,即每个部分中只余一个元素
- 第二步:进入merge函数
(我再也不想画图了)
依次排序得到数组b,然后将b数组的值返回给a数组,释放b的空间。
依次合并的过程,可用如下图解(不是这道题,但很清楚)
- 得到运行结果,输出a数组得1 2 3 4 5 6 7 9 10