當前位置:
首頁 > 科技 > 漫畫:什麼是計數排序?

漫畫:什麼是計數排序?

(畫外音:這都寒露了喲)

第二天

————————————

假定20個隨機整數的值如下:

9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9。

如何給這些無序的隨機整數排序呢?

非常簡單,讓我們遍歷這個無序的隨機數列,每一個整數按照其值對號入座,對應數組下標的元素進行加1操作。

比如第一個整數是9,那麼數組下標為9的元素加1:

第二個整數是3,那麼數組下標為3的元素加1:

繼續遍曆數列並修改數組......

最終,數列遍歷完畢時,數組的狀態如下:

數組每一個下標位置的值,代表了數列中對應整數出現的次數。

有了這個「統計結果」,排序就很簡單了。直接遍曆數組,輸出數組元素的下標值,元素的值是幾,就輸出幾次:

0,1,1,2,3,3,3,4,4,5,5,6,7,7,8,9,9,9,9,10。

顯然,這個輸出的數列已經是有序的了。

publicstaticint[] countSort(int[]array) {

//1.得到數列的最大值

intmax =array[];

for(inti=1; i

if(array[i] > max){

max =array[i];

}

}

//2.根據數列最大值確定統計數組的長度

int[] countArray =newint[max+1];

//3.遍曆數列,填充統計數組

for(inti=; i

countArray[array[i]]++;

}

//4.遍歷統計數組,輸出結果

intindex =;

int[] sortedArray =newint[array.length];

for(inti=; i

for(intj=; j

sortedArray[index++] = i;

}

}

returnsortedArray;

}

publicstaticvoidmain(String[] args){

int[]array=newint[] {4,4,6,5,3,2,8,1,7,5,6,,10};

int[] sortedArray = countSort(array);

System.out.println(Arrays.toString(sortedArray));

}

這段代碼在一開頭補充了一個步驟,就是求得數列的最大整數值max。後面創建的統計數組countArray,長度就是max+1,以此保證數組的最後一個下標是max。

95,94,91,98,99,90,99,93,91,92。

怎麼解決這個問題呢?

很簡單,我們不再以(輸入數列的最大值+1)作為統計數組的長度,而是以(數列最大值和最小值的差+1)作為統計數組的長度。

同時,數列的最小值作為一個偏移量,用於統計數組的對號入座。

以剛才的數列為例,統計數組的長度為 99-90+1 = 10 ,偏移量等於數列的最小值 90 。

對於第一個整數95,對應的統計數組下標是 95-90 = 5,如圖所示:

什麼意思呢?讓我們看看下面的例子:

給定一個學生的成績表,要求按成績從低到高排序,如果成績相同,則遵循原表固有順序。

那麼,當我們填充統計數組以後,我們只知道有兩個成績並列95分的小夥伴,卻不知道哪一個是小紅,哪一個是小綠:

下面的講解會有一些燒腦,請大家扶穩坐好。我們仍然以剛才的學生成績表為例,把之前的統計數組變形成下面的樣子:

這是如何變形的呢?統計數組從第二個元素開始,每一個元素都加上前面所有元素之和。

為什麼要相加呢?初次看到的小夥伴可能會覺得莫名其妙。

這樣相加的目的,是讓統計數組存儲的元素值,等於相應整數的最終排序位置。比如下標是9的元素值為5,代表原始數列的整數9,最終的排序是在第5位。

接下來,我們創建輸出數組sortedArray,長度和輸入數列一致。然後從後向前遍歷輸入數列:

第一步,我們遍歷成績表最後一行的小綠:

小綠是95分,我們找到countArray下標是5的元素,值是4,代表小綠的成績排名位置在第4位。

同時,我們給countArray下標是5的元素值減1,從4變成3,,代表著下次再遇到95分的成績時,最終排名是第3。

第二步,我們遍歷成績表倒數第二行的小白:

小白是94分,我們找到countArray下標是4的元素,值是2,代表小白的成績排名位置在第2位。

同時,我們給countArray下標是4的元素值減1,從2變成1,,代表著下次再遇到94分的成績時(實際上已經遇不到了),最終排名是第1。

第三步,我們遍歷成績表倒數第三行的小紅:

小紅是95分,我們找到countArray下標是5的元素,值是3(最初是4,減1變成了3),代表小紅的成績排名位置在第3位。

同時,我們給countArray下標是5的元素值減1,從3變成2,,代表著下次再遇到95分的成績時(實際上已經遇不到了),最終排名是第2。

這樣一來,同樣是95分的小紅和小綠就能夠清楚地排出順序了,也正因此,優化版本的計數排序屬於穩定排序

後面的遍歷過程以此類推,這裡就不再詳細描述了。

publicstaticint[] countSort(int[]array) {

//1.得到數列的最大值和最小值,並算出差值d

intmax =array[];

intmin =array[];

for(inti=1; i

if(array[i] > max) {

max =array[i];

}

if(array[i]

min =array[i];

}

}

intd = max - min;

//2.創建統計數組並統計對應元素個數

int[] countArray =newint[d+1];

for(inti=; i

countArray[array[i]-min]++;

}

//3.統計數組做變形,後面的元素等於前面的元素之和

intsum =;

for(inti=;i

sum += countArray[i];

countArray[i] = sum;

}

//4.倒序遍歷原始數列,從統計數組找到正確位置,輸出到結果數組

int[] sortedArray =newint[array.length];

for(inti=array.length-1;i>=;i--) {

sortedArray[countArray[array[i]-min]-1]=array[i];

countArray[array[i]-min]--;

}

returnsortedArray;

}

publicstaticvoidmain(String[] args){

int[]array=newint[] {95,94,91,98,99,90,99,93,91,92};

int[] sortedArray = countSort(array);

System.out.println(Arrays.toString(sortedArray));

}

1.當數列最大最小值差距過大時,並不適用計數排序。

比如給定20個隨機整數,範圍在0到1億之間,這時候如果使用計數排序,需要創建長度1億的數組。不但嚴重浪費空間,而且時間複雜度也隨之升高。

2.當數列元素不是整數,並不適用計數排序。

本漫畫純屬娛樂,還請大家盡量珍惜當下的工作,切勿模仿小灰的行為哦。

聲明:本文為作者投稿,首發於個人公眾號程序員小灰,版權歸其所有。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

今天,阿里用「平頭哥」死磕起了中國芯!
BAT 面試中,遇到知識盲點如何巧妙圓場?

TAG:CSDN |