用户登录
用户注册

分享至

认识下基数排序

  • 作者: 达?矢抾哆拉?
  • 来源: 51数据库
  • 2022-09-20
导读 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
1. 基数排序 vs 计数排序 vs 桶排序

基数排序有两种方法:

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

  1. 基数排序:根据键值的每位数字来分配桶;
  2. 计数排序:每个桶只存储单一键值;
  3. 桶排序:每个桶存储一定范围的数值;
2. LSD 基数排序动图演示

代码实现:

JavaScript

实例

//LSD Radix Sort
var counter = [];
function radixSort(arr, maxDigit) {
    var mod = 10;
    var dev = 1;
    for (var i = 0; i < maxdigit;="" i++,="" dev="" *="10," mod="" *="10)" {="" for(var="" j="0;" j="">< arr.length;="" j++)="" {="" var="" bucket="parseInt((arr[j]" %="" mod)="" dev);="" if(counter[bucket]="=null)" {="" counter[bucket]="[];" }="" counter[bucket].push(arr[j]);="" }="" var="" pos="0;" for(var="" j="0;" j="">< counter.length;="" j++)="" {="" var="" value="null;" if(counter[j]!="null)" {="" while="" ((value="counter[j].shift())" !="null)" {="" arr[pos++]="value;" }="" }="" }="" }="" return="" arr;="">
Java

实例

/**
 * 基数排序
 * 考虑负数的情况还可以参考: https://code.i-harness.com/zh-CN/q/e98fa9
 */
public class RadixSort implements IArraySort {

    @Override
    public int[] sort(int[] sourceArray) throws Exception {
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        int maxDigit = getMaxDigit(arr);
        return radixSort(arr, maxDigit);
    }

    /**
     * 获取最高位数
     */
    private int getMaxDigit(int[] arr) {
        int maxValue = getMaxValue(arr);
        return getNumLenght(maxValue);
    }

    private int getMaxValue(int[] arr) {
        int maxValue = arr[0];
        for (int value : arr) {
            if (maxValue < value)="" {="" maxvalue="value;" }="" }="" return="" maxvalue;="" }="" protected="" int="" getnumlenght(long="" num)="" {="" if="" (num="=" 0)="" {="" return="" 1;="" }="" int="" lenght="0;" for="" (long="" temp="num;" temp="" !="0;" temp="" 10)="" {="" lenght++;="" }="" return="" lenght;="" }="" private="" int[]="" radixsort(int[]="" arr,="" int="" maxdigit)="" {="" int="" mod="10;" int="" dev="1;" for="" (int="" i="0;" i="">< maxdigit;="" i++,="" dev="" *="10," mod="" *="10)" {="" 考虑负数的情况,这里扩展一倍队列数,其中="" [0-9]对应负数,[10-19]对应正数="" (bucket="" +="" 10)="" int[][]="" counter="new" int[mod="" *="" 2][0];="" for="" (int="" j="0;" j="">< arr.length;="" j++)="" {="" int="" bucket="((arr[j]" %="" mod)="" dev)="" +="" mod;="" counter[bucket]="arrayAppend(counter[bucket]," arr[j]);="" }="" int="" pos="0;" for="" (int[]="" bucket="" :="" counter)="" {="" for="" (int="" value="" :="" bucket)="" {="" arr[pos++]="value;" }="" }="" }="" return="" arr;="" }="" *="" *="" 自动扩容,并保存数据="" *="" *="" @param="" arr="" *="" @param="" value="" */="" private="" int[]="" arrayappend(int[]="" arr,="" int="" value)="" {="" arr="Arrays.copyOf(arr," arr.length="" +="" 1);="" arr[arr.length="" -="" 1]="value;" return="" arr;="" }="">
PHP

实例

function radixSort($arr, $maxDigit = null)
{
    if ($maxDigit === null) {
        $maxDigit = max($arr);
    }
    $counter = [];
    for ($i = 0; $i < $maxdigit;="" $i++)="" {="" for="" ($j="0;" $j="">< count($arr);="" $j++)="" {="" preg_match_all('/\d/',="" (string)="" $arr[$j],="" $matches);="" $numarr="$matches[0];" $lentmp="count($numArr);" $bucket="array_key_exists($lenTmp" -="" $i="" -="" 1,="" $numarr)="" intval($numarr[$lentmp="" -="" $i="" -="" 1])="" :="" 0;="" if="" (!array_key_exists($bucket,="" $counter))="" {="" $counter[$bucket]="[];" }="" $counter[$bucket][]="$arr[$j];" }="" $pos="0;" for="" ($j="0;" $j="">< count($counter);="" $j++)="" {="" $value="null;" if="" ($counter[$j]="" !="=" null)="" {="" while="" (($value="array_shift($counter[$j]))" !="=" null)="" {="" $arr[$pos++]="$value;" }="" }="" }="" }="" return="" $arr;="">
C++

实例

int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int maxData = data[0];              ///< 最大数="" 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。="" for="" (int="" i="1;" i="">< n;="" ++i)="" {="" if="" (maxdata="">< data[i])="" maxdata="data[i];" }="" int="" d="1;" int="" p="10;" while="" (maxdata="">= p)
    {
        //p *= 10; // Maybe overflow
        maxData /= 10;
        ++d;
    }
    return d;
/*    int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n;="" ++i)="" {="" while(data[i]="">= p)
        {
            p *= 10;
            ++d;
        }
    }
    return d;*/
}
void radixsort(int data[], int n) //基数排序
{
    int d = maxbit(data, n);
    int *tmp = new int[n];
    int *count = new int[10]; //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d;="" i++)="" 进行d次排序="" {="" for(j="0;" j="">< 10;="" j++)="" count[j]="0;" 每次分配前清空计数器="" for(j="0;" j="">< n;="" j++)="" {="" k="(data[j]" radix)="" %="" 10;="" 统计每个桶中的记录数="" count[k]++;="" }="" for(j="1;" j="">< 10;="" j++)="" count[j]="count[j" -="" 1]="" +="" count[j];="" 将tmp中的位置依次分配给每个桶="" for(j="n" -="" 1;="" j="">= 0; j--) //将所有桶中记录依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n;="" j++)="" 将临时数组的内容复制到data中="" data[j]="tmp[j];" radix="radix" *="" 10;="" }="" delete="" []tmp;="" delete="" []count;="">
C

实例

#include
#define MAX 20
//#define SHOWPASS
#define BASE 10

void print(int *a, int n) {
  int i;
  for (i = 0; i < n;="" i++)="" {="" printf("%d\t",="" a[i]);="" }="" }="" void="" radixsort(int="" *a,="" int="" n)="" {="" int="" i,="" b[max],="" m="a[0]," exp="1;" for="" (i="1;" i="">< n;="" i++)="" {="" if="" (a[i]=""> m) {
      m = a[i];
    }
  }

  while (m / exp > 0) {
    int bucket[BASE] = { 0 };

    for (i = 0; i < n;="" i++)="" {="" bucket[(a[i]="" exp)="" %="" base]++;="" }="" for="" (i="1;" i="">< base;="" i++)="" {="" bucket[i]="" +="bucket[i" -="" 1];="" }="" for="" (i="n" -="" 1;="" i="">= 0; i--) {
      b[--bucket[(a[i] / exp) % BASE]] = a[i];
    }

    for (i = 0; i < n;="" i++)="" {="" a[i]="b[i];" }="" exp="" *="BASE;" #ifdef="" showpass="" printf("\npass="" :="" ");="" print(a,="" n);="" #endif="" }="" }="" int="" main()="" {="" int="" arr[max];="" int="" i,="" n;="" printf("enter="" total="" elements="" (n=""><= %d)="" :="" ",="" max);="" scanf("%d",="" &n);="" n="n">< max="" n="" :="" max;="" printf("enter="" %d="" elements="" :="" ",="" n);="" for="" (i="0;" i="">< n;="" i++)="" {="" scanf("%d",="" &arr[i]);="" }="" printf("\narray="" :="" ");="" print(&arr[0],="" n);="" radixsort(&arr[0],="" n);="" printf("\nsorted="" :="" ");="" print(&arr[0],="" n);="" printf("\n");="" return="" 0;="">
Lua

实例

-- 获取表中位数
local maxBit = function (tt)
    local weight = 10;      -- 十進制
    local bit = 1;
   
    for k, v in pairs(tt) do
        while v >= weight do
            weight = weight * 10;
            bit = bit + 1;  
        end
    end
    return bit;
end
-- 基数排序
local radixSort = function (tt)
    local maxbit = maxBit(tt);

    local bucket = {};
    local temp = {};
    local radix = 1;
    for i = 1, maxbit do
        for j = 1, 10 do
            bucket[j] = 0;      --- 清空桶
        end
        for k, v in pairs(tt) do
            local remainder = math.floor((v / radix)) % 10 + 1;    
            bucket[remainder] = bucket[remainder] + 1;      -- 每個桶數量自動增加1
        end
       
        for j = 2, 10 do
            bucket[j] = bucket[j - 1] + bucket[j];  -- 每个桶的数量 = 以前桶数量和 + 自个数量
        end
        -- 按照桶的位置,排序--这个是桶式排序,必须使用倒序,因为排序方法是从小到大,顺序下来,会出现大的在小的上面清空。
        for k = #tt, 1, -1 do
            local remainder = math.floor((tt[k] / radix)) % 10 + 1;
            temp[bucket[remainder]] = tt[k];
            bucket[remainder] = bucket[remainder] - 1;
        end
        for k, v in pairs(temp) do
            tt[k] = v;
        end
        radix = radix * 10;
    end
end;
软件
前端设计
程序设计
Java相关