持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情
流程
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
- 合并:
①设定两个指针,最初位置分别为两个已经排序序列的起始位置。
②比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。
③重复步骤③直到某一指针超出序列尾。
④ 将另一序列剩下的所有元素直接复制到合并序列尾。
演示
代码
#include <stdio.h>
#define N 1001
int n,a[N],x,b[N];
void paixu(int l,int r)
{
if (l==r) return;
int mid=(l+r)/2+1,i,j,t=0;
paixu(l,mid-1);
paixu(mid,r);
for (i=l,j=mid;i<mid&&j<=r;)
if (a[i]<a[j]) b[++t]=a[i++];
else b[++t]=a[j++];
if (i==mid)
for (;j<=r;++j) b[++t]=a[j];
else for (;i<mid;++i) b[++t]=a[i];
for (i=l;i<=r;++i) a[i]=b[i-l+1];
}
int main()
{
scanf("%d",&n);
for (int j,i=1;i<=n;++i) scanf("%d",&a[i]);
paixu(1,n);
for (int i=1;i<=n;++i) printf("%d ",a[i]);
return 0;
}
时间复杂度
首先,我们假设进行合并排序的数组大小为N且为2的幂,表示对其排序耗费的时间,那么就有:
- (两个N分别为合并耗费时间和拷贝回原数组所耗费的时间)
将2式左右除以N,得:
递推该式,得
……
将上述所有式子左侧相加且右侧相加,得:
化简,得:,即
这个时间复杂度与快速排序的平均时间复杂度相同,比快速排序的最坏情况要好得多。
但是在实际应用中快速排序要比合并排序优先考虑,原因在于合并排序需要更多的内存空间,并且从tempArr拷贝数据回原数组也是一项花费巨大的工作。