倒序排序_排序算法(六):Counting Sort 计数排序
之前文章介紹的一些排序算法都是基于比較來進行排序的,故它們在平均情況下的時間復雜度最好也不過是線性對數級別。這里我們來介紹一種簡單的基于非比較的排序算法——Counting Sort 計數排序,其時間復雜度可以達到線性級別
基本思想
Counting Sort 計數排序,顧名思義,就是統計待排序數組元素的出現次數。其基本思想比較簡單: 1. 根據待排序元素的數值范圍大小k(max-min+1),建立一個k大小的頻數統計數組counts。對于counts數組而言,其索引范圍 0 ~ k-1,正好可以對應到待排序元素的取值范圍min~max上 2. 統計待排序元素element的次數,并其存儲到counts數組中,即counts[ elemet-min ] = countValue 3. 待計數統計完成后遍歷counts數組,根據次數值來輸出原待排序元素值,此時即完成排序
這里給出計數排序在Java下的實現:
/*** 計數排序*/ public class CountingSort {/*** 升序排列 (非穩定)*/public static void sort1() {// 獲取測試用例int[] array = getTestCase();int size = array.length;System.out.println("before sort: " + Arrays.toString(array) );// 求取最值int[] minMax = getMinMax(array);int min = minMax[0];int max = minMax[1];// 根據數據范圍創建統計數組int k = max-min+1;int[] counts = new int[ k ];// 統計原數組中元素出現的次數for(int i=0; i<size; i++) {int dataInCountIndex = array[i] - min; // 計算原數組元素在統計數組中的索引counts[dataInCountIndex] +=1; // 統計該值次數}int j = 0; // 有序的數據的插入位置for(int i=0; i<k; i++) {int originalData = i + min; // 還原 原排序數組的數據值while( counts[i]>0 ) {array[j] = originalData;counts[i]--; // 該數值出現的次數減1j++; // 更新有序數據的插入位置}}System.out.println("after sort: " + Arrays.toString(array) );} /*** 求指定數組的最值* @param array* @return [0]: 最小值; [1]: 最大值;*/private static int[] getMinMax(int[] array) {int min = array[0];int max = array[0];for(int i=1; i<array.length; i++) {if( array[i]>max ) {max = array[i];}if( array[i]<min ) {min = array[i];}}int[] minMax = new int[]{min,max};return minMax;}/*** 獲取測試用例*/private static int[] getTestCase() {int[] caseArray = {-1,1,-1,1,2};return caseArray;} }測試結果如下:
穩定的計數排序
基本原理
上面的計數排序算法是非穩定的,而一般我們所說的計數排序都是穩定的。那么如何保證計數排序的穩定性呢?其實很簡單,只需在統計完待排序元素的頻數后,對counts作累加計算(counts[i] = counts[i-1] + counts[i]),即計算統計數組中指定索引位置上的元素在排序后的位置;然后倒序遍歷原數組,根據counts數組中的排序位置來將待排序元素放入合適的位置,同時將counts數組相應的值減1,以使下一個重復的排序元素可以放在前一位的位置上,以保證穩定性
算法圖解
下圖即是通過穩定的計數排序對 -1,1,-1,1,2 序列進行升序排列的圖解過程
1. 建立counts數組
2. 倒序遍歷原待排序數組,按升序排列
Java實現
這里給出計數排序在Java下的實現:
/*** 計數排序*/ public class CountingSort {.../*** 升序排列 (穩定)*/public static void sort2() {// 獲取測試用例int[] array = getTestCase();int size = array.length;System.out.println("before sort: " + Arrays.toString(array) );// 求取最值int[] minMax = getMinMax(array);int min = minMax[0];int max = minMax[1];// 根據數據范圍創建統計數組int k = max-min+1;int[] counts = new int[ k ];// 統計原數組中元素出現的次數for(int i=0; i<size; i++) {int dataInCountIndex = array[i] - min; // 計算原數組元素在統計數組中的索引counts[dataInCountIndex] +=1; // 統計該值次數}// 計算統計數組的累計值,即計算 統計數組中指定索引位置上的元素在排序后的位置// 如果該索引位置上有重復元素,則為重復元素所占的最大排序位置for(int i=1; i<k; i++) {counts[i] = counts[i-1] + counts[i];}int[] sortedArray = new int[size]; // 排序結果數組// 倒序遍歷原數組,保證穩定性for(int i=size-1; i>=0; i--) {int dataInCountIndex = array[i] - min; // 計算原數組元素在統計數組中的索引// 計算其排序后的位置, 因為數組索引從0開始計算,故應對排序位置減1// 例如,排在最前面的元素,排序位置為1,則其在數組中的位置索引應為0int sortIndex = counts[dataInCountIndex] - 1;sortedArray[sortIndex] = array[i]; // 將原數組元素放入排序后的位置上counts[dataInCountIndex]--; // 下一個重復的元素,應排前一個位置,以保證穩定性}System.out.println("after sort: " + Arrays.toString(sortedArray) );}... }測試結果如下:
特點
復雜度、穩定性
這里以穩定的計數排序進行說明:
缺陷
參考文獻
總結
以上是生活随笔為你收集整理的倒序排序_排序算法(六):Counting Sort 计数排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一维卷积filter_面试题:CNN的卷
- 下一篇: layui table 添加img_la