排序算法之基数排序

概述

首先从多排序码排序开始介绍基数排序。以扑克牌排序为例。每张扑克牌有两个“排序码”:花色和面值。其有序关系为:

  • 花色: <<<
  • 面值: 2<3<4<5<6<7<8<9<10<J<Q<K<A

如果把所有扑克牌排成以下次序:
♣2,…,♣A,♦2,…,♦A,♥2,…,♥A,♠2,…,♠A
这就是多排序码排序。排序后形成的有序序列叫做字典有序序列。
一般情况下,假定有一个n个元素的序列 V0V1...Vn1 ,且每个元素 Vi 中含有 d 个排序码(K1,K2,...,Kd)
实现多排序码排序有两种常用的方法:一种方法是最高位优先(Most Significant Digit first,MSD),一种方法是最低位优先(Least Significant Digit first,LSD)。

MSD基数排序

基本思想

首先根据最高位关键码 K1 得到若干对象组,对象组中的每个对象都有对象都有相同的关键码K1;再分别对每组中的对象根据关键码 K2 进行排序,按K2值的不同,再分成若干个更小的子组,子组中的对象具有相同的 K1 K2 值;依次重复,直到对关键码 Kd 完成排序为止。最后,把所有子组中的对象依次连接起来,就得到一个有序的对象序列。

代码

private int radix = 10;//基数,默认十进制
private void msdRadixSort(int[] a, int left, int right, int d) {
    int[] auxArray = new int[a.length];// 辅助数组,存放按桶分配的结果,根据count[]预先算定各桶元素的使用位置
    int[] count = new int[right-left+1];// 辅助数组,记录当处理第i位时各个元素的第i位取值为k的有多少个。
    int i, j;
    if (d > 0) {//位数尚未处理完
        //初始化count数组
        for (i = 0; i < radix; i++)
            count[i] = 0;
        //统计各桶元素的个数
        for (i = left; i <= right; i++)
            count[getDigit(a[i], d)]++;
        //计算各桶元素的存放位置
        for (i = 1; i < radix; i++)
            count[i] = count[i] + count[i - 1];
        //将待排序列中的元素按位值分配到各个桶中,存于辅助数组auxArray中
        for (i = left; i <= right; i++) {
            j = getDigit(a[i], d);  //取元素a[i]第d位的值
            auxArray[count[j] - 1] = a[i];  //按预先计算位置存放
            count[j]--;     //计数器减1
        }

        //从辅助数组顺序写入原数组
        for (i = left, j = 0; i <= right; i++, j++)
            a[i] = auxArray[j];

        //按桶递归对d-1位处理
        for (j = 0; j < radix - 1; j++) {
            int p1 = count[j];  //取桶开始端
            int p2 = count[j + 1] - 1;  //取桶结束端
            if (p1 < p2 && d > 1)
                msdRadixSort(a, p1, p2, d - 1);//对桶内元素进行基数排序
        }
    }
}

LSD基数排序

基本思想

首先依据最低位排序码 Kd 对所有元素进行一趟排序,然后依据次低位排序码 Kd1 对上一趟排序的结果再排序,依次重复,直到依据排序码 K1 最后一趟排序完成,就可以得到一个有序的序列。使用这种排序方法对每个排序码进行排序时,不需要再分组,而是整个元素组都参加排序。

代码

private void lsdRadixSort(int[] a, int left, int right, int d) {
    int[] auxArray = new int[a.length];// 辅助数组,存放按桶分配的结果,根据count[]预先算定各桶元素的使用位置
    int[] count = new int[right-left+1];// 辅助数组,记录当处理第i位时各个元素的第i位取值为k的有多少个。
    int i, j, k;
    for (k = 1; k <= d; k++) {
        for (i = 0; i < radix; i++)
            count[i] = 0;
        for (i = left; i <= right; i++)
            count[getDigit(a[i], k)]++;
        for (i = 1; i < radix; i++)
            count[i] = count[i] + count[i - 1];
        for (i = left; i <= right; i++) {
            j = getDigit(a[i], k);
            auxArray[count[j] - 1] = a[i];
            count[j]--;
        }
        // 从辅助数组顺序写入原数组
        for (i = left, j = 0; i <= right; i++, j++)
            a[i] = auxArray[j];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值