浅谈各种排序算法
目录
main程序
int main(){
int n;
cin>>n;
vector<int> q(n+1);
for(int i=1,t;i<=n;i++){
cin>>t;
q[i]=t;
}
//bubble_sort(q,n);
//select_sort(q,n);
//insert_sort(q,n);
//merge_sort(q,1,n);
//quick_sort(q,1,n);
//heap_sort(q,n);
//counting_sort(q,n);
radix_sort(q,n);
for(int i=1;i<=n;i++) cout<<q[i]<<" ";
cout<<endl;
return 0;
}
1、冒泡排序
//冒泡排序 时间复杂度:最坏O(n^2)
void bubble_sort(vector<int> &q,int n){
for(int i=n;i>1;i--){
bool flag=false;
for(int j=1;j<i;j++){
if(q[j]>q[j+1]) {
swap(q[j],q[j+1]);
flag=true;
}
}
if(!flag) break; //若一次都没进行交换,那么证明已排序好,直接break
}
}
2、选择排序
//选择排序 时间复杂度:O(n^2)
void select_sort(vector<int> &q,int n){
for(int i=1;i<n;i++){
int k=i;
for(int j=i+1;j<=n;j++){ //在后面数中找到最小的数,和当前数进行交换
if(q[j]<q[k]) k=j;
}
if(k!=i) swap(q[k],q[i]);
}
}
3、插入排序
//插入排序 时间复杂度:最坏情况下 O(n^2)
void insert_sort(vector<int> &q,int n){
for(int i=2;i<=n;i++){
int t=q[i]; //记录下当前的数
int j=i-1;
while(j>=1&&q[j]>t) q[j+1]=q[j],j--;//遍历前面的数,若比当前数值大,则往后移
q[j+1]=t; //把当前数放到比它小的后面一个坑中
}
}
4、归并排序
//归并排序 时间复杂度 nlogn
void merge_sort(vector<int> &q,int l,int r){
if(l>=r) return;
//进行分治
int mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
static vector<int> w; //静态 只分配一次内存空间
w.clear();
//进行归并操作,两个区间都有序
int i=l,j=mid+1;
while(i<=mid&&j<=r){
if(q[i]<=q[j]) w.push_back(q[i++]);
else w.push_back(q[j++]);
}
while(i<=mid) w.push_back(q[i++]);
while(j<=r) w.push_back(q[j++]);
//赋值到原数组
for(int i=l,j=0;j<w.size();i++,j++) q[i]=w[j];
}
5、快速排序
//快速排序 时间复杂度:平均 nlogn
void quick_sort(vector<int> &q,int l,int r){
if(l>=r) return;
int i=l-1,j=r+1,x=q[l+r>>1]; //x是选取的中心轴
while(i<j){
do i++;while(q[i]<x);//把小于x的数放在x的左边
do j--;while(q[j]>x); //把大于x的数放在x的右边
if(i<j) swap(q[i],q[j]);
else quick_sort(q,l,j),quick_sort(q,j+1,r);//i、j相遇,即遍历完,递归操作处理两边
}
}
6、堆排序
//堆排序
//当叶子节点值大于当前值时,需要向下压
void push_down(vector<int> &q,int n,int u){
int t=u,left=u*2,right=u*2+1; //left为左叶子节点,right为右叶子节点
if(left<=n&&q[left]>q[t]) t=left;
if(right<=n&&q[right]>q[t]) t=right;
if(t!=u){
swap(q[t],q[u]);
push_down(q,n,t);
}
}
//当父节点比当前节点值小时,需要向上推
void push_up(vector<int> &q,int u){
while(u/2&&q[u/2]<q[u]){
swap(q[u/2],q[u]);
u/=2;
}
}
void heap_sort(vector<int> &q,int n){
for(int i=1;i<=n;i++) push_up(q,i);//先构建一个大根堆
int size=n;
for(int i=1;i<=n;i++){
swap(q[1],q[size]); //把最大值放在末尾
size--;
push_down(q,size,1); //调整堆顶元素
}
}
7、计数排序
//计数排序 时间复杂度:O(n)
void counting_sort(vector<int> &q,int n){
vector<int> cnt(101,0); //假设数的大小范围是1~100
for(int i=1;i<=n;i++) cnt[q[i]]++; //记录每个数的个数
for(int i=1,k=1;i<=100;i++) //依次遍历每一个数值
while(cnt[i]){
q[k++]=i;
cnt[i]--;
}
}
8、基数排序
//基数排序
//求x的第i位
int get(int x,int i){
while(i--) x/=10;
return x%10;
}
void radix_sort(vector<int> &q,int n){
vector<vector<int>> cnt(10); //0~9都是一个桶
for(int i=0;i<3;i++){ //枚举每一位
for(int j=0;j<10;j++) cnt[j].clear(); //先清空每一个桶
for(int j=1;j<=n;j++) cnt[get(q[j],i)].push_back(q[j]);//把在当前i位相同的数放在同一个桶中
for(int j=0,k=1;j<10;j++) //遍历每一个桶
for(int x:cnt[j])
q[k++]=x;
}
}