C++内部排序算法总结(2)

本文详细介绍了桶排序和基数排序两种算法。桶排序利用均匀分布的特性将元素分配到不同桶中,通过累加前缀和确定元素位置;基数排序则针对大数值,通过转换为特定进制,逐位进行桶排序,降低时间复杂度。这两种排序算法在特定场景下具有较高的效率,且都是稳定的排序方法。
摘要由CSDN通过智能技术生成

桶排序(计数排序)

算法原理

桶排序是设置m个桶,每个桶记录从0到N中的单个元素出现的次数,即第i个桶记录数字i出现的次数,然后将桶里的数放到数组中即可。

那么如何将桶里的数放到原数组中呢?首先我们知道,1号桶的元素一定都在2号桶前面,假如有10个1和1个2,那么2的下标10 + 2 - 1,因此我们只需要算出每个数对应的前缀和,然后就能求出每个数对应的下标了。

注意:因为是按顺序遍历,因此同一个数中越靠后的数会在越上面,例如1,1's[1] = 1时放入的是1,s[1] = 2时放入的是1',因此在将桶里的数放入数组时我们需要从后往前遍历确保相同元素的相对位置不变。

代码

void backet_sort(){ // 桶排序(计数排序)
    for(int i = 0; i < n; i ++) s[q[i]] ++; // 将每个元素放到对应桶里
    for(int i = 1; i < N; i ++) s[i] += s[i - 1]; // 求出每个元素的前缀和,即可得到每个元素排序后的位置
    for(int i = n - 1; i >= 0;i --) w[-- s[q[i]]] = s[q[i]]; // 因为遍历时相同元素靠后的会被放在上面,所以从后往前遍历可以确保相同元素相对位置不变
    for(int i = 0; i < n; i ++) q[i] = w[i]; // 将数组复制回原数组
}

时间复杂度

最好情况: O ( n + m ) O(n + m) O(n+m)

平均情况: O ( n + m ) O(n + m) O(n+m)

最坏情况: O ( n + m ) O(n + m) O(n+m)

空间复杂度

O ( n + m ) O(n + m) O(n+m)

稳定

基数排序

算法原理

基数排序是桶排序的一个优化,因为当数值达到一定大小后(例如a[i] == 1 0 9 10^9 109),桶排序的时间复杂度达到了 1 0 9 10^9 109(需要安排 1 0 9 10^9 109个桶),显然是无法满足我们的需求的,因此基数排序就是将需要排序的数字转化为r进制,此时只需要r个桶,假设数组元素a[i]转换为r进制后最高有d位,那么只需要对位数从小到大进行桶排序,即可在 O ( d ( n + r ) ) O(d(n + r)) O(d(n+r))的时间复杂度内完成排序,因为 d = ⌈ l o g r n ⌉ d = \lceil log_rn\rceil d=logrn,且r比较小,因此我们可以近似认为时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

代码

void radix_sort(int d,int r){ // 基数排序,d代表最高位数,r代表进制数
    int radix = 1; // 用来取出每个数的第i为数字
    for(int i = 1; i <= d; i ++){ // 从个位开始排序
        for(int j = 0; j < r; j ++) s[j] = 0; // 清空桶
        for(int j = 0; j < n; j ++) s[q[j] / radix % r] ++; // 对第i位数进行桶排序
        for(int j = 1; j < r; j ++) s[j] += s[j - 1];
        for(int j = n - 1; j >= 0; j --) w[-- s[q[j] / radix % r]] = q[j];
        for(int j = 0; j < n; j ++) q[j] = w[j];
        radix *= r; // 进入下一位的桶排序
    }
}

时间复杂度

最好情况: O ( d ( n + r ) ) O(d(n + r)) O(d(n+r))

平均情况: O ( d ( n + r ) ) O(d(n + r)) O(d(n+r))

最坏情况: O ( d ( n + r ) ) O(d(n + r)) O(d(n+r))

空间复杂度

O ( n + r ) O(n + r) O(n+r)

稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L_Hygen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值