桶排序——計數排序和基數排序
阿新 • • 發佈:2022-04-06
桶排序的基本思想:
* 之前所涉及到的簡單排序及複雜排序中的歸併排序,快速排序和堆排序都屬於基於比較的排序
* 而桶排序則是一個不基於比較的排序
*
* 桶排序這類不基於比較的排序的適用範圍較為有限
* 其核心思想是把有著相同特點的某些元素裝入一個桶,桶與桶之間是有序的,桶的內部也是有序的
* 最終只要按照這種順序把桶中元素依次倒出即可達到有序
*
* 桶排序適用於已知要排的陣列的大致範圍,且這個範圍不大的情況下,可以使用桶排序來進行
1.計數排序:
* 計數排序思想即用到了map陣列的思想,去統計範圍內每一個值出現的次數,再從小到大去遍歷這些可能的值*將其依次輸出
程式碼實現:
1 //桶排序之一——計數排序的實現 2 public static void CountSort(int[] arr,int min,int max) {//min--max為arr的可能取值範圍 3 int len = max - min + 1; 4 int[] count = new int[len]; 5 for (int i = 0; i < arr.length; i++) { 6 count[arr[i] - min]++; 7 } 8 intcnt = 0; 9 while (cnt < arr.length) { 10 for (int i = 0; i < len; i++) { 11 while (count[i] > 0) { 12 arr[cnt++] = i + min; 13 count[i]--; 14 } 15 } 16 } 17 }
2.
* 基數排序:(一般針對整形數進行使用(因為其位數已知))
* 其核心思想就是從低位到高位對每一位進行按位排序(因為每一位就10種情況,即範圍有限,所以可以使用桶排序思想)
* 只要保證每次低位排完以後,對在同一個桶的元素做到先進先出,那麼就可以處理掉每位的排序問題
* 又因為越高位在比較數的大小時優先順序越高,越有決定性,所以放到越後面來排
程式碼實現及解析:
1 //程式碼實現:(其程式碼實現中在以上的思想基礎上還涉及了諸多優化) 2 public static void radixSort(int[] arr,int l,int r) {//res為最大數的位數 3 if (l < r) { 4 int res = getRes(arr,l,r); 5 process(arr,l,r,res); 6 } 7 } 8 9 //獲得陣列範圍上的最大數的位數 10 public static int getRes(int[] arr,int l,int r) { 11 int res = 0; 12 int max = Integer.MIN_VALUE; 13 for (int i = l; i <= r; i++) { 14 max = Math.max(max, arr[i]); 15 } 16 while (max != 0) { 17 res++; 18 max /= 10; 19 } 20 return res; 21 } 22 23 //獲得x的從右到左的第d位 24 public static int getDigit(int x,int d) { 25 return ((x / ((int)Math.pow(10,d - 1))) % 10); 26 } 27 28 public static void process(int[] arr,int l,int r,int res) { 29 final int radix = 10;//一般都為10進位制數的排序 30 int[] budget = new int[r - l + 1];//用來臨時儲存每輪處理完後的陣列 31 for (int i = 1; i <= res; i++) {//最高位有res位則要進出桶res次,i表示從右到左的第i位 32 int[] count = new int[radix];//用來記錄0-9每種數字出現了幾次(放到迴圈內部重新申請,就不用對前一次 33 //得到的陣列進行置0操作) 34 for (int j = l; j <= r; j++) {//記錄當前第i位的0-9的數字的出現次數 35 int digit = getDigit(arr[j],i); 36 count[digit]++; 37 } 38 for (int j = 1; j < radix; j++) {//進行字首和處理,得到的字首和結果有 "分片" 的作用 39 count[j] += count[j - 1]; 40 } 41 //關鍵步驟:逆序(可以保證先進先出的思想)通過字首和的分片作用,調整出這輪排序後的結果,存到budget中 42 for (int j = r; j >= l; j--) { 43 int digit = getDigit(arr[j],i); 44 budget[--count[digit]] = arr[j]; 45 } 46 //將所得的結果budget存回到原陣列arr 47 for (int j = 0; j < budget.length; j++) { 48 arr[l + j] = budget[j]; 49 } 50 }