Java 实现基数排序

介绍

基数排序(桶排序)介绍:

1)基数排序radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用

2)基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法

3)基数排序(Radix Sort)桶排序的扩展

4)基数排序是1887年赫尔曼·何乐礼发明的。它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。

基本思想

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

2)这样说明,比较难理解,下面我们看一个图文解释,理解基数排序的步骤

 

数组的初始状态

arr = {53, 3, 542, 748, 14, 214}

1轮排序:

(1) 将每个元素的个位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)

(2) 按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)

 数组的第1轮排序结果:

arr = {542, 53, 3, 14, 214, 748}  

2轮排序:

(1) 将每个元素的十位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)

(2) 按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)

数组的第2轮排序结果:

arr = {3, 14, 214, 542, 748, 53

3轮排序:

(1) 将每个元素百位数取出,然后看这个数应该放在哪个对应的桶(一个一维数组)

(2) 按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)

数组的第3轮排序结果:

arr = {3, 14, 53, 214, 542, 748}

 代码实现

 

import java.time.Duration;
import java.time.LocalTime;
import java.util.Arrays;

public class RadixSort {

	public static void main(String[] args) {
//		test1();
//		test2();
		test3();
	}
	
	public static void test1() {
		int arr[]={53, 3, 542, 748, 14, 214};
		System.out.println("排序前:");
		printArr(arr);
		radixSort(arr);
		System.out.println("排序后:");
		printArr(arr);
	}
	
	
	public static void  test2() {
		int len=12;
		int arr[]=new int [len];
		for(int i=0;i<len;i++) {
			arr[i]=(int) (Math.random()*100);
		}
		System.out.println("排序前:");
		printArr(arr);
		radixSort(arr);
		System.out.println("排序后:");
		printArr(arr);
		
	}
	
	public static void test3() {
		int len =80000;
		int arr[] = new int [len];
		for(int i=0;i<len;i++) {
			arr[i]=(int) (Math.random()*1000);
		}
		LocalTime before=LocalTime.now();
		System.out.println("排序前的时间:"+before);
		radixSort(arr);
		LocalTime after=LocalTime.now();
		Duration dur=Duration.between(before, after);
		System.out.println("排序后的时间:"+after);
		System.out.println("时间差(毫秒):"+dur.toMillis());
	}
	
	private static void radixSort(int[] arr) {
		int maxLen=getDigitLen(arr);
		int bucket[][]=new int [10][arr.length];
		int [] bucketElementCount=new int [10];
		
		//	外层for要按照maxlen个位数排序
		for(int i=0 , n=1;i<maxLen;i++,n*=10) {
			//按照第i位数的大小 对每个数进行排序
			for(int j=0;j<arr.length;j++) {
				
				int num=arr[j] / n % 10;
				//把位数 num 放到对应的桶中
				int count=bucketElementCount[num];
				bucket[num][count]=arr[j];
				//第num个桶,的元素数量+1
				++bucketElementCount[num];
			}
			arr=clearBucket(bucket, bucketElementCount,arr);
			
			//把所有的桶清空
			Arrays.fill(bucketElementCount, 0);
		}
		
	}

	private static int[] clearBucket(int[][] bucket, int[] bucketElementCount, int[] arr) {
		int index=0;
		//按照1维数组的下标,把元素放到原来数组中
		for(int i=0;i<bucketElementCount.length;i++) {
			//第i个桶的是否有元素
			int amount=bucketElementCount[i];
			if(amount != 0) {
				//把第i个桶的元素拿出来
				// 遍历第i个桶的第j个小格子
				for(int j=0;j<amount;j++)
					arr[index++]=bucket[i][j];
			}
			//把第i个桶的元素拿出来后,把这个桶清空,
			//通过把桶数量赋值为0 就可以实现清空
//			bucketElementCount[i]=0;
			
		}
//		System.out.println("第i轮排序结果:"+Arrays.toString(arr));
		return arr;
	}

	//获取最大数有多少 个 位数
	private static int getDigitLen(int[] arr) {
		int max=arr[0];
		for(int i=1;i<arr.length;i++) {
			if(arr[i]>max) {
				max=arr[i];
			}
		}
		return String.valueOf(max).length();
	}

	//打印数组
	private static void printArr(int[] arr) {
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		System.out.println();	
	}
}

运行结果:

test2

test3

 

说明: 

基数排序的说明:

1)基数排序是对传统桶排序的扩展,速度很快.

2)基数排序是经典的空间换时间的方式,占用内存很大, 当对海量数据排序时,容易造成 OutOfMemoryError

3)基数排序时稳定的。[:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的]

4)有负数的数组,我们不用基数排序来进行排序, 如果要支持负数,参考: https://code.i-harness.com/zh-CN/q/e98fa9icon-default.png?t=M4ADhttps://code.i-harness.com/zh-CN/q/e98fa9

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值