1.并归排序
基本思想:并归排序采用了分治法,将已有序的子序列合并,得到完全有序的序列;即先使子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路并归。(这段直接摘录的一本通,这里已经介绍的比较简洁了)
并归排序的算法我们通常用递归实现,先把有序区间[l,r]中分,接着把左边子区间排序,再把右边子区间排序,最后合并两子区间。
具体代码实现会比之前的代码复杂,下面的代码批注会详细一些。
如果是初学的话,应该先了解分治算法,然后再试着在理解的同时动手写代码。
#include <bits/stdc++.h>
using namespace std;
int a[100],b[100]; // a表示需要排序数组,b用于暂存
void msort(int l,int r){ //l表示最左边的下标,r表示最右边的下标
if(l==r)return; //如果只有一个数字则直接返回
int mid=(l+r)/2; //mid表示序列中位数
msort(l,mid); //分解左序列
msort(mid+1,r); //分解右序列
int i=l,j=mid+1,k=l;
while (i<=mid&&j<=r){
if(a[i]<=a[j]){
b[k]=a[i];k++;i++;
}else {
b[k]=a[j];k++;j++;
}
}
while(i<=mid){ //复制左边子序列剩余
b[k]=a[i];i++;k++;
}
while(j<=r){ //复制右边子序列剩余
b[k]=a[j];j++;k++;
}
//将数组b中暂存元素全部黏贴到数组a中
for(i=l;i<=r;i++)a[i]=b[i];
}
int main(){
int n,i;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
}
msort(0,n-1);//调用函数
for(i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
并归排序的时间复杂度使O(nlogn),速度快,稳定。
2.快速排序
基本思想:将待排序序列任取一个记录,将所有小于它的记录都放在左子序列中,大于它的记录都放在右子序列中,这个过程称作一次快速排序(或一次划分)。
一趟快速排序的做法:设两个指针i和j,设记录取mid。从j所指位置向前找一个比mid小的记录,从i所指位置先后找一个比mid大的记录,将他们交换,重复直到i>j为止。
快速排序的代码实现难度和基本思想都比并归排序简单
#include <bits/stdc++.h>
using namespace std;
int a[100];
void qsort(int l,int r){
int i,j,mid,p;
i=l;j=r;
mid=a[(l+r)/2];//注意这里的mid不是中位数下标!!
while(i<=j){
while(a[i]<mid)i++;//在左半部分寻找一个比mid大的数,i表示其下标
while(a[j]>mid)j--;//在右半部分寻找一个比mid小的数,j表示其下标
if(i<=j){
swap(a[i],a[j]);//交换a[i],a[j]
i++;j--; //继续找
}
}
//若未到边界,则递归搜索左右区间
if(l<j)qsort(l,j);
if(i<r)qsort(i,r);
}
int main(){
int i,n;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
}
qsort(0,n-1);
for(i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
当然,如果noip中遇到需要排序还是用sort函数好。别在比赛的时候给自己增加难度。(就算排序一个都不会,sort总该会吧)
离NOIP还剩110天,加油!