NOIP2 数据排序2 (并归、快速、逆序对+各种排序比较)C++

本文介绍了两种高效的排序算法——并归排序和快速排序的基本思想及实现方式,并提供了详细的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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天,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值