基数排序图解

概述

基数排序属于分配式排序,又称“桶子法”。顾名思义,其是利用多个”桶“,通过将元素按照某种顺序放入桶中,而后又按照顺序再次取出,并且重复此操作,直到完成排序的一种排序方式。

基数排序是一种非比较型整数排序算法。也就是在运行过程中不需要对值的大小进行比较。是属于一种经典的空间换时间的算法

基数排序在面对数字位数不大时有较好的表现。

基数排序是一种稳定性算法(相同的两个元素位置在排序后保持不变),在某些时候,基数排序法的效率高于其它的稳定性排序法。

实现思路

基数排序,顾名思义,是通过对数字的基数来进行排序实现的。

在这里的基数可以理解为每一个数字不同位数上的数字。

例如:

123在百位上的基数为1,十位上的基数为2,个位上的基数为3,通过对这些基数的排序来实现元素的排序。

基数排序的整体实现步骤如下:

1 . 按照个位数将数据分配到各个桶中:

按照个位数放到桶中

按照个数放桶
2. 将上一次放置桶中的元素按照由基数数字从小到大,同基数先进先出的规律将数组进行一次排序。
基数数字从小到大,同基数先进先出1
基数数字从小到大,同基数先进先出2
3. 位数进一位没有该位数的按照0处理,按照以上两步规律继续进行操作:
十位操作
进行十位操作。

进行十位操作
进行重新依次串起来数字操作:

串起来数字操作
串起来完成

进行十位操作后发现还有百位数字未操作,此时进行百位操作

进行百位操作

进行百位操作

串起来数据:

百位操作串起来数据
操作完成
当对所有位数操作完毕后,算法结束,数据有序。

基数排序的算法思路比较简单,就是利用上一次位数排序产生的序列,不断按照位数推进进行排序,直到最大位数操作完毕,此时算法结束。

最后再辅助一张动图帮助了解全程:

菜鸟动图
动图来源:

菜鸟基数排序

但是本例子中讲解基数排序还有两个问题:

  • 不能处理0数据,解决方法是可以对0数据进行特殊处理

  • 不能处理负数,解决方法是开拓属于负数的10个桶,重新利用上诉思路解决。

代码演示:



public class RadixSort {
    
    
	public static void main(String[] args) {
    
    
		int [] arr = {
    
    9,8,7,10,123,456,789,654,321,987};
		radixSort(arr);
		System.out.println(Arrays.toString(arr));
	}
	//基数排序方法
	public static void radixSort(int arr[]) {
    
    
		//定义一个二维数组表示桶
		//基数排序属于空间换时间的经典算法
		int [][] bucket = new int [10][arr.length];
		//用一个一维数组来表示每个桶存入的个数
		int [] bucketElmentsCounts = new int [10];
		int max = arr[0];
		for(int i = 1;i < arr.length;i++) {
    
    
			if(arr[i] > max) {
    
    
				max = arr[i];
			}
		}
		int maxLength = (max + "").length();
		for(int i  = 0,n = 1;i < maxLength;i++,n *= 10) {
    
    
			//获取元素下标
			for(int j = 0;j < arr.length;j++) {
    
    
				//获取下标
				int digitOfElement = arr[j] / n % 10;
				//放桶
				bucket[digitOfElement][bucketElmentsCounts[digitOfElement]++] = arr[j];
			}
			int index = 0;
			for(int k = 0;k < bucketElmentsCounts.length;k++) {
    
    
				if(bucketElmentsCounts[k]!=0) {
    
    
					for(int l = 0;l < bucketElmentsCounts[k];l++) {
    
    
						arr[index++] = bucket[k][l];
					}
				}
				//把桶下表清零
				bucketElmentsCounts[k] = 0;
			}
			
		}
	}
}

代码参考:

尚硅谷数据结构与算法

复杂度

n: 数据规模

k:桶的个数

时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 是否稳定
O(n * k) O(n * k) O(n * k) O(n + k)

Guess you like

Origin blog.csdn.net/Nimrod__/article/details/114272799