基数排序java实现

来源:互联网 发布:office2011for mac 编辑:程序博客网 时间:2024/05/17 07:22

基数排序属于“分配式排序”(distribution sort),基数排序法又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。

基数排序(Radix sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机(Tabulation Machine)上的贡献。

它是这样实现的: 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零. 然后, 从最低位开始, 依次进行一次排序.这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列.

效率

基数排序的时间复杂度是 O(k·n),其中n是排序元素个数,k是数字位数。注意这不是说这个时间复杂度一定优于O(n·log(n)),因为k的大小一般会受到 n 的影响。 以排序n个不同整数来举例,假定这些整数以B为底,这样每位数都有B个不同的数字,k就一定不小于logB(n)。由于有B个不同的数字,所以就需要B个不同的桶,在每一轮比较的时候都需要平均n·log2(B) 次比较来把整数放到合适的桶中去,所以就有:

  • k 大于或等于 logB(n)
  • 每一轮(平均)需要 n·log2(B) 次比较

所以,基数排序的平均时间T就是:

T ≥logB(nn·log2(B) = log2(n)·logB(2n·log2(B)= log2(n)·n·logB(2)·log2(B) = n·log2(n)

所以和比较排序相似,基数排序需要的比较次数:T ≥ n·log2(n)。故其时间复杂度为Ω(n·log2(n)) = Ω(n·log n) 。

时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(n),共进行d趟分配和收集。 空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。

实现的方法

最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。

最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。

基数排序的缺点: 

不呈现时空局部性,因为在按位对每个数进行排序的过程中,一个数的位置可能发生巨大的变化,所以不能充分利用现代机器缓存提供的优势。同时计数排序作为中间稳定排序的话,不具有原地排序的特点,当内存容量比较宝贵的时候,还是有待商榷。

  1. package com.algorithm.sort;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. public class RadixSort {  
  6.   
  7.     //基于计数排序的基数排序算法  
  8.     private static void radixSort(int[] array,int radix, int distance) {  
  9.         //array为待排序数组  
  10.         //radix,代表基数  
  11.         //代表排序元素的位数  
  12.           
  13.         int length = array.length;  
  14.         int[] temp = new int[length];//用于暂存元素  
  15.         int[] count = new int[radix];//用于计数排序  
  16.         int divide = 1;  
  17.           
  18.         for (int i = 0; i < distance; i++) {  
  19.               
  20.             System.arraycopy(array, 0,temp, 0, length);  
  21.             Arrays.fill(count, 0);  
  22.               
  23.             for (int j = 0; j < length; j++) {  
  24.                 int tempKey = (temp[j]/divide)%radix;  
  25.                 count[tempKey]++;  
  26.             }  
  27.               
  28.             for (int j = 1; j < radix; j++) {  
  29.                 count [j] = count[j] + count[j-1];  
  30.             }  
  31.               
  32.             //个人觉的运用计数排序实现计数排序的重点在下面这个方法              
  33.             for (int j = length - 1; j >= 0; j--) {  
  34.                 int tempKey = (temp[j]/divide)%radix;  
  35.                 count[tempKey]--;  
  36.                 array[count[tempKey]] = temp[j];  
  37.             }  
  38.               
  39.             divide = divide * radix;                  
  40.               
  41.         }  
  42.                   
  43.     }  
  44.       
  45.       
  46.     /** 
  47.      * @param args 
  48.      */  
  49.     public static void main(String[] args) {  
  50.       
  51.         int[] array = {3,2,3,2,5,333,45566,2345678,78,990,12,432,56};  
  52.         radixSort(array,10,7);  
  53.         for (int i = 0; i < array.length; i++) {  
  54.             System.out.print("  " + array[i]);  
  55.         }  
  56.           
  57.   
  58.     }  
  59.   
  60. }  

0 0
原创粉丝点击