几种常用的排序算法

一、直接调用快排sort函数

P2676 [USACO07DEC]Bookshelf B

#include <bits/stdc++.h>
using namespace std;
int n, b, h[20001], s;
int main()
{
	scanf("%d %d", &n, &b);
	for(int i=1; i<=n; ++i){
		scanf("%d", &h[i]);
	}
	sort(h+1, h+n+1);
	for(int i=n; i>=1; --i){
		s+=h[i];
		if(s>=b){
			printf("%d", n-i+1);
			return 0;
		}
	}
	return 0;
}

一、字符串高精度排序

P1781 宇宙总统

#include <bits/stdc++.h>
using namespace std;
int n, asd;
string x, mx;
//如果a > b, 则返回true 
bool cmp(string a, string b)
{
	int l1=a.length(), l2=b.length();
	if(l1==l2)	//如果长度一样
	{
		for(int i=0; i<l1; ++i){
			if(a[i]>b[i]){	//a>b 
				return true;
			}
			else if(a[i]<b[i]){	//a<b
				return false;
			}
		}
		//相等 
		return false;
	}
	else{	//如果长度不同, 长度长的大 
		return l1>l2;
	} 
}
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		cin >> x;
		//如果x比mx还要大 
		if(cmp(x, mx)){
			mx=x;
			asd=i; 
		}
	}
	printf("%d\n", asd);
	cout << mx;
	return 0;
}

二、桶排序

P1271 【深基9.例1】选举学生会

//桶排序模板题 
#include <bits/stdc++.h>
using namespace std;
int n, m, x, tong[1000];
int main()
{
	scanf("%d %d", &n, &m);
	for(int i=1; i<=m; ++i){
		scanf("%d", &x);
		tong[x]++;
	}
	for(int i=1; i<=n; ++i){
		for(int j=1; j<=tong[i]; ++j){
			printf("%d ", i);
		}
	}
	return 0;
}

三、根据结构体某一元素排序

P5143 攀爬者

#include <bits/stdc++.h>
using namespace std;
int n;
double ans;
struct node{
	double x, y, z;
}a[50006];
bool cmp(node p, node q)
{
	return p.z<q.z;
}
double dis(node p, node q)
{
	double xx1=p.x, yy1=p.y, zz1=p.z, xx2=q.x, yy2=q.y, zz2=q.z;
	return sqrt((xx1-xx2)*(xx1-xx2)+(yy1-yy2)*(yy1-yy2)+(zz1-zz2)*(zz1-zz2));
}
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		scanf("%lf %lf %lf", &a[i].x, &a[i].y, &a[i].z);
	}
	sort(a+1, a+n+1, cmp);
	for(int i=1; i<n; ++i){
		ans+=dis(a[i], a[i+1]);
	}
	printf("%.3lf", ans);
	return 0;
}

四、归并排序

归并排序模板

//归并排序O(nlogn) 
#include <bits/stdc++.h>
using namespace std;
int n, a[500006], temp[500006];
void f(int l, int r)
{
	if(l>=r)	return;
	int mid=(l+r)>>1;
	f(l, mid);
	f(mid+1, r);
	int head1=l, head2=mid+1;
	for(int i=l; i<=r; ++i){
		//当head2没有超出r, 并且右区间第一个数比左区间第一个数小
		//或者当head2没有超出r,右区间已经空了 
		//则将右区间的第一个数放入temp数组中 
		if(head2<=r && (head1>mid || a[head2]<a[head1])){
			temp[i]=a[head2];
			head2++;
		}
		else{
			temp[i]=a[head1];
			head1++;
		} 
	}
	for(int i=l; i<=r; ++i){
		a[i]=temp[i];
	}
	return;
} 
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		scanf("%d", &a[i]);
	}
	f(1, n); 
	for(int i=1; i<=n; ++i){
		printf("%d ", a[i]);
	}
	return 0;
}

P1908 逆序对(归并排序思想)

//归并排序思路求逆序对个数O(nlogn) 
#include <bits/stdc++.h>
using namespace std;
int n, a[500006], temp[500006];
long long ans;
//计算a[l~r]中的逆序对数量 
void f(int l, int r)
{
	if(l>=r)	return;
	int mid=(l+r)>>1;
	//先往下分 
	f(l, mid);
	f(mid+1, r);
	//再不断合并 
	int head1=l, head2=mid+1;
	for(int i=l; i<=r; ++i){
		//当head2没有超出r, 并且右区间第一个数比左区间第一个数小
		//或者当head2没有超出r,右区间已经空了 
		//则将右区间的第一个数放入temp数组中 
		if(head2<=r && (head1>mid || a[head2]<a[head1])){
			temp[i]=a[head2];
			head2++;
			//当右区间a[head2]比左区间a[head1]小时, a[head2]会比a[head1~mid]都要小, 
			//此时a[head2]这个数会给答案贡献 mid-head1+1 
			ans+=mid-head1+1;
		}
		else{ 
			temp[i]=a[head1];
			head1++;
			//或者当左区间a[head1]要放入temp数组中时, 要形成逆序对, 
			//只需要在右区间找比它小的数的个数, 也就是右区间中在它(a[head1])之前已经放入temp数组中的数 
			//就是mid+1~head2-1这些数, 总数为 head2-1-(mid+1)+1=head2-mid-1 
//			ans+=head2-mid-1; 
		} 
	}
	for(int i=l; i<=r; ++i){
		a[i]=temp[i];
	}
	return;
} 
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		scanf("%d", &a[i]);
	}
	f(1, n); 
	printf("%lld", ans);
	return 0;
}

P1966 [NOIP2013 提高组] 火柴排队(归并排序求逆序对数量)

//求∑(ai-bi)^2的最小值, 相当于求 ∑(ai*bi)的最大值
//当a[]从大到小排序, b[]从大到小排序后,  ∑(ai*bi)的值最大
//或者当a[]从小到大排序, b[]从小到大排序后,  ∑(ai*bi)的值最大
//排好序的两个数组中第i位上的两个数一一对应即为最终的状态,
//但是并不需要全部排序, 只要满足一一对应关系即可, 这样能减少交换次数
//因为数据范围2^31-1比较大, 所以需要离散化一下 
#include <bits/stdc++.h>
#define mod 99999997
using namespace std;
int n, c[100006], temp[100006];
long long ans;
struct asd
{
	int height, id;	
}a[100006], b[100006];
//按照height从小到大排序 
bool cmp(asd x, asd y)
{
	return x.height<y.height;
}
void f(int l, int r)
{
	if(l>=r)	return;
	int mid=(l+r)>>1;
	f(l, mid);
	f(mid+1, r);
	int head1=l, head2=mid+1, cnt=l;
	while(head1<=mid && head2<=r){
		if(c[head1]<c[head2]){
			temp[cnt]=c[head1];
			cnt++;
			head1++;
		}
		else if(c[head1]>c[head2]){	//如果左区间的c[head1]大于右区间的c[head2] 
			//逆序对, 那么左区间的c[head1~mid]一定大于右区间c[heade2]
			ans=(ans+mid-head1+1)%mod;
			temp[cnt]=c[head2];
			cnt++;
			head2++;
		}
	}
	while(head1<=mid){
		temp[cnt]=c[head1];
		cnt++;
		head1++;
	}
	while(head2<=r){
		temp[cnt]=c[head2];
		cnt++;
		head2++;
	}
	for(int i=l; i<=r; ++i){
		c[i]=temp[i];
	}
	return;
}
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; ++i){
		scanf("%d", &a[i].height);
		a[i].id=i;	//离散化 
	}
	for(int i=1; i<=n; ++i){
		scanf("%d", &b[i].height);
		b[i].id=i;	//离散化 
	}
	//根据height从小到大排序 
	sort(a+1, a+n+1, cmp);
	sort(b+1, b+n+1, cmp);
	//a[1~n].height需要和b[1~n].height一一对应
	//也就是a[1~n].id需要和b[1~n].id一一对应 
	//那我们让a[]数组不动, 我们去动b[]数组, 来和a[]数组一一对应上
	//这时候需要做一个映射
	for(int i=1; i<=n; ++i){
		c[a[i].id]=b[i].id;
	}
	//归并排序找逆序对 
	f(1, n);
	printf("%lld", ans); 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ypeijasd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值