【算法学习】 基数排序算法

基数排序是在桶排序的基础上发展而来的,两种排序都是分配排序的高级实现。将数组中的所有数按位进行分类,由于每一位数的大小都在0~9之间,因此创建下标为0~9的十个数组,根据需要对数进行存储。

图解:

例如对{12 45 3 15 61 154 242 58 46 9}进行排序的步骤如下 :

第一轮,建立10个桶,也就是数组,将数组中的数依次取出,按照个位数字的不同依次放入不同的桶中:

放入桶中之后:

 然后,按照桶的顺序(下标顺序)依次将所有桶中的元素取出放回到原来的数组:61 12 242 3 154 45 15 46 58 9

第二轮,再次将数组中的数依次取出,按照十位数字的不同依次放入不同的桶中,如果十位上没有数字则补零:

 然后,按照桶的顺序(下标顺序)依次将所有桶中的元素取出放回到原来的数组:3 9 12 15 242 45 46 154 58 61

第三轮, 再次将数组中的数依次取出,按照百位数字的不同依次放入不同的桶中,如果百位上没有数字则补零:

 然后,按照桶的顺序(下标顺序)依次将所有桶中的元素取出放回到原来的数组:3 9 12 15 45 58 61 154 242,此时已经排序完成。

代码

import java.util.Arrays;

public class RadixSort {

	public static void main(String[] args) {
		int arr[] = {12, 45, 3, 15, 61, 154, 242, 58, 46, 9};
		sort(arr);
	}
	
	public static void sort(int[] arr) {
		
		//定义一个二维数组,表示10个桶
		//二维数组包含10个一维数组,为了防止移除,每个一维数组的大小都要容得下arr中所有的元素
		//因此基数排序算法就是以空间换时间的算法,比较耗费空间
		int[][] bucket = new int[10][arr.length];
		
		//为了记录每个桶中存放了多少数据,定义一个一维数组存放每个桶中数据的个数
		//num[n]表示第n个位置已经存放的元素个数
		int[] num = new int[10];
		
		//得到数组中最大数的位数
		int max = arr[0];
		for(int i=0; i<arr.length; i++) {
			if(arr[i]>max) {
				max = arr[i];
			}
		}
		//最大数的位数
		int maxLength = (max+"").length();
		
		int n = 1;
		for(int i=0; i< maxLength; i++) {
			for(int j=0; j<arr.length; j++)
			{ //取出每个元素的对应的位
				int ge = arr[j] / n %10;
				n = n*10; //下次取十位,再下次取百位
				//放入相应的桶当中
				bucket[ge][num[ge]] = arr[j];
				//该数组中元素+1
				num [ge]++;
			}
			
			//依次取出每个桶中的元素放回到原数组
			int index = 0;
			for(int k=0; k<10; k++) {//遍历每一个桶
				//如果桶中有数据就取出
				if(num[k] != 0) {
					for(int m=0; m<num[k];m++) {
						arr[index++] = bucket[k][m];
					}
				}
				//num清零
				num[k] = 0;
			}
			System.out.println("第"+ (i+1) +"轮结果"+ Arrays.toString(arr));
		}
			
		
	}

}

特点

  • 时间复杂度:平均、最好、最坏都为O(k*n),其中k为常数,n为元素个数
  • 空间复杂度:O(n+k)
  • 基数排序是对传统桶排序的扩展,速度很快.
  • 排序是经典的空间换时间的方式,占用内存很大, 当对海量数据排序时,容易造成 OutOfMemoryError
  • 数排序时稳定的[:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程芝士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值