[学习]排序算法:快排/选择/冒泡/桶排序

稍微复习(+学习)了一下排序的算法:选择/冒泡/桶/快排等

下面的代码和讲解也是这几种排序,至于归并/基数啥的想单独开一篇博客

以下单独代码均涉及宏定义,可以先看思路再到最后看宏定义内容

本博客针对洛谷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然后再学这些排序的原因呢,是得了解原理啊

反正好多题都是这些原理改的(现在突然想起来做过一个桶排序的推广题)

好了,就这,祝你能看懂。

猜你喜欢

转载自blog.csdn.net/cls1277/article/details/110205163
今日推荐