zoukankan      html  css  js  c++  java
  • 008-排序算法-基数排序【桶排序、基数排序】

    一、概述

      基数排序(Radix Sort)是在桶排序的基础上发展而来的,两种排序都是分配排序的高级实现。分配排序(Distributive Sort)的基本思想:排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序。它们的时间复杂度可达到线性阶:O(n)。

    1.1、桶排序

      桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。

      每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

      假设待排序的数组a中共有N个整数,并且已知数组a中数据的范围[0, MAX)。在桶排序时,创建容量为MAX的桶数组r,并将桶数组元素都初始化为0;将容量为MAX的桶数组中的每一个单元都看作一个"桶"。

      在排序时,逐个遍历数组a,将数组a的值,作为"桶数组r"的下标。当a中数据被读取时,就将桶的值加1。例如,读取到数组a[3]=5,则将r[5]的值+1。 

    代码

        /*
         * 桶排序
         *
         * 参数说明:
         *     a -- 待排序数组
         *     max -- 数组a中最大值的范围
         */
        public static void bucketSort(int[] a, int max) {
            int[] buckets;
    
            if (a==null || max<1)
                return ;
    
            // 创建一个容量为max的数组buckets,并且将buckets中的所有数据都初始化为0。
            buckets = new int[max];
    
            // 1. 计数
            for(int i = 0; i < a.length; i++)
                buckets[a[i]]++;
    
            // 2. 排序
            for (int i = 0, j = 0; i < max; i++) {
                while( (buckets[i]--) >0 ) {
                    a[j++] = i;
                }
            }
    
            buckets = null;
        }
    
        public static void main(String[] args) {
            int i;
            int a[] = {8,2,3,4,3,6,6,3,9};
    
            System.out.printf("before sort:");
            for (i=0; i<a.length; i++)
                System.out.printf("%d ", a[i]);
            System.out.printf("
    ");
    
            bucketSort(a, 10); // 桶排序
    
            System.out.printf("after  sort:");
            for (i=0; i<a.length; i++)
                System.out.printf("%d ", a[i]);
            System.out.printf("
    ");
        }

    代码地址:地址 中的algorithm-001-sort中 BucketSort

    1.2、基数排序

      基数排序(Radix Sort)是桶排序的扩展,它的基本思想是:将整数按位数切割成不同的数字,然后按每个位数分别比较。

      具体做法是:将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

    代码

        /*
         * 获取数组a中最大值
         *
         * 参数说明:
         *     a -- 数组
         *     n -- 数组长度
         */
        private static int getMax(int[] a) {
            int max;
    
            max = a[0];
            for (int i = 1; i < a.length; i++)
                if (a[i] > max)
                    max = a[i];
    
            return max;
        }
    
        /*
         * 对数组按照"某个位数"进行排序(桶排序)
         *
         * 参数说明:
         *     a -- 数组
         *     exp -- 指数。对数组a按照该指数进行排序。
         *
         * 例如,对于数组a={50, 3, 542, 745, 2014, 154, 63, 616};
         *    (01) 当exp=1表示按照"个位"对数组a进行排序
         *    (02) 当exp=10表示按照"十位"对数组a进行排序
         *    (03) 当exp=100表示按照"百位"对数组a进行排序
         *    ...
         */
        private static void countSort(int[] a, int exp) {
            //int output[a.length];    // 存储"被排序数据"的临时数组
            int[] output = new int[a.length];    // 存储"被排序数据"的临时数组
            int[] buckets = new int[10];
    
            // 将数据出现的次数存储在buckets[]中
            for (int i = 0; i < a.length; i++)
                buckets[ (a[i]/exp)%10 ]++;
    
            // 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在output[]中的位置。
            for (int i = 1; i < 10; i++)
                buckets[i] += buckets[i - 1];
    
            // 将数据存储到临时数组output[]中
            for (int i = a.length - 1; i >= 0; i--) {
                output[buckets[ (a[i]/exp)%10 ] - 1] = a[i];
                buckets[ (a[i]/exp)%10 ]--;
            }
    
            // 将排序好的数据赋值给a[]
            for (int i = 0; i < a.length; i++)
                a[i] = output[i];
    
            output = null;
            buckets = null;
        }
    
        /*
         * 基数排序
         *
         * 参数说明:
         *     a -- 数组
         */
        public static void radixSort(int[] a) {
            int exp;    // 指数。当对数组按各位进行排序时,exp=1;按十位进行排序时,exp=10;...
            int max = getMax(a);    // 数组a中的最大值
    
            // 从个位开始,对数组a按"指数"进行排序
            for (exp = 1; max/exp > 0; exp *= 10)
                countSort(a, exp);
        }
    
        public static void main(String[] args) {
            int i;
            int a[] = {53, 3, 542, 748, 14, 214, 154, 63, 616};
    
            System.out.printf("before sort:");
            for (i=0; i<a.length; i++)
                System.out.printf("%d ", a[i]);
            System.out.printf("
    ");
    
            radixSort(a);    // 基数排序
    
            System.out.printf("after  sort:");
            for (i=0; i<a.length; i++)
                System.out.printf("%d ", a[i]);
            System.out.printf("
    ");
        }
    }

     代码地址:地址 中的algorithm-001-sort中 RadixSort

    地方

  • 相关阅读:
    关于域名系统DNS解析IP地址的一些总结
    一个完整的TCP连接
    针对github权限导致hexo部署失败的解决方案
    关于css的一些事情(1)
    MVC、MVVM、MVP小结
    关于移动端开发的一些总结
    json与jsonp小结
    BFC 小结
    ES6 - for...of
    ES6-Symbol
  • 原文地址:https://www.cnblogs.com/bjlhx/p/10971504.html
Copyright © 2011-2022 走看看