排序算法七:基数排序(Radix sort)

上一篇提到了计数排序,它在输入序列元素的取值范围较小时,表现不俗。但是,现实生活中不总是满足这个条件,比如最大整形数据可以达到231-1,这样就存在2个问题:

1)因为m的值很大,不再满足m=O(n),计数排序的时间复杂也就不再是线性的;

2)当m很大时,为计数数组申请的内存空间会很大;

为解决这两个问题,本篇讨论基数排序(Radix sort),基数排列的思想是:

1)将先按照某个基数将输入序列的每个元素划分成若干部分,每个部分对排序结果的影响是有优先级的;

2)先按低优先级排序,再按高优先级排序,依次递推。这里要注意,每个部分进行排序时,必须选用稳定排序算法,例如基数排序。

3)最后的次序就是高优先级高的在前,高优先级相同的,低优先级高的在前。

(一)算法实现

 1     @Override
 2     protected void sort(int[] toSort) {
 3         // number to sort, n integers
 4         int n = toSort.length;
 5         // b bits each integer
 6         int b = Integer.SIZE;
 7         /*
 8          * Split each integer into b/r digits, and each r bits long. So average
 9          * running time is O(b/r(2^r+n)). It is proved that running time is
10          * close to least time while choosing r to lgn.
11          */
12         int r = (int) Math.ceil(Math.log(n) / Math.log(2));
13         // considering the space cost, the maximum of r is 16.
14         r = Math.min(r, 16);
15
16         int upperLimit = 1 << r;
17         int loopCount = b / r;
18         int j = 0;
19         int[] resultArray = new int[toSort.length];
20         int[] countingArray = new int[upperLimit];
21         while (j < loopCount) {
22             int rightShift = j * r;
23             radixSort(toSort, upperLimit, rightShift, resultArray,
24                     countingArray);
25             Arrays.fill(countingArray, 0);
26             j++;
27         }
28         int mod = b % r;
29         if (mod != 0) {
30             upperLimit = 1 << mod;
31             int rightShift = r * loopCount;
32             countingArray = new int[upperLimit];
33             radixSort(toSort, upperLimit, rightShift, resultArray,
34                     countingArray);
35         }
36     }
37
38     private void radixSort(int[] toSort, int upperLimit, int rightShift,
39             int[] resultArray, int[] countingArray) {
40         int allOnes = upperLimit - 1;
41         for (int i = 0; i < toSort.length; i++) {
42             int radix = (toSort[i] >> rightShift) & allOnes;
43             countingArray[radix]++;
44         }
45         for (int i = 1; i < countingArray.length; i++) {
46             countingArray[i] += countingArray[i - 1];
47         }
48
49         for (int i = toSort.length - 1; i >= 0; i--) {
50             int radix = (toSort[i] >> rightShift) & allOnes;
51             resultArray[countingArray[radix] - 1] = toSort[i];
52             countingArray[radix]--;
53         }
54         System.arraycopy(resultArray, 0, toSort, 0, resultArray.length);
55     }

radixSort

1)算法属于分配排序

2)平均时间复杂度是O(b/r(2r+n)), b-每个元素的bit数,r-每个元素划分成b/r个数字,每个数字r个bit。当r=log2n时,复杂度是O(2bn/log2n),也就是说,当b=O(log2n)时,时间复杂度是O(n).

3) 空间复杂度是O(2r+n)

4)算法属于稳定排序

(二)算法仿真

下面对随机化快速排序和基数排序,针对不同输入整数序列长度,仿真结果如下,从结果看,当输入序列长度越大,基数排序性能越优越。

**************************************************
Number to Sort is:2500
Array to sort is:{1642670374,460719485,1773719101,2140462092,1260791250,199719453,1290828881,1946941575,2032337910,643536338...}
Cost time of 【RadixSort】 is(milliseconds):48
Sort result of 【RadixSort】:{217942,491656,1389218,2642908,3608001,3976751,4905471,5094692,6340348,7693772...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):1
Sort result of 【RandomizedQuickSort】:{217942,491656,1389218,2642908,3608001,3976751,4905471,5094692,6340348,7693772...}
**************************************************
Number to Sort is:25000
Array to sort is:{987947608,1181521142,1240568028,373349221,289183678,2051121943,1257313984,745646081,1414556623,1859315040...}
Cost time of 【RadixSort】 is(milliseconds):1
Sort result of 【RadixSort】:{47434,109303,240122,255093,448360,526046,526445,628228,837987,966240...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):2
Sort result of 【RandomizedQuickSort】:{47434,109303,240122,255093,448360,526046,526445,628228,837987,966240...}
**************************************************
Number to Sort is:250000
Array to sort is:{1106960922,1965236858,1114033657,1196235697,2083563075,1994568819,1185250879,670222217,1386040268,1316674615...}
Cost time of 【RadixSort】 is(milliseconds):7
Sort result of 【RadixSort】:{466,884,8722,35382,37181,44708,53396,55770,67518,74898...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):27
Sort result of 【RandomizedQuickSort】:{466,884,8722,35382,37181,44708,53396,55770,67518,74898...}
**************************************************
Number to Sort is:2500000
Array to sort is:{1903738012,485657780,1747057138,2082998554,1658643001,91586227,2127717572,557705232,533021562,1322007386...}
Cost time of 【RadixSort】 is(milliseconds):81
Sort result of 【RadixSort】:{369,392,1316,1378,2301,3819,4013,4459,5922,6423...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):340
Sort result of 【RandomizedQuickSort】:{369,392,1316,1378,2301,3819,4013,4459,5922,6423...}
**************************************************
Number to Sort is:25000000
Array to sort is:{2145921976,298753549,11187940,410746614,503122524,1951513957,1760836125,2141838979,1702951573,1402856280...}
Cost time of 【RadixSort】 is(milliseconds):1,022
Sort result of 【RadixSort】:{130,145,406,601,683,688,736,865,869,954...}
Cost time of 【RandomizedQuickSort】 is(milliseconds):3,667
Sort result of 【RandomizedQuickSort】:{130,145,406,601,683,688,736,865,869,954...}

相关源码:

 1 package com.cnblogs.riyueshiwang.sort;
 2
 3 import java.util.Arrays;
 4
 5 public class RadixSort extends abstractSort {
 6
 7     @Override
 8     protected void sort(int[] toSort) {
 9         // number to sort, n integers
10         int n = toSort.length;
11         // b bits each integer
12         int b = Integer.SIZE;
13         /*
14          * Split each integer into b/r digits, and each r bits long. So average
15          * running time is O(b/r(2^r+n)). It is proved that running time is
16          * close to least time while choosing r to lgn.
17          */
18         int r = (int) Math.ceil(Math.log(n) / Math.log(2));
19         // considering the space cost, the maximum of r is 16.
20         r = Math.min(r, 16);
21
22         int upperLimit = 1 << r;
23         int loopCount = b / r;
24         int j = 0;
25         int[] resultArray = new int[toSort.length];
26         int[] countingArray = new int[upperLimit];
27         while (j < loopCount) {
28             int rightShift = j * r;
29             radixSort(toSort, upperLimit, rightShift, resultArray,
30                     countingArray);
31             Arrays.fill(countingArray, 0);
32             j++;
33         }
34         int mod = b % r;
35         if (mod != 0) {
36             upperLimit = 1 << mod;
37             int rightShift = r * loopCount;
38             countingArray = new int[upperLimit];
39             radixSort(toSort, upperLimit, rightShift, resultArray,
40                     countingArray);
41         }
42     }
43
44     private void radixSort(int[] toSort, int upperLimit, int rightShift,
45             int[] resultArray, int[] countingArray) {
46         int allOnes = upperLimit - 1;
47         for (int i = 0; i < toSort.length; i++) {
48             int radix = (toSort[i] >> rightShift) & allOnes;
49             countingArray[radix]++;
50         }
51         for (int i = 1; i < countingArray.length; i++) {
52             countingArray[i] += countingArray[i - 1];
53         }
54
55         for (int i = toSort.length - 1; i >= 0; i--) {
56             int radix = (toSort[i] >> rightShift) & allOnes;
57             resultArray[countingArray[radix] - 1] = toSort[i];
58             countingArray[radix]--;
59         }
60         System.arraycopy(resultArray, 0, toSort, 0, resultArray.length);
61     }
62
63     public static void main(String[] args) {
64         for (int j = 0, n = 2500; j < 5; j++, n = n * 10) {
65             System.out
66                     .println("**************************************************");
67             System.out.println("Number to Sort is:" + n);
68             int upperLimit = Integer.MAX_VALUE;
69             int[] array = CommonUtils.getRandomIntArray(n, upperLimit);
70             System.out.print("Array to sort is:");
71             CommonUtils.printIntArray(array);
72
73             int[] array1 = Arrays.copyOf(array, n);
74             new RadixSort().sortAndprint(array1);
75
76             int[] array2 = Arrays.copyOf(array, n);
77             new RandomizedQuickSort().sortAndprint(array2);
78         }
79     }
80 }

RadixSort.java

时间: 2024-10-10 03:05:17

排序算法七:基数排序(Radix sort)的相关文章

算法学习-基数排序(radix sort)卡片排序(card sort) C++数组实现

基数排序又叫卡片排序,这是在比较早的时候用的比较多的排序方法. 在现代计算机出现之前,一直用于老式穿孔卡的排序. 说下基数排序的思想,前面我有写一个桶式排序,基数排序的思想是桶式排序的推广. 桶式排序:http://blog.csdn.net/alps1992/article/details/38132593 基数排序的思想是在于只有10个桶,而不是最大数是多少就有多少个桶.假如我们有10个乱序的数字. 第一趟排序之后 0 1 512 343 64 125 216 27 8 729 0 1 2

经典排序算法 - 基数排序Radix sort

经典排序算法 - 基数排序Radix sort 原理类似桶排序,这里总是需要10个桶,多次使用 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数 例如 待排序数组[62,14,59,88,16]简单点五个数字 分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样 |  0  |  0  | 62 |  0  | 14 |  0  | 16 |  0  |  88 | 59 | |  0  |  1  |  2  |  3  |  4 | 

排序算法七:选择排序之堆排序

排序算法七:选择排序之堆排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据

经典排序算法之基数排序(C语言版)

排序算法之基数排序的C语言实现. #include "math.h" #include "stdio.h" /* * 基数排序 2016-04-18 23:43:49 * 基数排序的思想:1.求出数组中最大的元素. *   2.求出最大元素是几位数.设为i位. *   3.对所有的数进行i轮排序.首先排个位,然后在十位,然后百位...... *   4.每一轮的排位都需要分桶,桶是有顺序的,然后在把桶里的数按顺序放入原来的数组中. *   5.直到i轮排序结束后,数

桶排序/基数排序(Radix Sort)

说基数排序之前,我们先说桶排序: 基本思想:是将阵列分到有限数量的桶子里.每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序).桶排序是鸽巢排序的一种归纳结果.当要被排序的阵列内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n)).但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响.          简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序. 例如要对大小为[1..1000]范围内的n个整数A[1..n]排序 首

排序算法系列——基数排序

基数排序不同于其他的七种排序算法,它是基于一种分配法,而非比较.基数排序属于"分配式排序"(distribution sort),基数排序法又称"桶子法"(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些"桶"中,藉以达到排序的作用.它的灵感来自于队列(Queue),它最独特的地方在于利用了数字的有穷性(阿拉伯数字只有0到9的10个). 基本思想: 我们考虑对整数进行基数排序的过程,对于整数,

排序算法之基数排序

概述 首先从多排序码排序开始介绍基数排序.以扑克牌排序为例.每张扑克牌有两个"排序码":花色和面值.其有序关系为: 花色:?<?<?<? 面值:2<3<4<5<6<7<8<9<10<J<Q<K<A 如果把所有扑克牌排成以下次序: ?2,-,?A,?2,-,?A,?2,-,?A,?2,-,?A 这就是多排序码排序.排序后形成的有序序列叫做字典有序序列. 一般情况下,假定有一个n个元素的序列{V0,V

经典排序算法(1) - 冒泡排序Bubble Sort

冒泡排序(Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端.运作步骤如下: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除了最后

基数排序(radix sort)

1 #include<iostream> 2 #include<ctime> 3 #include <stdio.h> 4 #include<cstring> 5 #include<cstdlib> 6 #include <map> 7 #include <string> 8 using namespace std; 9 // A utility function to get maximum value in arr[]