알고리즘 노트-기수 정렬

기본 정렬

소개

1) 기수 정렬 (radixsort)은 ** "bucket sort **"(버킷 정렬) 또는 binsort로도 알려진 " distribution sort"(distributionsort) 에 속합니다. 이름에서 알 수 있듯이 각 비트의 값으로 정렬 됩니다. 키 값요소는 정렬 효과를 얻기 위해 일부 "버킷"에 할당됩니다 .
2) 기수 정렬 방법은 안정적인 정렬 이고 기수 정렬 방법은 효율적이고 안정적인 정렬 방법입니다.
3) 기수 정렬 ( RadiXSort) 는 버킷 정렬입니다. 확장
4) 기본 번호 정렬은 1887 년 Hermann Holly에 의해 발명되었습니다. 이는 다음과 같이 구현됩니다. 정수는 자릿수에 따라 다른 숫자로 잘린 다음 각 자릿수에 따라 비교됩니다.

도표

img

생각 정렬

동일한 숫자 길이와 비교할 모든 값을 통합하고 더 짧은 숫자로 숫자 앞에 0을 채 웁니다. 그런 다음 가장 낮은 비트부터 시작하여 순서대로 한 번 정렬합니다. 이렇게하면 가장 낮은 순서에서 가장 높은 순서로 순서가 지정된 순서가됩니다.

이해

즉, 숫자를 세어 해당 위치에 넣습니다. 예를 들어 3 열에 3을, 1 열에 41을 넣습니다. 3이 한 자릿수이고 앞에 0이 추가되면 어떻게 될까요? . 03이고 3 열은 버킷 중 하나이고 1은 버킷, 51은 1 버킷, 23은 3 버킷에도 있습니다.

즉, 0-9에서 10 개의 버킷이 있습니다 (정확히 10 개의 버킷이 아닐 수도 있음).

주제 : HKUST 팀의 점수는 53,3,542,748,14,214입니다. 기수 정렬 방법을 사용하여이 사람들의 점수를 가장 작은 것부터 가장 큰 것까지 정렬하십시오.

단계

1. 각 요소의 한 자리를 꺼내 해당 버킷에이 숫자를 넣습니다 ( 버킷은 1 비트의 배열입니다 ).

2. 버킷 (1 차원 배열 첨자)의 순서에 따라 데이터를 순서대로 꺼내 원래 배열에 다시 넣습니다.

3. 배열 정렬의 첫 번째 라운드

542 53 3 14214748

4. 방금 전 작업에 따라 542 53 3 14 214 748을 다시 수행하지만 이번에는 10 자리 숫자로 이동하여 버킷을 지정합니다.

0 배럴 3

1 배럴 14214

4 배럴 542748

53 개 배럴 5 개

원래 배열로 돌아 가기

5. 두 번째 정렬 결과

3 14214542748 53

6. 세 번째 라운드에서 동일한 이유는 두 번째 정렬을 기준으로 100 자리 숫자로 버킷을 정의하기 때문입니다.

0 배럴 3 14 53

2 배럴 214

5 배럴 542

7 배럴 748

세 번째 정렬의 결과

3 14 53214542748이 최종 결과입니다.

재귀 적 단계가 없다는 것을 알 수 있는데 몇 번이나 걸리나요? 배열에서 가장 큰 숫자의 자릿수에 따라 다릅니다.이 배열에서 748의 가장 큰 숫자는 100 자릿수이므로 3 자릿수입니다. 4 자릿수이면 4 번입니다.

코드 유도

	//基数排序方法
	public static void radixSort(int[] arr){
    
    
		//第一轮排序(针对每个元素的个位进行排序)
		//定义一个二维数组,表示10个桶,每个桶就是一个一位数组
		//说明
		//1.二维数组包含10个一位数组,但是一位数组要多大?
		//2.为了防止再放入数字的时候,数据溢出,则我们每个一位数组(桶)大小定位arr.length
		//基数排序也就是空间换时间的算法
		int[][] bucket = new int[10][arr.length];//这个桶要多大?
		//我们怎么把数据从桶中取出来呢?我们桶中实际有多少个数据呢?
		//为了记录,我们定义一个一维数组来记录各个桶中每次放入的个数
		//bucketElementCounts[0]就是记录0桶中有几个数据
		int[] bucketElementCounts = new int[10];
		//第一轮
		for(int j = 0;j < arr.length;j++){
    
    
			//取出个位数字
			int digitOfElement = arr[j] %10;
			//放入到对应的桶中
			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
			bucketElementCounts[digitOfElement]++;
		}
		//重新放回原数组
		int index = 0;
		//遍历每一个桶,并将桶中的数据放入到原数组
		for(int  k = 0; k < bucketElementCounts.length;k++){
    
    
			//如果桶中有数据
			if(bucketElementCounts[k] != 0){
    
    
				//循环该桶  即第k个桶,即第k个一维数组
				for(int l = 0;l < bucketElementCounts[k];l++){
    
    
					//取出元素,放回原数组
					arr[index] = bucket[k][l];
					index++;
				}
				//第一轮取出数据后,需要将每个bucketElementCounts[k] = 0
				//为了我们第二轮第三轮处理的时候,没有数据
				bucketElementCounts[k] = 0;
			}
		}
		System.out.println("第一轮对个位的排序处理"+Arrays.toString(arr));
		
		//第二轮处理
		for(int j = 0;j < arr.length;j++){
    
    
			//取出个位数字
			int digitOfElement = arr[j] /10 %10;
			//放入到对应的桶中
			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
			bucketElementCounts[digitOfElement]++;
		}
		//重新放回原数组
		index = 0;
		//遍历每一个桶,并将桶中的数据放入到原数组
		for(int  k = 0; k < bucketElementCounts.length;k++){
    
    
			//如果桶中有数据
			if(bucketElementCounts[k] != 0){
    
    
				//循环该桶  即第k个桶,即第k个一维数组
				for(int l = 0;l < bucketElementCounts[k];l++){
    
    
					//取出元素,放回原数组
					arr[index] = bucket[k][l];
					index++;
				}
				bucketElementCounts[k] = 0;
			}
		}
		System.out.println("第二轮对十位的排序处理"+Arrays.toString(arr));
		//第三轮
		for(int j = 0;j < arr.length;j++){
    
    
			//取出个位数字
			int digitOfElement = arr[j] /100;
			//放入到对应的桶中
			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
			bucketElementCounts[digitOfElement]++;
		}
		//重新放回原数组
		index = 0;
		//遍历每一个桶,并将桶中的数据放入到原数组
		for(int  k = 0; k < bucketElementCounts.length;k++){
    
    
			//如果桶中有数据
			if(bucketElementCounts[k] != 0){
    
    
				//循环该桶  即第k个桶,即第k个一维数组
				for(int l = 0;l < bucketElementCounts[k];l++){
    
    
					//取出元素,放回原数组
					arr[index] = bucket[k][l];
					index++;
				}
				bucketElementCounts[k] = 0;
			}
		}
		System.out.println("第三轮对百位的排序处理"+Arrays.toString(arr));
	}

최종 코드

import java.util.Arrays;

//基数排序
//@author   王庆华
//2021年1月14日13:39:02
public class RadioxSort {
    
    
	public static void main(String[] args) {
    
    
		int arr[] = {
    
    53,3,542,748,14,214};
		radixSort(arr);
		
	}
	//基数排序方法
	public static void radixSort(int[] arr){
    
    
		//1.得到数组中最大数的位数
		int max = arr[0];//假设第一个数就是最大数
		for(int i=1;i < arr.length;i++){
    
    
			if(arr[i] > max){
    
    
				max = arr[i];
			}
		}
		//得到最大数是几位数
		int maxLength = (max+"").length();//变成字符串
		int[][] bucket = new int[10][arr.length];
		int[] bucketElementCounts = new int[10];
		//使用循环对代码处理
		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][bucketElementCounts[digitOfElement]] = arr[j];
				bucketElementCounts[digitOfElement]++;
			}
			//重新放回原数组
			int index = 0;
			//遍历每一个桶,并将桶中的数据放入到原数组
			for(int  k = 0; k < bucketElementCounts.length;k++){
    
    
				//如果桶中有数据
				if(bucketElementCounts[k] != 0){
    
    
					//循环该桶  即第k个桶,即第k个一维数组
					for(int l = 0;l < bucketElementCounts[k];l++){
    
    
						//取出元素,放回原数组
						arr[index] = bucket[k][l];
						index++;
					}
					//第一轮取出数据后,需要将每个bucketElementCounts[k] = 0
					//为了我们第二轮第三轮处理的时候,没有数据
					bucketElementCounts[k] = 0;
				}
			}
			System.out.println("第"+(i+1)+"轮对个位的排序处理"+Arrays.toString(arr));
		}
	}
}

추천

출처blog.csdn.net/qq_22155255/article/details/112620310