八种排序算法之七:图解基数排序

本文深入解析基数排序算法,介绍其核心思想与步骤,演示通过多个排序轮次,利用桶排序技巧,最终实现数字序列的完全排序过程。文章包含详细的代码实现与运行结果,适合初学者理解和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基数排序适合于有不同位数的大小数字,例如以下数列:
在这里插入图片描述
核心思想是:
先找十个桶:0~9
第一轮按照元素的个位数排序
桶内分别存放上述数组元素的个位数,按照数组元素的顺序依次存放
在这里插入图片描述
之后,按照从左向右,从上到下的顺序依次取出元素,组成新的数组。
在这里插入图片描述
在新的数组中,进行第二轮,按照十位数排序,依次存放于桶中:
在这里插入图片描述
按照之前的顺序取出,组成新的数组。
进行第三轮,按照百位数排序:
在这里插入图片描述
将百位数的元素取出之后,我们发现新的数组已经变成了有序数组
在这里插入图片描述
大家也已经发现,排序进行的轮数就是最大数的位数,这几轮进行之后,也就完成了基数排序。

全流程为此图:
在这里插入图片描述


进入代码阶段:
代码阶段一:实现第一轮个位数的排序
注意以下几点:
1.1.计算最大数的位数,可以通过此方法,加空字符转字符串使用length

int maxLength =(max+"").length();

1.2.得使用二维数组存储元素在桶中的位置:一个是余数位,一个是在在桶中第几个位置
1.3打印测试二维数组的方法为:

//打印二维数组,测试
				for(int[] nums:temp){
					System.out.println(Arrays.toString(nums));

测试第一轮是否正确的全部代码


package demo4;

import java.util.Arrays;

/**
 * 基数排序
 *
 * 2019年2月14日
 */
public class RadixSort {
	
	public static void main(String[] args) {
		int[] arr = new int[]{23,6,9,287,56,1,789,34,65,653};
		//System.out.println(Arrays.toString(arr));
		radixSort(arr);		
	//System.out.println(Arrays.toString(arr));
	}
	
	public static void radixSort(int[] arr){
		
		//存数组中最大的数字,为了知道循环几次
		int max = Integer.MIN_VALUE;//(整数中的最小数)
		//遍历数组,找出最大值
		for(int i=0;i<arr.length;i++){
			if(max<arr[i]){
				max=arr[i];
			}
		}
		
		//计算最大数是几位数,,此方法计较绝妙
		int maxLength =(max+"").length();
		//用于临时存储数据的数组
		int[][] temp = new int[10][arr.length];
		//用于存储桶内的元素位置
		int[] counts = new int[arr.length]; 
		
		//第一轮个位数较易得到余数,第二轮就得先除以十再去取余,之后百位除以一百
		//可以看出,还有一个变量随循环次数变化,为了取余
		
		//循环的次数
		for(int i=0,n=1;i<maxLength;i++,n*=10){
			//每一轮取余
			for(int j=0;j<arr.length;j++){
				//计算余数
				int ys= (arr[j]/n)%10;
			    //把便利店数据放在指定数组中,有两个信息,放在第几个桶+数据应该放在第几位
				temp[ys][counts[ys]] = arr[j];
			    //记录数量
			    counts[ys]++;
			}
			if(i==0){
				//打印二维数组,测试
				for(int[] nums:temp){
					System.out.println(Arrays.toString(nums));
				}
			}

		}
		
	}

}


结果如下,验证第一轮通过
在这里插入图片描述
代码阶段二:实现第一轮取余存储之后,我们需要重新按照顺序(从左向右,从上向下)把元素从桶中拿出来组成一个新的数组,下一轮迭代时使用此新的数组
部分参考代码如下:

//记录取的数字应该放到位置
			int index=0;
			//每一轮循环之后把数字取出来
			for(int k=0;k<counts.length;k++){
				//记录数量的数组中当前余数记录不为零
				if(counts[k]!=0){
					for(int l=0;l<counts[k];l++){
						//取出元素
						arr[index]= temp[k][l];
						index++;
					}
					//取出后把数量置为零
					counts[k]=0;
				}
			}

至此,基数排序也写完了,运行结果及代码如下:
在这里插入图片描述
全部代码:`在这里插入代码片

package demo4;

import java.util.Arrays;

/**
 * 基数排序
 *
 * 2019年2月14日
 */
public class RadixSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 23, 6, 9, 287, 56, 1, 789, 34, 65, 653 };
		System.out.println(Arrays.toString(arr));
		radixSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void radixSort(int[] arr) {

		// 存数组中最大的数字,为了知道循环几次
		int max = Integer.MIN_VALUE;// (整数中的最小数)
		// 遍历数组,找出最大值
		for (int i = 0; i < arr.length; i++) {
			if (max < arr[i]) {
				max = arr[i];
			}
		}

		// 计算最大数是几位数,,此方法计较绝妙
		int maxLength = (max + "").length();
		// 用于临时存储数据的数组
		int[][] temp = new int[10][arr.length];
		// 用于存储桶内的元素位置
		int[] counts = new int[arr.length];

		// 第一轮个位数较易得到余数,第二轮就得先除以十再去取余,之后百位除以一百
		// 可以看出,还有一个变量随循环次数变化,为了取余

		// 循环的次数
		for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
			// 每一轮取余
			for (int j = 0; j < arr.length; j++) {
				// 计算余数
				int ys = (arr[j] / n) % 10;
				// 把便利店数据放在指定数组中,有两个信息,放在第几个桶+数据应该放在第几位
				temp[ys][counts[ys]] = arr[j];
				// 记录数量
				counts[ys]++;
			}

			// 记录取的数字应该放到位置
			int index = 0;
			// 每一轮循环之后把数字取出来
			for (int k = 0; k < counts.length; k++) {
				// 记录数量的数组中当前余数记录不为零
				if (counts[k] != 0) {
					for (int l = 0; l < counts[k]; l++) {
						// 取出元素
						arr[index] = temp[k][l];
						index++;
					}
					// 取出后把数量置为零
					counts[k] = 0;
				}
			}

		}
	}

}
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值