二十一、自己动手实现排序算法(9)-------- “ Radix Sort 基数排序 ”

基数排序是一种非比较型整数排序算法,通过按照低位到高位的顺序分别进行排序,最终形成有序序列。该算法适合处理包含多个位数的数据,复杂度为O(kn)。文章提供了基数排序的详细原理介绍、图解以及Java代码实现和测试。
摘要由CSDN通过智能技术生成

参考文章:

https://www.cnblogs.com/guoyaohua/p/8600214.html                 十大经典排序算法最强总结(含JAVA代码实现)(强推

https://www.cnblogs.com/skywang12345/p/3603669.html            基数排序


温馨提示:

        如果代码看不懂,那就拿出纸和笔,照着代码流程走一遍,走一遍,再走一遍,另外看基数排序,最好先把其他的排序都给看了,再看这个会好理解一些。

基数排序分析:

平均时间复杂度最好情况最坏情况空间复杂度排序方式稳定性
O(n*k)O(n*k)O(n*k)O(n+k)Out-place稳定

基数排序原理:

        基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn),n为数组长度,k为数组中的数的最大的位数;

       基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。

 

基数排序算法描述:

  • 取得数组中的最大数,并取得位数;
  • arr为原始数组,从最低位开始取每个位组成radix数组;
  • 对radix进行计数排序(利用计数排序适用于小范围数的特点);

 

基数排序算法原理图解:

图解1:

 

图解2:

在上图中,首先将所有待比较树脂统一为统一位数长度,接着从最低位开始,依次进行排序。
1. 按照个位数进行排序。
2. 按照十位数进行排序。
3. 按照百位数进行排序。

排序后,数列就变成了一个有序序列。

 

基数排序 Java 代码实现:

代码一:


package com.sorting.algorithm;

import java.util.ArrayList;

public class RadixSort {
	
	public static int[] radixSort(int[] array){
		
		// 寻找数组中的最大数 max ,并求出最大数的位数maxDigit
		int maxDigit = 0,max = array[0];
		for (int i = 0; i < array.length; i++) {
			if(max < array[i])
				max = array[i];
		}
		while(max != 0){
			max /= 10;
			maxDigit++;
		}
		
		// 设立bucketList 数组,0-10,存储数字0-9,0-9的数组中可以存放多个数组元素,即个位或者十位相同时,就会存放到一起。
		ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
		
		// 初始化bucketList
		for(int i = 0; i < 10; i++){
			bucketList.add(new ArrayList<Integer>());
		}
		
		
		System.out.println("排序过程:");
		
		// mod 取余数用,div 是用来取余之后提取个位、十位、百位的数字
		int mod =10, div =1;
		for(int i = 0; i < maxDigit; mod *= 10, div *= 10, i++ ){
			// 按照0-9 的数字顺序,将数组中的元素放入到bucketList中,0-9每个数字可存放多个数组元素
			for (int j = 0; j < array.length; j++) {
				int num = (array[j]%mod)/div;
				bucketList.get(num).add(array[j]);
			}
			
			// 将已经按照个位或十位或百位 排序的元素,重新放入 array数组中,以达到按照个位或十位或百位排序的效果
			int index = 0 ;
			for (int j = 0; j < bucketList.size(); j++) {
				for (int k = 0; k < bucketList.get(j).size(); k++) {
					array[index++] = bucketList.get(j).get(k);
				}
				bucketList.get(j).clear();
			}
			
			printArr(array);
		}
		
		return array;
	}
	
	
	public static void printArr(int[] array){
		for (int i = 0; i < array.length; i++) {
			if(i != array.length-1)
				System.out.print(array[i]+ ", ");
			else
				System.out.println(array[i]);
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		
		int[] array = {53,3,542,748,14,214,154,63,616};
		
		System.out.println("排序之前:");
		
		printArr(array);
		int[] sortedArr = radixSort(array);

		System.out.println("排序之后:");
		printArr(sortedArr);
	}
	
}

 

 

代码二:

package com.sorting.algorithm;

public class RadixSort2 {
	
	public static int[] radixSort(int[] array){
		// 寻找最大数
		int max = array[0];
		for (int i = 0; i < array.length; i++) {
			if(max < array[i])
				max = array[i];
		}
		
		System.out.println("排序过程:");
		
		// exp 为应该取模整除的数字,依次类推
		// exp =1, 取个位
		// exp =10, 取十位
		// exp=100, 取百位
		int exp = 1;
		
		// 对数组中的元素每一位进行排序,即基数排序
		while(max/exp > 0){
			radixSort(array,exp);
			exp *= 10;
		}
		
		return array;
	}
	
	private static void radixSort(int[] array, int exp){
		// output 为缓存数组,暂存排序后的数组
		int [] output = new int[array.length];
		int [] buckets = new int[10];
		
		// 计数排序中,统计各元素出现的个数
		for(int i = 0; i < array.length; i++)
			buckets[(array[i]/exp)%10]++;
		
		// 计数排序汇中,计算数组元素的排序位置
		for(int i = 1; i < buckets.length; i++)
			buckets[i] = buckets[i] + buckets[i-1];
		
		// 这个要逆序来赋值,因为位置相同的数组元素,越靠前的,他的位置就越靠后
		for(int i = array.length-1 ; i >= 0; i--){
			buckets[(array[i]/exp)%10]--;
			output[buckets[(array[i]/exp)%10]] = array[i];
		}
		
		// 将缓存数组总排序好的数组,重新赋值给数组 array
		for(int i = 0; i < array.length; i++) 
			array[i] = output[i];
		
		printArr(output);
		
	}

	public static void printArr(int[] array){
		for (int i = 0; i < array.length; i++) {
			if(i != array.length-1)
				System.out.print(array[i]+ ", ");
			else
				System.out.println(array[i]);
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		
		int[] array = {53,3,542,748,14,214,154,63,616};
		
		System.out.println("排序之前:");
		
		printArr(array);
		int[] sortedArr = radixSort(array);

		System.out.println("排序之后:");
		printArr(sortedArr);
	}
	
}

 

 

 

 

基数排序代码测试:

代码一测试:

 

代码二测试:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值