演算法——排序演算法——計數排序優化
在前幾篇部落格中講了計數排序的一般方法,理解起來比較簡單。但是上一次提到的計數排序只是簡單的按照陣列下標統計輸出了元素的值,並沒有真正將原來的資料進行排序。在日常的使用當中,往往會出現相同的資料進行排序,如果還使用前幾篇的方法就會發現有些力不從心了,下面來說說如何對計數排序進行優化。
比如說有幾個人的成績分別是:小紅:90,小橙:99,小黃:95,小綠:94,小青:95。將這些學生的成績按照從低到高的順序進行排序,如果成績相同按照原來的先後順序。
首先,還是建立統計陣列countArray如下所示:
但是兩個95分的學生的成績不知道順序如何排列,為了解決這個問題我們隊統計陣列進行變形,得到如下陣列
具體的變化過程是:從統計陣列的第二個元素開始,每一個元素的值都是本元素的值加上前面的所有的元素值之和。這樣做的目的是把整數放到最終排序的位置上去,比如9對應的元素是5,則99最終應該排在第五位。
下面我們對照成績表把統計陣列中的元素遍歷出來,並排序,注意:每遍歷一個,就在統計陣列中將其值減1,從後往前遍歷成績表,第一個是小青:95,對應的值為4,則表示小青95分應該排在第四位,同時統計陣列中下標5對應的值應減1變為3,接著小綠94分,應該排在第二位,同時修改統計陣列對應的值為1,下面是小黃95,對應的值為3,應該排在第三位修改下標為2(實際上已經用不到了),下面是小橙99分,對應的值為5,應該排在第五位,修改下標值為4(實際上已經用不到了),最後是小紅90分,對應的值為1,應該排在第一位,修改下標的值為0(實際上已經用不到了)。這樣通過遍歷得到一個新的排序:
設原始數列規模是n,最大最小整數差是m,則時間複雜度為o(n+m),空間複雜度為o(m)。計數排序的缺點是當最大值最小值差距過大時,不適用計數排序,當元素不是整數值,不適用計數排序。
具體java實現程式碼如下:
import java.util.Arrays; public class countSort { /** * @param args */ public static int[] countSort(int[] array){ //定義陣列的最大值最小值,並算出差值 int max = array[0]; int min = 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 d=max-min; //建立統計陣列並統計對應元素個數 int[] countArray = new int[d+1]; //遍歷陣列,把統計陣列填上 for(int i1=0;i1<array.length;i1++){ countArray[array[i1]-min]++; } //統計陣列做變形,後面的元素等於前面的元素之和 int sum=0; for(int j=0;j<countArray.length;j++){ sum+=countArray[j]; countArray[j]=sum; } //倒敘遍歷原始數列,從統計陣列中找到正確的位置,輸出到結果陣列 int[] sorteArray=new int[array.length]; for(int i=array.length-1;i>=0;i--){ sorteArray[countArray[array[i]-min]-1]=array[i]; countArray[array[i]-min]--; } return sorteArray; } public static void main(String[] args) { // TODO Auto-generated method stub int[] array= new int[]{95,94,91,98,99,90,99,93,91,92}; int[] sortArray=countSort(array); System.out.println(Arrays.toString(sortArray)); } }
輸出結果:[90, 91, 91, 92, 93, 94, 95, 98, 99, 99]
優化後的版本的計數排序屬於一種穩定排序。