数据结构与算法之基数排序算法

基数排序算法是一种非比较排序算法,其原理是根据每个元素的位值来进行排序,又称桶排序。基数排序算法可以按照位数来排序,最终得到一个有序的序列。这种排序方法的效率较高,可以处理大量数据。

基数排序的具体实现步骤如下:

  1. 将待排序的数列按照个位数先进行排序,将排序后的数列存入一个桶中。

  2. 将桶中的数列按照十位数进行排序,将排序后的数列存入一个桶中。

  3. 将桶中的数列按照百位数进行排序,将排序后的数列存入一个桶中。

  4. 重复以上步骤,直到排完最高位数后,得到一个有序的数列。

基数排序算法的时间复杂度为O(d*(n+k)),其中d为位数,n为元素数量,k为桶的数量。因为桶的数量k通常是固定的,所以基数排序的时间复杂度为O(d*n)。

基数排序算法的空间复杂度较高,需要额外的桶来存储数据。同时,基数排序算法只适用于非负整数的排序,对于其他类型的数据需要进行转换才能使用。

在这里插入图片描述

一、C 实现 基数排序算法 及代码详解

基数排序(radix sort)是一种非比较型的排序算法,根据关键词对待排序数据进行多次排序,以达到排序的目的。

下面是 C 语言实现基数排序的代码。以下代码将数组中的元素看做是整数,不包括小数。

#include <stdio.h>

void radix_sort(int arr[], int n) {
    int i, j, k;
    int cnt[10]; // 计数器,用于计算每个桶中的元素个数
    int bucket[10][n]; // 用于存放每个桶中的元素
    int max_num = arr[0]; // 计算出数组中最大的数
    int digit = 1; // 数位

    // 计算数组中最大的数
    for (i = 1; i < n; i++) {
        if (arr[i] > max_num) {
            max_num = arr[i];
        }
    }

    // 从低位到高位,对每一位进行排序
    while (max_num / digit > 0) {
        // 将数据出现的次数存储在 cnt 数组中
        for (i = 0; i < 10; i++) {
            cnt[i] = 0;
        }
        for (i = 0; i < n; i++) {
            k = (arr[i] / digit) % 10;
            bucket[k][cnt[k]] = arr[i];
            cnt[k]++;
        }

        // 重置计数器
        for (i = 0; i < 10; i++) {
            cnt[i] = 0;
        }

        // 将桶中的数据,依次放回原数组
        for (i = 0; i < 10; i++) {
            for (j = 0; j < cnt[i]; j++) {
                arr[cnt[i] * i + j] = bucket[i][j];
            }
        }

        // 位数增加
        digit *= 10;
    }
}

int main() {
    int arr[] = {32, 56, 12, 91, 18, 74, 8, 47, 3, 65};
    int n = sizeof(arr) / sizeof(arr[0]);
    int i;

    printf("Original array: ");
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    radix_sort(arr, n);

    printf("\nSorted array: ");
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    return 0;
}

在上述代码中,首先计算数组中最大的数,然后循环进行排序,从低位到高位。对于每一位,首先统计每个桶中的元素个数,然后将每个元素放到对应的桶中,最后从每个桶中取出元素,依次放回原数组中。需要注意的是,位数增加时需要将 digit 乘以 10。

基数排序的时间复杂度为 O(kn),其中 k 表示数字的位数,n 表示数组的大小。当 k 不大于 log10n 时,基数排序的效率较高。

值得注意的是,基数排序使用的是计数排序的思想,因此也可以使用计数排序的方式来实现。这种方式比较简单,不需要使用桶这个数据结构。

在这里插入图片描述

二、C++ 实现 基数排序算法 及代码详解

基数排序(Radix Sort)是一种非比较排序算法,它将所有待比较数值统一为同样的数位长度,然后从低位开始,依次进行排序。基数排序的实现可以使用桶排序或计数排序。

以下是 C++ 实现基数排序算法的代码:

#include <iostream>
#include <vector>

using namespace std;

// 获取 num 的第 d 位数字(从低位开始)
int getDigit(int num, int d) {
    for (int i = 1; i < d; i++) {
        num /= 10;
    }
    return num % 10;
}

// 基数排序
void radixSort(vector<int>& nums) {
    if (nums.empty()) {
        return;
    }

    int n = nums.size();
    int maxNum = *max_element(nums.begin(), nums.end()); // 获取最大数
    int maxDigit = to_string(maxNum).length(); // 获取最大数的位数

    vector<vector<int>> buckets(10); // 一维是桶的编号,二维是桶里的元素

    for (int d = 1; d <= maxDigit; d++) {
        // 将 nums 中的数放入对应的桶中
        for (int i = 0; i < n; i++) {
            int digit = getDigit(nums[i], d);
            buckets[digit].push_back(nums[i]);
        }

        // 将桶中的数依次放入 nums 中
        int idx = 0;
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < buckets[i].size(); j++) {
                nums[idx++] = buckets[i][j];
            }
            buckets[i].clear(); // 清空桶
        }
    }
}

// 测试
int main() {
    vector<int> nums = {45, 2, 78, 23, 56, 89, 12, 67};
    radixSort(nums);
    for (int num : nums) {
        cout << num << " ";
    }
    cout << endl;
    return 0;
}

代码中,getDigit 函数用于获取一个数的第 d 位数字,从低位开始。radixSort 函数是基数排序的核心代码,其中:

  1. 首先获取最大数和最大数的位数。
  2. 创建 10 个桶,一维是桶的编号,二维是桶里的元素。依次对每一位进行排序:
    1. 将 nums 中的数放入对应的桶中;
    2. 将桶中的数依次放入 nums 中。
  3. 返回排好序的 nums 数组。

最后,在 main 函数中测试基数排序的实现效果。

在这里插入图片描述

三、Java 实现 基数排序算法 及代码详解

基数排序算法是一种非比较排序算法,它将待排序的元素按照位数切割成不同的数字,然后按照每个数字分别进行排序。这个过程中,需要使用到桶排序来对每个位上的数字进行排序。基数排序算法的时间复杂度为O(d*(n+m)),其中d表示位数,n表示元素个数,m表示每个位上数字的取值范围。

以下是基数排序算法的Java实现和详细注释:

public class RadixSort {
    public static void radixSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        // 找到数组中最大的数
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        // 用于存放每个位上的数字
        int[] count = new int[10];
        // 用于存放排序后的结果
        int[] temp = new int[arr.length];
        // 计算各个位上数字的出现次数
        for (int i = 1; max / i > 0; i *= 10) {
            Arrays.fill(count, 0);
            for (int j = 0; j < arr.length; j++) {
                int num = arr[j] / i % 10;
                count[num]++;
            }
            // 计算各个数字在temp数组中的位置
            for (int j = 1; j < count.length; j++) {
                count[j] += count[j - 1];
            }
            // 将arr数组中的元素按照对应的位上的数字排好序放入temp数组中
            for (int j = arr.length - 1; j >= 0; j--) {
                int num = arr[j] / i % 10;
                temp[--count[num]] = arr[j];
            }
            // 将排序后的结果复制回原数组
            System.arraycopy(temp, 0, arr, 0, arr.length);
        }
    }

    public static void main(String[] args) {
        int[] arr = {3, 8, 1, 5, 9, 4, 6, 7, 2, 0};
        radixSort(arr);
        System.out.println(Arrays.toString(arr)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    }
}

上述代码中,首先用一个循环找到数组中最大的数max,然后再对每个位上的数字进行排序,排序的过程中用到了桶排序的思想,具体步骤如下:

  • 定义一个长度为10的数组count,用于存放每个位上数字的出现次数;
  • 定义一个长度和原数组大小相同的数组temp,用于存放排序后的结果;
  • 对于每个数字的每个位,计算出该位上数字的出现次数,记录在count数组中;
  • 计算各个数字在temp数组中的位置;
  • 将arr数组中的元素按照对应的位上的数字排好序放入temp数组中;
  • 将排序后的结果复制回原数组。

重复上面的步骤d次,其中d表示最大数的位数,每一次排序都会使数组更加有序。

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值