优质广告供应商

广告是为了更好地支持作者创作

基数排序 radix sort

基数排序

  • 时间复杂度:平均、最好、最坏都为O(k*n),其中k为常数,n为元素个数
  • 空间复杂度:O(n+k)
  • 稳定性:稳定

算法解析:

  • 基数排序的思想就是先排好各位,然后排好各位的基础上排十位,以此类推,直到遍历最高位 次,排序结束(仔细理解最后一句话)
  • 基数排序不是比较排序,而是通过分配和收集的过程来实现排序
  • 初始化10个桶(固定的),桶下标为0-9
  • 通过得到待排序数字的个十百等位的数字,把这个数字对应的item放到对应的桶中
  • 基数排序有两种排序方式:LSD和MSD,最小位优先(从右边开始)和最大位优先(从左边开始)

动画演示

radixSort.gif

OC代码实现 LSD

- (void)radixSort:(NSMutableArray *)arr {// [@1,@2,@19,...]
    
    NSNumber *max = arr[0];
    for (NSNumber *num in arr) {
        if ([num intValue] > [max intValue]) {
            max = num;
        }
    }
    int position = 0;
    int maxDigital = [max intValue];
    while (maxDigital > 0) {
        maxDigital /= 10;
        position++;
    }
    NSMutableArray *arrMutable = [NSMutableArray array];
    for (int i = 0; i<10; i++) {
        [arrMutable addObject:[NSMutableArray array]];
    }
    
    int divisor = 1;//除数
    for (int i = 0; i<position; i++) {
        for (NSNumber *n in arr) {
            int digital = [n intValue];
            int lastN = (digital/divisor)%10;
            [((NSMutableArray *)arrMutable[lastN]) addObject:n];
        }
        int increase = 0;
        for (int j = 0; j<arrMutable.count; j++) {
            for (int k = 0; k<((NSArray *)arrMutable[j]).count; k++) {
                arr[increase] = arrMutable[j][k];
                increase++;
            }
        }
        [arrMutable makeObjectsPerformSelector:@selector(removeAllObjects)];
        divisor *= 10;
    }
}

Swift实现 LSD

func radixSort(arr : inout [Int]) -> Void {
    //0-9,10个桶
    var bucket = [[Int]]()
    for _ in 0..<10 {
        bucket.append([Int]())
    }
    //获取最大值
    var max = 0
    for (_,item) in arr.enumerated() {
        if max < item {
            max = item
        }
    }
    //获取最高位
    var position = 0
    while max > 0 {
        max = max / 10
        position += 1
    }

    var divisor = 1
    var num = 0//位上的数字
    for _ in 0..<position {
        for (_,item) in arr.enumerated() {//入桶
            num = (item / divisor) % 10
            bucket[num].append(item)
        }
        //遍历完成,需要重置arr
        var k = 0
        for i in 0..<bucket.count {//把有数据的桶串起来
            while !bucket[i].isEmpty {
                arr[k] = bucket[i].remove(at: 0)
                k += 1
            }
        }
        divisor = divisor * 10 //位:1 10 100
    }
}

以下代码实现均来源于网络,未验证

c++实现

/*
*求数据的最大位数,决定排序次数
*/
int maxbit(int data[], int n) 
{
    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[n];
    int count[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;
    }

JavaScript 代码实现

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 代码实现

public class RadixSort {
private static void radixSort(int[] array,int d)
{
    int n=1;//代表位数对应的数:1,10,100...
    int k=0;//保存每一位排序后的结果用于下一位的排序输入
    int length=array.length;
    int[][] bucket=new int[10][length];//排序桶用于保存每次排序后的结果,这一位上排序结果相同的数字放在同一个桶里
    int[] order=new int[length];//用于保存每个桶里有多少个数字
    while(n<d)
    {
        for(int num:array) //将数组array里的每个数字放在相应的桶里
        {
            int digit=(num/n)%10;
            bucket[digit][order[digit]]=num;
            order[digit]++;
        }
        for(int i=0;i<length;i++)//将前一个循环生成的桶里的数据覆盖到原数组中用于保存这一位的排序结果
        {
            if(order[i]!=0)//这个桶里有数据,从上到下遍历这个桶并将数据保存到原数组中
            {
                for(int j=0;j<order[i];j++)
                {
                    array[k]=bucket[i][j];
                    k++;
                }
            }
            order[i]=0;//将桶里计数器置0,用于下一次位排序
        }
        n*=10;
        k=0;//将k置0,用于下一轮保存位排序结果
    }
}

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;
}

优质广告供应商

广告是为了更好地支持作者创作

推荐阅读更多精彩内容

  • 【算法】基数排序 前面介绍的各类排序方法(快速排序,归并排序,插入排序等)都是建立在关键字比较的基础上,而分配类排...
    0与1的邂逅阅读 869评论 0 1
  • 基本思想: 基数排序是一种有意思的排序,在看过其它比较排序后,基数排序真的很有意思。 基数排序(Radix Sor...
    NEXTFIND阅读 15,800评论 1 10
  • 优质广告供应商

    广告是为了更好地支持作者创作

  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 911评论 0 2
  • 基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序...
    Awanwan阅读 407评论 0 0
  • 一些概念 该算法是稳定的排序法; 在所有的情况下,时间复杂度均为O(nlog(p)k),空间复杂度为O(n*p)(...
    假装会编程阅读 892评论 0 0
  • 加入好报画画群,到明天的话就整整满一个月了,像学生一样到了毕业季,是需要交纳一篇毕业作品的,丢丢老师建议将之前的作...
    一心小茶馆阅读 967评论 6 18
  • 优质广告供应商

    广告是为了更好地支持作者创作

  • 1. CSS和JS在网页中的放置顺序是怎样的? css放在head标签里 js放在body标签的最后主要是为了避免...
    mint9602阅读 261评论 0 0
  • 语言最大的好处,除了沟通以为,就是欺骗。所以我一般不愿意听别人怎么解释,对方每解释一句都显得很幼稚。听了这种编造的...
    张赟ZhangYun阅读 74评论 0 0
  • 最近支付宝频频有大动作,一时说凭芝麻信用可以免押金骑共享单车,一时说可以免押金租房,信用似乎变得越来越“值钱”。 ...
    30efbf645eeb阅读 350评论 0 1