如何給廣東省人口按照年齡來排序?


      據統計,廣東省人口已經突破一億人,是中國人口最多的省份,那么我們如何快速給廣東省人口按照年齡來排序呢?大家都知道快速排序的時間復雜度是O(nlogn),那還有比快速排序更快的算法嗎?那就跟我來一探究竟。

計數排序

      計數排序的思想很簡單:當要排序 n 個數據,並且n的取值范圍並不大的時候,比如最大值是k,我們就可以把數據划分成k個桶,每個桶內的數據值都是相同的。我們來觀察一下年齡這個數據的特征是啥?我們假設最大的年齡是120歲,最小的年齡是0歲,那么年齡的數據范圍是0-120歲,這就說明年齡的取值范圍不大,正好符合計數排序的數據要求。所以我們可以分成121個桶,對應年齡0~120。我們根據人的年齡,將所有廣東省的人口划入

這個121個桶里。桶內的數據都是年齡相同的人,所以不需要再排序。我們只需要依次掃描每個桶,將桶內的數據輸出,就實現了廣東省人口按年齡來排序,因為只是涉及到了遍歷操作,所以時間復雜度是O(n)。 

     我們接下來來看一下計數排序的具體實現。我們還拿年齡的例子來看,為了方便說明,我們將數據規模進行了簡化處理,假設只有7個人,年齡的范圍是0~5。這7個人的年齡放在一個數組A中。他們分別是5,4,3,3,2,4,0。

     年齡的范圍是0~5,我們使用大小為6的數組C表示桶,其中數組的下標對應的是年齡,C數組存儲的是對應年齡的人數。我們遍歷一遍人口年齡數據,就可以給數組C初始化完成。

圖片

      從圖中可以看出,年齡為3的人數是2,小於3的人數有2個,所以,年齡為3的人在排序之后的有序數組中,會保存下標2,3的位置。

圖片

      那我們如何快速計算出,每個年齡的人在有序數組中對應的存儲位置呢?這個處理方法非常巧妙,很不容易想到。思路是這樣的:我們對數組C順序求和,數組C存儲的數據就變成了下面這樣子。C[k]里存儲小於等於年齡k的人的個數。

圖片

        接下來是最核心的部分了。我們從后到前依次遍歷數組A。比如,當掃描到0時,我們從數組C中取出下標為0的值1,也就是說,到目前為止,包括自己在內,年齡小於等於 0 的人數有 1 個,也就是說 0 是數組 R 中的第 1 個元素(也就是數組 R 中下標為 0 的位置)。當0放入到數組 R 中后,小於等於 0 的元素就只剩下了 1 個了,所以相應的 C[0]要減 1,變成 0。當我們掃描完整個數組 A 后,數組 R 內的數據就是按照分數從小到大有序排列的了。

圖片

      接下來,我們來看一下代碼是如何實現的。

def countingSort(a,n):
     if n<=1:
          return

     #求出最大值
     max_data=max(a)

     c=[0 for i in range(max_data+1)]

     #初始化C
     for j in a:
          c[j]+=1

     ##依次累加
     for i in range(1,max_data+1) :
         c[i] = c[i-1] + c[i]

     r=[0 for i in range(n)]

     for i in range(n-1,-1,-1):
          index = c[a[i]]-1
          r[index] = a[i]
          c[a[i]]-=1
     return r


a=[5,4,3,3,2,4,0]
r=countingSort(a,len(a))
print(r)

  

    總結一下,計數排序只能用在數據范圍不大的場景中,如果數據范圍 k 比要排序的數據 n 大很多,就不適合用計數排序了。而且,計數排序只能給非負整數排序,如果要排序的數據是其他類型的,要將其在不改變相對大小的情況下,轉化為非負整數。

     計數排序你學會了嗎?歡迎留言和我一起討論,更多有趣內容,請關注公眾號。

image.png


免責聲明!

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



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