數據結構與算法-排序(九)基數排序(Radix Sort)


摘要

基數排序是進行整數序列的排序,它是將整數從個位開始,直到最大數的最后一位截止,每一個進位(比如個位、十位、百位)的數進行排序比較。

每個進位做的排序比較是用計數排序的方式處理,所以基數排序離不開計數排序。

邏輯

對整數依次從個位數、十位數...進行排序。基數排序非常適合用於整數排序

對每一輪的排序可以使用計數排序的方法處理

基數排序和計數排序來做個簡單的比較時,可以看到基數排序每一個進位都要進行一次計數排序,所以比較循環多一些。但是每個進制上的數范圍是 0 到 9 這 10 個數,所以需要開辟的空間相對可控和少一些。下面來詳細了解一下

流程

  1. 獲取序列中的最大值,確定排序的最大位數
  2. 從個位起,使用計數排序的方式處理序列

實現

找出最大值, max 的初始值為序列的 first 元素。循環從 1 開始。

	int max = array[0];
	for (int i = 1; i < array.length; i++) {
		if (array[i] > max) {
			max = array[i];
		}
	}

對序列從個位開始排序(計數排序的方式)。這里要留意,divider 的每一次增加是 divider *= 10,相當於向前進一位。

這里的每一輪比較排序中,交換的是序列中的元素,而不是某個進位上的數字,這個要特別注意。


	for (int divider = 1; divider <= max; divider *= 10) {
		CountingSort(divider);
	}

下面的排序就是用計數排序來處理,對計數排序不太明白的可以看上一期介紹計數排序。

這里有兩點需要留意:

  1. 這里直接開辟了 10 個存儲空間,是因為,每一個進位上的數只有 0 到 9 這 10 個數
  2. 這里通過 divider % 10 這個方式獲取到該進位上的數字。

	private void CountingSort(int divider) {
		
		// 開辟內存空間,存儲次數
		int[] counts = new int[10];
		// 統計每個整數出現的次數
		for (int i = 0; i < array.length; i++) {
			counts[array[i] / divider % 10]++;
		}
		// 累加次數
		for (int i = 1; i < counts.length; i++) {
			counts[i] += counts[i-1];
		}
		
		// 從后往前遍歷數組,放在有序數組中的位置
		int[] newArray = new int[array.length];
		for (int i = array.length - 1; i >= 0; i--) {
			newArray[--counts[array[i] / divider % 10]] = array[i];
		}
		// 將有序數組覆蓋到 array
		for (int i = 0; i < newArray.length; i++) {
			array[i] = newArray[i];
		}
	}

時間和空間復雜度

  • 最好、最壞、平均時間復雜度:O(d*(n+k))
  • 空間復雜度:O(n+k)
  • 屬於穩定排序

d 是最大值的位數,k 是進制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM