算法原理
分治
算法步骤
- 确定分界点为中间位置,mid=(l+r)/2
- 递归排序左右两边
- 归并两个排好序的数组,合二为一(最难的部分),时间复杂度是O(n)
双指针算法
两个指针分别指向两个数组的开头,比较两个指针对应数值大小,小的放进新数组,该指针后移,直到一个指针到达数组末尾,将另外一个数组剩下的部分添加到新数组中。
1 3 5 7 9
2 4 5 8 10
i=0,j=0;p[i]=p[0]=1<q[j]=q[1]=2,s[0]=p[0]=1;i++;i=1,j=0;
i=1,j=0;p[i]=p[1]=3>q[j]=q[0]=2,s[1]=q[0]=2;j++;i=1,j=1;
i=1,j=1;p[i]=p[1]=3<q[j]=q[1]=4,s[2]=p[1]=3;i++;i=2,j=1;
i=2,j=1;p[i]=p[2]=5>q[j]=q[1]=4,s[3]=q[1]=4;j++;i=2,j=2;
i=2,j=2;p[i]=p[2]=5<=q[j]=q[2]=5,s[4]=p[2]=5;i++;i=3,j=2;
i=3,j=2;p[i]=p[3]=7>q[j]=q[2]=5,s[5]=q[2]=5;j++;i=3,j=3;
i=3,j=3;p[i]=p[3]=7<q[j]=q[3]=8,s[6]=p[3]=7,i++;i=4,j=3;
i=4,j=3;p[i]=p[4]=9>q[j]=q[3]=8,s[7]=q[3]=8,j++;i=4,j=4;
i=4,j=4;p[i]=p[4]=10>q[j]=q[4]=9,s[8]=q[4]=9,j++;i=4,j=5
s[9]=p[4]=10
原序列中两个值相同的数,排序后相对位置不发生变化,排序算法就是稳定的。
算法
#include<iostream>
using namespace std;
const int N = 1000010;
int n;// 数组元素个数
int q[N];//待排序的数组
int tmp[N];// 用来存放合并左右两边结果的数组
void merge_sort()
{
// 当前区间只有一个数或者没有数
if(l>=r) return ;
// 确定分界点为数组中点
int mid = l+r>>1;
// 对左右两边进行递归排序
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
// 将左右两边排好序的部分合并
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r)
{
if(q[i]<=q[j])
{
tmp[k]=q[i];
k++;
i++;
}
else
{
tmp[k]=q[j];
k++;
j++;
}
}
//左半边有序数组没有循环完,剩余部分填到数组中
while(i<=mid)
{
tmp[k++]=q[i++];
}
// 右半边数组没有循环完,剩余部分填到数组中
while(j<=r)
{
tmp[k++]=q[j++];
}
for(i=l,j=0;i<=r;i++,j++)
{
q[i] = tmp[j];
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&q[i]);
}
merge_sort(q,0,n-1);
for(int i=0;i<n;i++)
{
printf("%d ",q[i]);
}
return 0;
}