非比較排序--基數排序實現給字符串數組排序

1.計數排序的侷限性

 

    前面學習了計數排序,可以實現O(n+k)的時間複雜度,但是他有很大的侷限性,最大的問題就是如果最大值和最小值之間相差太大的話,那麼會浪費掉很大的空間,比如要排序{1,10000,99,64,120}我們可以根據之前的計算公式最大值減去最小值加一得到計數數組的長度,那麼計數數組長度就應該是10000,但是實際上我們只存放了5個數據,中間浪費了極大的空間,所以在使用計數排序時,應該根據自己的實際情況來決定。

    比如我們要對電話號碼進行一個排序,顯然用計數排序是很浪費空間的,同時因爲時間複雜度爲O(n+k),但是n太大時,實際上他不一定比快速排序或者歸併排序要快。

 

2.基數排序

 

    什麼是基數排序呢?基數排序和計數排序都是桶排序的一種思想,基數是一種關鍵字排序,例如我們有這樣的一組數據{421,326,266,157,222,414}我們首先拿到每一個數的最後一位,也就是個位,然後進行排序,排序好後再取出十位進行排序,最後拿出百位來進行排序即可,而其中我們每次取的位就是對關鍵字的操作。

 

 

    ps:需要注意的是我們第一次根據個位排序時操作的是原數組,而根據十位排序的時候是在之前個位排好的基礎上進行排序,同理百位則是對十位排好後的進行排序。

    看到這兒聰明的你肯定會問,如果位數不一致怎麼辦?比如有的是3位數,有的是4位數,甚者有可能還有2位數以及1位數,其實這個很好解決我們只需要找到最大的那個數,然後根據最大的那個數來決定排幾次,其餘不足的在前面添0,比如最大222,其中又有1位數的,2位數的,那麼就在2位數前面加一個0,而1位數則在前面加2個0即可。

 

java代碼實現如下

 

    實際上我們這個代碼已經實現了自動加0的功能,我們用Math.pow(10,i)來產生10的i平方,然後拿到原數組中的值除以得到的平方數再求餘10,如果是1除以1000是0,再用0取餘10所以還是0,所以會自動補0。

 

3.基數排序時間空間複雜度

 

    我們來看看時間複雜度和空間複雜度,實際上找出最大數的位數爲多少位,這一步應該是在外面計算好了傳遞進來的,他並不屬於基數排序裏面的。

    

    最外層一共循環了d次,其中d就是我們最大數的位數,而循環體內我們對原數組遍歷了2次,所以是2n,而計數數組執行了一次就是k,也就是O(d*(2n+k)),然後我們去掉一個常數階,可以得到時間複雜度爲O(d*(n+k)),那空間複雜度又是多少呢?根據我們寫的代碼,我們一共定義了一個計數數組和一個結果數組所以是O(n+10),然後去掉一個常數階可以得到空間複雜度爲O(n)。且基數排序是一個穩定的排序算法。

 

4.基數排序字符串排序

 

    如何用基數排序實現對字符串排序呢?我們還是使用同樣的方式例如字符串數{"abc","def","sxf","sss","cbh"},我們拿到最後一位放入對應的位置,比如abc,當我們拿到c時這個時候由於是字符串你是根本不知道放那個位置的,所以我們可以將他變成char的字符,由於c字符對應的ASCll是99,所以我們存放在99的位置就行,當然如果字符串位數不一致,同理我們可以在前面補一個比A的ASCll還小的值即可。字符串排序重點就是要藉助ASCll來實現。

 

Java代碼實現如下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章