前
稍微复习(+学习)了一下排序的算法:选择/冒泡/桶/快排等
下面的代码和讲解也是这几种排序,至于归并/基数啥的想单独开一篇博客
以下单独代码均涉及宏定义,可以先看思路再到最后看宏定义内容
本博客针对洛谷P1177排序模板 并已通过大数据对拍 为升序排序
中
快速排序
STL大法好,直接sort
想降序可以手写cmp或者倒序输出
Fo(i,1,n) num[i]=read();
sort(num+1,num+n+1);
Fo(i,1,n) printf("%d ",num[i]);
降序cmp写法
bool cmp(int a , int b) {
return a>b;
}
选择排序
顾名思义就是每次都选择我需要的那个数放在一遍,重复n次
每次我假定第i个值最小,然后我循环从i+1到n,如果有比我小的我就记录下来,并且记录这个位置,当我把i+1后面所有的值都循环完之后,我找到了最小的值,交换最小的值和i位置上的值,所以i位置目前放的就是最小的,然后将i循环起来,就可以升序排序。
void xz_sort() {
//选择排序 未优化版
Fo(i,1,n) {
minn = num[i];
min_op = i;
Fo(j,i+1,n)
if(minn>num[j]) {
minn = num[j];
min_op = j;
}
swap(num[min_op],num[i]);
}
}
选择排序的优化
每次只选最小值还是有点浪费时间的,我倒不如每次都选择最大值和最小值,然后把最大值放在最后最小值放在最前面。注意这里的最后和最前是还没排序好的,如果已经确定了就不要再修改了。这样的话我们的i就没必要循环到n了,就省下了一部分时间。
坑点:小心代码中continue的两种情况均是“最小值在最后的情况”:1.最大值在最前面,最小值在最后面,交换一次就可以了 2.最小值在最后,最大值不是最前面,所以最小值要与原来最大值的位置互换。
void x_sort() {
//选择排序 优化版
Fo(i,1,n/2+1) {
minn=maxx=num[i];
min_op=max_op=i;
Fo(j,i+1,n-i+1) {
if(num[j]<minn) {
minn = num[j];
min_op = j;
}
if(num[j]>maxx) {
maxx = num[j];
max_op = j;
}
}
if(i==max_op&&n-i+1==min_op) {
swap(num[i],num[min_op]);
continue;
}
swap(num[n-i+1],num[max_op]);
if(min_op==n-i+1) {
swap(num[i],num[max_op]);
continue;
}
swap(num[i],num[min_op]);
}
}
冒泡排序
所谓冒泡排序,就是像冒泡一样,数的大小类比为泡的轻重。
每一个数从头循环到n-i,i的意思是已经有i个数排好序,这样每次遇到后面比前面小就互换,最大的一定在最后吧,这样做1次就有1个数到他自己应该去的地方,一共循环n次就把所有的数放到应该放的位置,就完成了排序。
void m_sort() {
//冒泡排序 未优化版
Fo(i,1,n)
Fo(j,1,n-i)
if(num[j]>num[j+1])
swap(num[j],num[j+1]);
}
冒泡排序的优化
就是如果i还没循环完就已经排好序了,后面是不是不用再排序了。用一个变量flag记录是否还在排序,从而判断是否结束循环。
void mp_sort() {
//冒泡排序 优化版
Fo(i,1,n) {
flag = 0;
Fo(j,1,n-i)
if(num[j]>num[j+1]) {
flag = 1;
swap(num[j],num[j+1]);
}
if(!flag)
break;
}
}
桶排序
用一个桶把所有的数出现的次数记录下来,然后i从1到最大值开始循环,如果发现出现过(出现次数不为0)就输出,出现几次就输出几次,这样输出就能排好序。数比较小,可以直接用数组存储。
int cnt[L];
void t_sort() {
//桶排序 小数
Fo(i,1,n) {
cnt[num[i]]++;
maxx=max(maxx,num[i]);
}
Fo(i,1,maxx)
if(cnt[i])
Fo(j,1,cnt[i])
printf("%d ",i);
}
桶排序的优化
数组当然不能满足我们的要求,所以考虑用map实现对大数的存放
(突然想起来上次决定要补的map鸽了)
map<LL,LL>pot;
void tp_sort() {
//桶排序 大数
Fo(i,1,n)
pot[num[i]]++;
map<LL,LL>::iterator it;
for(it=pot.begin();it!=pot.end();it++)
while(it->second) {
top++;
cnt[top]=it->first;
it->second--;
}
Fo(i,1,top)
printf("%d ",cnt[i]);
}
总的代码实现
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
#define PI acos(-1)
#define fin freopen("data.txt","r",stdin)
#define INF 2147483647
#define eps 1e-7
#define L 100005
#define Fo(i,a,b) for(LL i=(a),_=(b); i<=_; i++)
#define Ro(i,b,a) for(LL i=(b),_=(a); i>=_; i--)
inline LL read() {
LL x=0,f=1;char c=getchar();
while(!isdigit(c)) {
if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48ll),c=getchar();
return x*f;
}
map<LL,LL>pot;
int num[L] , n , minn , maxx , min_op , max_op , flag , cnt[L] , top;
bool cmp(int a , int b) {
return a>b;
}
void xz_sort() {
//选择排序 未优化版
Fo(i,1,n) {
minn = num[i];
min_op = i;
Fo(j,i+1,n)
if(minn>num[j]) {
minn = num[j];
min_op = j;
}
swap(num[min_op],num[i]);
}
}
void x_sort() {
//选择排序 优化版
Fo(i,1,n/2+1) {
minn=maxx=num[i];
min_op=max_op=i;
Fo(j,i+1,n-i+1) {
if(num[j]<minn) {
minn = num[j];
min_op = j;
}
if(num[j]>maxx) {
maxx = num[j];
max_op = j;
}
}
if(i==max_op&&n-i+1==min_op) {
swap(num[i],num[min_op]);
continue;
}
swap(num[n-i+1],num[max_op]);
if(min_op==n-i+1) {
swap(num[i],num[max_op]);
continue;
}
swap(num[i],num[min_op]);
}
}
void m_sort() {
//冒泡排序 未优化版
Fo(i,1,n)
Fo(j,1,n-i)
if(num[j]>num[j+1])
swap(num[j],num[j+1]);
}
void mp_sort() {
//冒泡排序 优化版
Fo(i,1,n) {
flag = 0;
Fo(j,1,n-i)
if(num[j]>num[j+1]) {
flag = 1;
swap(num[j],num[j+1]);
}
if(!flag)
break;
}
}
void t_sort() {
//桶排序 小数
Fo(i,1,n) {
cnt[num[i]]++;
maxx=max(maxx,num[i]);
}
Fo(i,1,maxx)
if(cnt[i])
Fo(j,1,cnt[i])
printf("%d ",i);
}
void tp_sort() {
//桶排序 大数
Fo(i,1,n)
pot[num[i]]++;
map<LL,LL>::iterator it;
for(it=pot.begin();it!=pot.end();it++)
while(it->second) {
top++;
cnt[top]=it->first;
it->second--;
}
Fo(i,1,top)
printf("%d ",cnt[i]);
}
int main() {
// fin;
n=read();
Fo(i,1,n) num[i]=read();
sort(num+1,num+n+1);//快速排序
xz_sort(); //选择排序 未优化版
x_sort(); //选择排序 优化版
m_sort(); //冒泡排序 未优化版
mp_sort(); //冒泡排序 优化版
t_sort(); //桶排序 小数
tp_sort(); //桶排序 大数
Fo(i,1,n) printf("%d ",num[i]);
return 0;
}
后
已经有nlogn的sort然后再学这些排序的原因呢,是得了解原理啊
反正好多题都是这些原理改的(现在突然想起来做过一个桶排序的推广题)
好了,就这,祝你能看懂。