【排序模板】

前言

比较排序和非比较排序模板。
以下均不涉及排序原理, 纯粹就是代码。 代码非常简洁。

以下均是C++代码(更偏向C)实现,
看不懂怎么办? 复制代码给ChatGPT解读即可, 堆排序需要补数据结构堆的知识。

比较排序:冒泡排序,选择排序,插入排序,希尔排序,堆排序,归并排序,快速排序。
非比较排序:计数排序,基数排序,桶排序。

本篇目前更新比较排序模板。
测试链接:排序

冒泡排序

时间复杂度: O ( n 2 ) O(n^2) O(n2)。 不推荐使用。

#include<bits/stdc++.h>
using namespace std;
//测试链接:https://www.luogu.com.cn/problem/P1177
const int N = 1e6+10;//1e4数据量可以使用,>1e5会超时。
int q[N],n;

void bubbleSort(int *q,int n){
    for(int i=0;i<n-1;i++){
        for(int j=0;j<n-1-i;j++){
            if(q[j+1]<q[j]){
                swap(q[j+1], q[j]);
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        scanf("%d",q+i);
    }
    bubbleSort(q,n);
    for(int i=0;i<n-1;++i){
        printf("%d ",q[i]);
    }
    printf("%d\n",q[n-1]);
    return 0;
}

选择排序

时间复杂度: O ( n 2 ) O(n^2) O(n2)。 不推荐使用。

#include<bits/stdc++.h>
using namespace std;
//测试链接:https://www.luogu.com.cn/problem/P1177
const int N = 1e6+10;
int q[N],n;
void selectionSort(int *q,int n){
    int min_idx = 0;
    for(int i=0;i<n-1;i++){
        min_idx = i;
        for(int j=i+1;j<n;++j){
            if(q[j]<q[min_idx]) min_idx = j;
        }
        std::swap(q[min_idx],q[i]);
    }    
}
int main(){
    scanf("%d", &n);
    for(int i=0;i<n;i++){
        scanf("%d", q+i);
    }
    selectionSort(q,n);
    for(int i=0;i<n-1;++i){
        printf("%d ",q[i]);
    }
    printf("%d\n",q[n-1]);
    return 0;
}

插入排序

时间复杂度: O ( n 2 ) O(n^2) O(n2), 小数据量或者接近有序非常好用。

#include<bits/stdc++.h>
using namespace std;
//测试链接:https://www.luogu.com.cn/problem/P1177
const int N = 1e6+10;
int q[N], n;
void insertionSort(int *q,int n){
    for(int i=1,j;i<n;i++){
        j = i - 1;
        int tmp = q[i];
        while(j>=0&&q[j]>tmp){
            q[j+1] = q[j];
            j--;
        }
        q[j+1]=tmp;
    }
}
int main(){
    scanf("%d", &n);
    for(int i=0;i<n;i++){
        scanf("%d", q+i);
    }
    insertionSort(q,n);
    for(int i=0;i<n-1;i++){
        printf("%d ",q[i]);
    }
    printf("%d\n",q[n-1]);
    return 0;
}

希尔排序

时间复杂度:平均 O ( n 1.3 ) − O ( n 1.5 ) O(n^{1.3}) - O(n^{1.5}) O(n1.3)O(n1.5), 最坏 O ( n 2 ) O(n^2) O(n2), 能通过测试。
时间复杂度取决于步长序列, 有多种选择方式可以自行了解一下。

优点是好写,运用插入排序的思想和步长序列。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int q[N],n;

void shellSort(int *q, int n) {
    for (int gap = n / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            int temp = q[i];
            int j = i - gap;
            while (j >= 0 && q[j] > temp) {
                q[j+gap] = q[j];
                j -= gap;
            }
            q[j+gap] = temp;
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>q[i];
    }
    shellSort(q,n);
    for(int i=0;i<n-1;i++){
        cout<<q[i]<<" ";
    }
    cout<<q[n-1]<<'\n';
    return 0;
}

堆排序

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
优点:堆排序稳定,平均,最差,最好都是 O ( n l o g n ) O(nlogn) O(nlogn), 数组可以模拟堆, 原地排序。
不依赖数据。

缺点: 同等复杂度常数时间不如快速排序, 需要掌握数据结构堆的知识, 实现比较复杂(容易写错)。

#include<bits/stdc++.h>
using namespace std;
//测试链接:https://www.luogu.com.cn/problem/P1177
const int N = 1e6+10;
int q[N],n;

void heapify(int *q,int size,int i){
    int l=i*2+1;
    while(l<size){
        int best = l+1<size&&q[l+1]>q[l]?l+1:l;
        best = q[best]>q[i]?best:i;
        if(best==i) return ;
        std::swap(q[i],q[best]);
        i = best;
        l = i*2+1;
    }
}
int main(){
    scanf("%d", &n);
    for(int i=0;i<n;i++){
        scanf("%d", &q[i]);
    }
    for(int i=(n-1)>>1;i>=0;i--){
        heapify(q,n,i);
    }
    int size = n;
    while(size>0){
        swap(q[0],q[--size]);
        heapify(q,size,0);
    }
    for(int i=0;i<n-1;i++){
        printf("%d ",q[i]);
    }
    printf("%d\n",q[n-1]);
    return 0;
}

归并排序

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
优点:归并排序具有稳定性, 时间复杂度严格控制在 O ( n l o g n ) O(nlogn) O(nlogn)
缺点:需要辅助数组。

#include<bits/stdc++.h>
using namespace std;
//测试链接:https://luogu.com.cn/problem/P1177
const int N = 1e6+10;
int q[N],n;
int help[N];//辅助数组

//时间复杂度:$O(nlogn)$
static void merge_sort(int *q,int l,int r){
    if(l>=r) return ;
    int m = l+((r-l)>>1);
    //递归树高度O(logn)
    merge_sort(q,l,m);
    merge_sort(q,m+1,r);
    //合并O(n)
    //l,m,r
    int a=l,b=m+1,i=l;
    while(a<=m&&b<=r) help[i++]=q[a]<=q[b]?q[a++]:q[b++];
    while(a<=m) help[i++]=q[a++];
    while(b<=r) help[i++]=q[b++];
    for(i=l;i<=r;i++) q[i] = help[i];
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",q+i);
    merge_sort(q,0,n-1);
    for(int i=0;i<n-1;i++) printf("%d ",q[i]);
    printf("%d\n",q[n-1]); 
    return 0;
}

快速排序

掌握随机化取数的快速排序即可。
非常快, 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn), 原地排序空间复杂度: O ( l o g n ) O(logn) O(logn)

//快速排序模板
//1. 朴素快排和随机化快排
//2. 三向切分快排速度
#include<bits/stdc++.h>
using namespace std;
//测试链接:https://www.luogu.com.cn/problem/P1177
const int N = 1e6+10;
int n, q[N];


void quick_sort_class(int *q,int l,int r){
    if(l>=r) return ;
    int x = q[l+rand()%(r-l+1)];//q[l]随机取左区间的数
    int i=l-1, j=r+1;
    while(i<j){
        do i++; while(q[i]<x);
        do j--; while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    quick_sort_class(q,l,j);
    quick_sort_class(q,j+1,r);
}

//三向切分快排,应对大量重复值的情况。
int first ,last;
//int* q
static void quick_sort(int* q,int l,int r){
    if(l>=r) return ;
    int x = q[l+rand()%(r-l+1)];
    first=l-1,last=r+1;
    int i=l;
    while(i<last){
        if(q[i]==x) i++;
        else if(q[i]<x) swap(q[++first],q[i++]);
        else swap(q[--last],q[i]);
    }
    quick_sort(q,l,first);
    quick_sort(q,last,r);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",q+i);
    }
    quick_sort_class(q,0,n-1);//60分,会超时。随机化取数:100分
    //quick_sort(q,0,n-1);//三向切分
    for(int i=0;i<n-1;i++){
        printf("%d ", q[i]);
    }
    printf("%d\n",q[n-1]);
    return 0;
}

补充

非比较排序等期末考试结束, 写完模板就补充上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值