排序的一千零一种食用方法


本文写于很久之前,那时读者水平很低,本文仅供参考,建议按照更正统的道路学习排序

关于排序

排序,就是指给你一个无序的数列,让你通过某种方式把这个数列转换为有序数列。

一般情况下,以比较为基本运算的排序算法极限是nlogn(有不是很复杂的证明方法),而以非比较为基本运算的算法多是线性(当然也有很多局限)

本文主要讲解一个 令人感动的稳定 n 2 n^{2} n2算法(冒泡)、两个nlogn算法(快速排序sort,堆排序)以及线性排序基本原理和代表计数(无误)排序

本文所有排序以升序为例

冒泡排序

最简单的排序,没有之一。

原理为对于每一个元素,与它之前的所有元素比较大小,小则交换。

没了。

#include<bits/stdc++.h>
using namespace std;
int a[10001];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	  cin>>a[i];
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=i;j++)
	    if(a[i]<a[j])
		swap(a[i],a[j]);//cmath自带函数,交换两个数 
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
	return 0;
}

nlogn算法

快排sort

其实我认为我当初真是闲的学快排学那么认真,不知道sort大法万岁

首先,快排能解决的一切问题,sort都能解决

sort原理:通过一些令人窒息的骚操作,以我们看不懂的方式,针对每一组待排序数据选择合适的算法进行排序。(比如什么时候用插入,什么时候用快排,什么时候用堆排)

#include<bits/stdc++.h>
using namespace std;
int a[10001];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	  cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
	return 0;
}

sort排序默认升序,如果你想降序,就用下面的程序

#include<bits/stdc++.h>
using namespace std;
int a[10001];
bool cmp(int x,int y)
{
	return x>y;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	  cin>>a[i];
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
	return 0;
}

sort(a+1,a+n+1,cmp);

a+1:这里指a数组的起始地址,因为我习惯数组下标从1开始,所以是 a+1。

a+n+1:n指的是数组长度,+1原因与上一致。

cmp:比较器,如果你排序的a数组是c++自带的(就是int那些关键字定义的),那么比较器可以不写,它会默认加上升序比较器。如果你想降序或者给结构体排序,就得写cmp,cmp的意义是告诉sort以什么样的标准排序。

堆排序

首先,你得知道什么是

然后,我们就需要用一个小根堆大根堆

来进行排序。

小根堆堆顶元素最小,我们只需要每次插入元素,确保插入后堆依然是小根堆就可以了,每次弹出堆顶。

你可能会说:堆排序也太麻烦了吧,还得手写堆,再balabala一大堆
这都9102年了还有人不会用stl

上面我的这篇博客讲的很详尽了,值得好好学习。

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x;
	inline bool operator<(const node a)const
	{
		return x>a.x;//重载运算符固定格式,重新解释<的意义
	}
};
priority_queue<node>q;
int main()
{
	int n;
	cin>>n;
	int a;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		q.push((node){a});
	}
	node step;
	for(int i=1;i<=n;i++)
	{
		step=q.top();
		q.pop();
		cout<<step.x<<" ";
	}
	return 0;
}

这个代码带了重载运算符,是升序排序。

线性排序

基本原理

通过统计一些信息,使得每个数彼此都能区分,统计出每个数出现几次,从小到大,出现几次就输出几次,每出现就不输出

计(无误)数排序

#include<bits/stdc++.h>
using namespace std;
int a[10001];
int main()
{
	int n;
	cin>>n;
	int x;
	int maxn=-1e9;
	int minn=1e9;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
		a[x]++;//统计数字个数
		maxn=max(maxn,x);
		minn=min(minn,x);//统计最大值,最小值,优化常数。
	}
	for(int i=minn;i<=maxn;i++)//从最小值到最大值
	{
		while(a[i]>0)//判断个数是否输出完
		{
			a[i]--;
			cout<<i<<" ";
		}
	}
	return 0;
}

计数排序显而易见有很大的漏洞:数最大值有多大,数组就得开多大

在我写这篇博客时,我旁边的lws说他在年轻的时候手写堆,来排序哈哈哈。
蒟蒻一名若有错漏请及时联系:)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

灰雾与红

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

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

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

打赏作者

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

抵扣说明:

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

余额充值