【排序算法】基数排序(java实现)

1.基本思想

它是根据关键字中各位的值,通过对排序的N个元素进行若干趟“分配”与“收集”来实现排序的。

不需要比较关键字的大小

将基数排序分为LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由数值的最右边(低位)开始,而MSD则相反,由数值的最左边(高位)开始。注意:LSD的基数排序适用于位数少的数列,如果位数多的话,使用MSD的效率会比较好。
MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。

示例:


2.算法分析

时间复杂度:O(dn)        (d即表示整形的最高位数)

空间复杂度:O(10n)      (10表示0~9,用于存储临时的序列)

稳定性:稳定 

3.算法实现:

<span style="white-space:pre">	</span>public static void radixSort(int[] array,int distance){
        //distance 代表排序元素的位数 
		int radix =10;  //radix 代表基数 ,0-9,10个
		int len = array.length;
		int[] count = new int[radix];
		int[][] tmp = new int[radix][len+1];
		int divide = 1;
		
		for(int i = 0; i < distance; i++){
            //按位数上数字分配到各个数组中
            for(int j = 0; j < len; j++){
            	int tmpkey = (array[j]/divide)%10;  
            	int index = ++count[tmpkey];
            	tmp[tmpkey][index] = array[j];
            }
            //整合
            for(int j = 0 ,k =0; j < radix; j++){
            	for (int x = 1; x <= count[j]; x++){
            		array[k++] = tmp[j][x];
            	}
            	count[j] = 0; //复位
            }
            divide *= radix;
		}
	}

注:需要引入Arrays类,import java.util.Arrays;

3.算法优化:

因为上述基数排序,需要设置一个10*n 的临时数组来储存变量,空间利用率不高。 以下考虑基于计数的基数排序。计数排序是什么意思呢?假设数序列中小于元素a的个数为n,则直接把a放到第n+1个位置上。 
通过结合这两者,空间复杂度降为O(n)。
以个位数为例,通过记录各radix的数量来判断有多少数是小于当前这个radix的,再逆序(保证算法的稳定性)插入相应位置即可。
	//基于计数的基数排序
	public static void radixSort2(int[] array,int distance){
        //distance 代表排序元素的位数 
		int radix =10;     //radix 代表基数 ,0-9,10个 
		int len = array.length;
		int[] tmp = new int[len];
		int[] count = new int[radix];
		int divide = 1;
		
		for(int i = 0; i < distance; i++){
			System.arraycopy(array, 0,tmp, 0, len);   //复制数组
            Arrays.fill(count, 0);    //将计数数组置0
            //计数
            for(int j =0; j < len; j++){
            	int tmpkey = (array[j]/divide)%10;  
            	count[tmpkey]++;
            }

            for(int j = 1; j < radix; j++){
            	count[j] += count[j-1];
            }
            
            //逆序,保证数组的稳定性
            for(int j = len -1; j >= 0; j--){
            	int tmpKey = (tmp[j]/divide)%radix;  
                count[tmpKey]--;  
                array[count[tmpKey]] = tmp[j]; 
            }
            divide *= radix;
		}	
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值