数据结构之排序

这里有一些看起来比较好看的排序代码模板~

快排

void q_sort(int l, int r)
{
    int i = l, j = r;
    if(l > r) return;
    while(i < j)
    {
        while(a[j] >= a[l] && i < j)
            j --;
        while(a[i] <= a[l] && i < j)
            i ++;
        if(i < j) swap(a[i], a[j]);
    }
    swap(a[i], a[l]);
    q_sort(l, i - 1);
    q_sort(i + 1, r);
}

归并排序

int tmp[N], a[N], n;
//这里为需要背诵的部分,要求:给一个相关题目,能快速写出该模板并调试通过。
//归并排序
void merge_sort(int q[], int l, int r)
{
    //递归出口
    if (l >= r) return;
    
    //第一步,分成两个子区间
    int mid =  l + r >> 1;
    
    //第二部,递归处理子区间
    //要注意这里用的mid和mid+1来划分两区间,建议不要用mid-1和mid来划分
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);
    
    //第三步,合并排序好的子区间
    //tips:k为tmp下标,i和j为两个子区间起始位置
    int k = 0, i = l, j = mid + 1;
    //排序好的两边取大小,暂存数组tmp挑小的取
    while (i <= mid && j <= r) 
    {
        if (q[i] <= q[j]) tmp[k++] = q[i++];
        else tmp[k++] = q[j++];
    }
    //很可能存在有一子区间没有比较完,由于该区间是排好序的,后面的没比较完,说明都是最大的,直接往tmp后面加即可。
    while (i <= mid) tmp[k++] = q[i++];
    while (j <= r) tmp[k++] = q[j++];
    //在[l, r]范围中,将tmp数组存的有序值赋给q数组完排序,注意<=r的等号不要漏
    for (int i = l, j =0; i <= r; i++, j++) q[i] = tmp[j];
}

堆排序

1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端

2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1

3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

注意:升序用大根堆,降序就用小根堆(默认为升序)

int cnt;
int h[N], a[N], n;
void down(int x)
{
    int t = x;
    if (x * 2 <= cnt && h[x * 2] < h[t])
        t = x * 2;
    if (x * 2 + 1 <= cnt && h[x * 2 + 1] < h[t])
        t = x * 2 + 1;
    if (x != t)
    {
        swap(h[x], h[t]);
        down(t);
    }
}
void heap_sort(int l, int r)
{
    cnt = 0;
    for (int i = l; i <= r; i++)
    {
        h[++cnt] = a[i];
    }
    for (int i = cnt / 2; i; i--)
    {
        down(i);
    }
    int k = l;
    while (cnt)
    {
        a[k++] = h[1];
        h[1] = h[cnt--];
        down(1);
    }
}
​
int cnt;
int h[N];
void down(int x)
{
    int t = x;
    if (x * 2 <= cnt && h[x * 2] > h[t])
        t = x * 2;
    if (x * 2 + 1 <= cnt && h[x * 2 + 1] > h[t])
        t = x * 2 + 1;
    if (x != t)
    {
        swap(h[x], h[t]);
        down(t);
    }
}
void heap_sort(int l, int r)
{
    cnt = 0;
    for (int i = l; i <= r; i++)
    {
        h[++cnt] = a[i];
    }
    for (int i = cnt / 2; i; i--)
    {
        down(i);
    }
    int k = r;
    while (cnt)
    {
        a[k --] = h[1];
        h[1] = h[cnt--];
        down(1);
    }
}

计数排序

计算ai的数量,然后算它在数组中是第几小的,然后把第几小赋给b数组作为下标,同时b下标=a中的值,最后整理下

int a[N], h[N+50];
int b[N];
int n;//如果出现负数 (-10000,10000)整体右移 x+10000 (0,20000)
//如果小数 整体*100
void counting_sort() 
{
    int w = 100050;
    memset(h, 0, sizeof h);
    for (int i = 0; i < n; i++) h[a[i]]++;
    for (int i = 1; i <= w; i++) h[i] += h[i - 1];
    for (int i = n-1; i >= 0; i--) b[h[a[i]]--] = a[i];
    for(int i=1;i<=n;i++)
    a[i-1]=b[i];
}

桶排序

桶排序的核心思想就是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶排序完之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。

int n, w = 100000, a[N];
vector<int> bucket[N];
​
void insert_sort(vector<int>& A) 
{
    for (int i = 1; i < A.size(); i++) 
    {
        int key = A[i];
        int j = i - 1;
        while (j >= 0 && A[j] > key) 
        {
            A[j + 1] = A[j];
            j--;
        }
        A[j + 1] = key;
    }
}
void bucket_sort() 
{
    int bucket_size = w / n + 1;
    for (int i = 0; i < n; i++) 
    {
        bucket[i].clear();
    }
    for (int i = 0; i < n; i++) 
    {
        bucket[a[i] / bucket_size].push_back(a[i]);
    }
    int p = 0;
    for (int i = 0; i < n; i++) 
    {
        insert_sort(bucket[i]);
        for (int j = 0; j < bucket[i].size(); j++) 
        {
            a[p++] = bucket[i][j];
        }
    }
}

基数排序

const int N = 100010;
const int W = 100010;
const int K = 100;
int n, w[K], k, cnt[W];
struct Element {
    int key[K];
    bool operator<(const Element& y) const {
        for (int i = 1; i <= k; ++i) {
            if (key[i] == y.key[i]) continue;
            return key[i] < y.key[i];
        }
        return false;
    }
} a[N], b[N];
void counting_sort(int p) {
    memset(cnt, 0, sizeof(cnt));
    for (int i = 1; i <= n; ++i) ++cnt[a[i].key[p]];
    for (int i = 1; i <= w[p]; ++i) cnt[i] += cnt[i - 1];
    for (int i = n; i >= 1; --i) 
    b[cnt[a[i].key[p]]--] = a[i];
    memcpy(a, b, sizeof(a));
}
void radix_sort() {
    for (int i = k; i >= 1; --i) {
        counting_sort(i);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值