【数据结构与算法】计数、基数、桶 O(n) 不基于比较
冒泡、插入、選擇 O(n^2) 基于比較
快排、歸并 O(nlogn) 基于比較
計數、基數、桶 O(n) 不基于比較
桶排序–>分區間桶+快速排序(歸并排序(穩定性))–>取出結果
計數排序(特殊的桶排序)–>分單個桶+計數–>
先統計計數,再取出來,實現排序
基數排序–>在每個位上桶排序–>
一、線性排序算法介紹
1.線性排序算法包括桶排序、計數排序、基數排序。
2.線性排序算法的時間復雜度為O(n)。
3.此3種排序算法都不涉及元素之間的比較操作,是非基于比較的排序算法。
4.對排序數據的要求很苛刻,重點掌握此3種排序算法的適用場景。
二、桶排序(Bucket sort)
1.算法原理:
1)將要排序的數據分到幾個有序的桶里,每個桶里的數據再單獨進行快速排序。
2)桶內排完序之后,再把每個桶里的數據按照順序依次取出,組成的序列就是有序的了。
2.使用條件
1)要排序的數據需要很容易就能劃分成m個桶,并且桶與桶之間有著天然的大小順序。
2)數據在各個桶之間分布是均勻的。
3.適用場景
1)桶排序比較適合用在外部排序中。
2)外部排序就是數據存儲在外部磁盤且數據量大,但內存有限無法將整個數據全部加載到內存中。
4.應用案例
1)需求描述:
有10GB的訂單數據,需按訂單金額(假設金額都是正整數)進行排序
但內存有限,僅幾百MB
2)解決思路:
掃描一遍文件,看訂單金額所處數據范圍,比如1元-10萬元,那么就分100個桶。
第一個桶存儲金額1-1000元之內的訂單,第二個桶存1001-2000元之內的訂單,依次類推。
每個桶對應一個文件,并按照金額范圍的大小順序編號命名(00,01,02,…,99)。
將100個小文件依次放入內存并用快排排序。
所有文件排好序后,只需按照文件編號從小到大依次讀取每個小文件并寫到大文件中即可。
3)注意點:若單個文件無法全部載入內存,則針對該文件繼續按照前面的思路進行處理即可。
三、計數排序(Counting sort)
1.算法原理
1)計數其實就是桶排序的一種特殊情況。
2)當要排序的n個數據所處范圍并不大時,比如最大值為k,則分成k個桶
3)每個桶內的數據值都是相同的,就省掉了桶內排序的時間。
2.代碼實現
案例分析:
假設只有8個考生分數在0-5分之間,成績存于數組A[8] = [2,5,3,0,2,3,0,3]。
使用大小為6的數組C[6]表示桶,下標對應分數,即0,1,2,3,4,5。
C[6]存儲的是考生人數,只需遍歷一邊考生分數,就可以得到C[6] = [2,0,2,3,0,1]。
對C[6]數組順序求和則C[6]=[2,2,4,7,7,8],c[k]存儲的是小于等于分數k的考生個數。
數組R[8] = [0,0,2,2,3,3,3,5]存儲考生名次。那么如何得到R[8]的呢?
從后到前依次掃描數組A,比如掃描到3時,可以從數組C中取出下標為3的值7,也就是說,到目前為止,包括自己在內,分數小于等于3的考生有7個,也就是說3是數組R的第7個元素(也就是數組R中下標為6的位置)。當3放入數組R后,小于等于3的元素就剩下6個了,相應的C[3]要減1變成6。
以此類推,當掃描到第二個分數為3的考生時,就會把它放入數組R中第6個元素的位置(也就是下標為5的位置)。當掃描完數組A后,數組R內的數據就是按照分數從小到大排列的了。
3.使用條件
1)只能用在數據范圍不大的場景中,若數據范圍k比要排序的數據n大很多,就不適合用計數排序;
2)計數排序只能給非負整數排序,其他類型需要在不改變相對大小情況下,轉換為非負整數;比如如果考試成績精確到小數后一位,就需要將所有分數乘以10,轉換為整數。
四、基數排序(Radix sort)
1.算法原理(以排序10萬個手機號為例來說明)
1)比較兩個手機號碼a,b的大小,如果在前面幾位中a已經比b大了,那后面幾位就不用看了。
2)借助穩定排序算法的思想,可以先按照最后一位來排序手機號碼,然后再按照倒數第二位來重新排序,以此類推,最后按照第一個位重新排序。
3)經過11次排序后,手機號碼就變為有序的了。
4)每次排序有序數據范圍較小,可以使用桶排序或計數排序來完成。
2.使用條件
1)要求數據可以分割**獨立的“位”**來比較(不夠補‘0’);
2)位之間由遞進關系,如果a數據的高位比b數據大,那么剩下的地位就不用比較了;
3)每一位的數據范圍不能太大,要可以用線性排序,否則基數排序的時間復雜度無法做到O(n)。
五、思考
1.如何根據年齡給100萬用戶數據排序?
實際上,根據年齡給 100 萬用戶排序,就類似按照成績給 50 萬考生排序。我們假設年齡的范圍最小 1 歲,最大不超過 120 歲。我們可以遍歷這 100 萬用戶,根據年齡將其劃分到這 120 個桶里,然后依次順序遍歷這 120 個桶中的元素。這樣就得到了按照年齡排序的 100 萬用戶數據。
2.對D,a,F,B,c,A,z這幾個字符串進行排序,要求將其中所有小寫字母都排在大寫字母前面,但是小寫字母內部和大寫字母內部不要求有序。比如經過排序后為a,c,z,D,F,B,A,這個如何實現呢?如果字符串中處理大小寫,還有數字,將數字放在最前面,又該如何解決呢?
用兩個指針a、b:a指針從頭開始往后遍歷,遇到大寫字母就停下,b從后往前遍歷,遇到小寫字母就停下,交換a、b指針對應的元素;重復如上過程,直到a、b指針相交。
對于小寫字母放前面,數字放中間,大寫字母放后面,可以先將數據分為小寫字母和非小寫字母兩大類,進行如上交換后再在非小寫字母區間內分為數字和大寫字母做同樣處理
筆記整理來源: 王爭 數據結構與算法之美
總結
以上是生活随笔為你收集整理的【数据结构与算法】计数、基数、桶 O(n) 不基于比较的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux面试题(34道)
- 下一篇: 0803