【基数排序介绍】

文章目录

  • 前言
  • 一、基数排序是什么?
  • 二、基数排序的步骤(LSD低位优先)
    • 1. 找出最大数的位数
    • 2. 对每一位进行排序(从最低位到最高位)
  • 三、C++实现
    • 1. 主函数:基数排序实现
  • 四、时间复杂度分析
  • 五、基数排序的适用场景
  • 六、与其他排序算法对比
  • 七、扩展:处理负数的思路
  • 总结


前言

在处理大规模整数排序问题时,比较类排序(如快速排序)可能无法发挥最优性能。本篇博客将详细介绍一种非比较类排序算法:基数排序(Radix Sort),它依赖于“按位分布”和“稳定性”的思想,对整数序列排序尤其高效。


一、基数排序是什么?

基数排序是一种非比较型排序算法,它通过“逐位排序”的方式,将整数按照位数从低位到高位(或从高位到低位)依次进行排序。每一轮排序都使用稳定的排序算法(如计数排序)对当前位进行排序,直到所有位数排序完成。

例如:
给定数组 [170, 45, 75, 90, 802, 24, 2, 66]
我们按个位 → 十位 → 百位进行排序,最终得到有序序列。


二、基数排序的步骤(LSD低位优先)

1. 找出最大数的位数

决定排序几轮。

2. 对每一位进行排序(从最低位到最高位)

采用稳定的计数排序对每一位数字排序。


三、C++实现

1. 主函数:基数排序实现

#include 
#include 
#include 
using namespace std;

// 获取最大值
int getMax(const vector<int>& arr) {
    return *max_element(arr.begin(), arr.end());
}

// 对数组按exp位(1, 10, 100...)进行计数排序
void countingSort(vector<int>& arr, int exp) {
    int n = arr.size();
    vector<int> output(n);
    int count[10] = {0};

    // 统计出现次数
    for (int i = 0; i < n; i++)
        count[(arr[i] / exp) % 10]++;

    // 累加出现次数
    for (int i = 1; i < 10; i++)
        count[i] += count[i - 1];

    // 从后向前,保持稳定性
    for (int i = n - 1; i >= 0; i--) {
        int idx = (arr[i] / exp) % 10;
        output[count[idx] - 1] = arr[i];
        count[idx]--;
    }

    // 复制回原数组
    for (int i = 0; i < n; i++)
        arr[i] = output[i];
}

// 基数排序主函数
void radixSort(vector<int>& arr) {
    int maxVal = getMax(arr);

    // 每位使用计数排序
    for (int exp = 1; maxVal / exp > 0; exp *= 10)
        countingSort(arr, exp);
}

int main() {
    vector<int> data = {170, 45, 75, 90, 802, 24, 2, 66};

    cout << "原始数组: ";
    for (int num : data) cout << num << " ";
    cout << endl;

    radixSort(data);

    cout << "排序后数组: ";
    for (int num : data) cout << num << " ";
    cout << endl;

    return 0;
}

输出结果:

原始数组: 170 45 75 90 802 24 2 66  
排序后数组: 2 24 45 66 75 90 170 802

四、时间复杂度分析

  • 时间复杂度:O(d × (n + k))

    • d:最大数的位数
    • n:元素数量
    • k:每位的可能数字数量(一般为10)
  • 空间复杂度:O(n + k)

  • 稳定性:稳定


五、基数排序的适用场景

适合如下场景:

  • 数据为非负整数定长字符串
  • 数据量大、范围分布较平均
  • 对稳定性有要求(例如数据库多关键字排序)

不适合:

  • 小数据量(快速排序更合适)
  • 含有负数(需额外处理)
  • 浮点数(需转换)

六、与其他排序算法对比

排序算法 时间复杂度(平均) 稳定性 适用场景
快速排序 O(n log n) 不稳定 普适性强,性能好
归并排序 O(n log n) 稳定 适用于链表、大规模排序
堆排序 O(n log n) 不稳定 优先队列、内存限制场景
基数排序 O(d(n + k)) 稳定 整数排序、大数据、定长字符串

七、扩展:处理负数的思路

基数排序天然只处理非负整数。若要处理负数:

  • 将负数和非负数分开
  • 分别对负数(取相反数)和非负数排序
  • 将负数结果逆序拼接在前,非负数拼接在后

总结

本文介绍了基数排序的基本原理和完整 C++ 实现。基数排序通过“按位处理”和“稳定排序”组合实现高效排序,特别适用于大量整数数据的排序。与传统比较排序相比,它在某些特定场景下能提供更优的性能。

你可能感兴趣的:(算法设计,算法,数据结构,排序算法)