算法導論公開課筆記(三)線性時間排序

前言

首先這里列出的大家熟知的排序算法:冒泡排序、插入排序、歸并排序、堆排序、快速排序等。對于能在O(n lgn)時間內進行排序的算法,歸并排序和堆排序達到了最壞的情況下的上界;快速排序在平均情況下達到了該上界。

這些算法都有一個共同點:在排序的最終結果中,各元素的次序依賴于它們之間的比較。我們稱這類排序算法為比較排序

比較排序在排序的排序過程可以抽象成一棵決策樹。在最壞的情況下,任何比較排序算法都需要做Ω(n lgn)次比較。

線性時間排序

下面介紹兩種線性時間排序的算法:計數排序、基數排序。

計數排序

計數排序假設n個輸入的元素中每一個都是在[0,k]區間內的一個整數,其中k為某個整數。當k=O(n)時,排序的運行時間為θ(n)。

計數排序執行過程:

  1. 開辟計數數組空間,并遍歷待排序數組對帶排序數組進行計數賦值;
  2. 對計數數組進行疊加操作,得到元素所在的最后的位置;
  3. 遍歷待排序數組,根據得出的計數數組完成輸出數組的賦值;
計數排序圖例

計數排序Java 代碼:

    /**
     * 
     * @param a 數組
     * @param k 范圍;例如 k equals 5 ,range is [0,4]
     */
    public void countingSort(int[] a,int[] b,int k) {
        
        if(k<0||(a==null||a.length<1)) return;
        int[] c=new int[k];
        
        //counting
        for(int j=0;j<a.length;j++) {
            c[a[j]]+=1;
        }
        
        //convert
        for(int i=1;i<k;i++) {
            c[i]=c[i]+c[i-1];
        }
        
        for(int j=(a.length-1);j>=0;j--) {
            b[c[a[j]]-1]=a[j];
            c[a[j]]-=1;
        }
        
    }

測試代碼:

    public static void main(String[] args) {
        //假設a數組中的數都是[0,10)之間的數
        int[] a= {4,6,3,3,2,2,9,0,1,4,4,8,7,7};
        //排序數組
        int[] b=new int[a.length];
        new RadixSort().countingSort(a, b, 10);
        for(int i=0;i<b.length;i++) {
            System.out.println(i+" is "+b[i]);
        }
    }

測試結果:

0 is 0
1 is 1
2 is 2
3 is 2
4 is 3
5 is 3
6 is 4
7 is 4
8 is 4
9 is 6
10 is 7
11 is 7
12 is 8
13 is 9

基數排序

基數排序是先按最低有效位進行排序解決排序問題,算法用到了穩定排序算法-計數排序。
基數排序的偽代碼很簡單:

RADIX_SORT(A,d)
  for i =1 to d
    use a stable sort to sort array A on digit i;
基數排序排序過程

基數排序Java 代碼:


    /**
     * 10的次方數的結果值
     * @param d 次方數
     * @return 10的n次方的結果
     */
    private int tenPow(int d) {
        int result=1;
        for(int i=0;i<d;i++) {
            result*=10;
        }
        return result;
    }

    /**
     * 為計數排序優化的計數排序
     * @param a 待排序數組
     * @param b 輸出的數組
     * @param k 范圍;例如 k equals 5 ,range is [0,9]
     */
    public void countingSort4Radix(int[] a,int[] b,int k) {
        
        
        if(k<0||(a==null||a.length<1)) return;
        
        int[] temps=new int[a.length];
        for(int x=0;x<temps.length;x++) {//copying
            temps[x]=b[x];
        }

        int[] c=new int[k];
        
        //counting
        for(int j=0;j<a.length;j++) {
            c[a[j]]+=1;
        }
        
        //convert
        for(int i=1;i<k;i++) {
            c[i]=c[i]+c[i-1];
        }
        
        for(int j=(a.length-1);j>=0;j--) {
            b[c[a[j]]-1]=temps[j];
            c[a[j]]-=1;
        }
        
    }
    

    /**
     * 基數排序
     * @param a 待排序數組
     * @param d 位數 如:834102 d eauals 6
     */
    public void radixSort(int[] a,int d) {
        
        //存放相應位數據的臨時數組
        int[] digitsTemp=new int[a.length];
        
        for(int j=0;j<d;j++) {
            
            //1.為相應位賦值
            for(int i=0;i<digitsTemp.length;i++) {
                digitsTemp[i]=(a[i]/tenPow(j))%10;
                System.out.println((j+1)+"位:"+"digitsTemp["+i+"] is "+ digitsTemp[i]);
            }
            
            //2.使用穩定的計數排序算法進行從低位到高位的按位排序
            countingSort4Radix(digitsTemp, a, 10);
            
            for(int x=0;x<a.length;x++) {
                System.out.println(" radixing->"+x+" is "+a[x]);
            }

        }
        
    }
    

測試代碼:

    public static void main(String[] args) {

        int[] x= {834102,634101,834112,512311};
        new RadixSort().radixSort(x, 6);
        
        System.out.println("-------基數排序的結果-------");

        for(int i=0;i<x.length;i++) {
            System.out.println(i+" is "+x[i]);
        }
    }

測試結果:

1位:digitsTemp[0] is 2
1位:digitsTemp[1] is 1
1位:digitsTemp[2] is 2
1位:digitsTemp[3] is 1
 radixing->0 is 634101
 radixing->1 is 512311
 radixing->2 is 834102
 radixing->3 is 834112
2位:digitsTemp[0] is 0
2位:digitsTemp[1] is 1
2位:digitsTemp[2] is 0
2位:digitsTemp[3] is 1
 radixing->0 is 634101
 radixing->1 is 834102
 radixing->2 is 512311
 radixing->3 is 834112
3位:digitsTemp[0] is 1
3位:digitsTemp[1] is 1
3位:digitsTemp[2] is 3
3位:digitsTemp[3] is 1
 radixing->0 is 634101
 radixing->1 is 834102
 radixing->2 is 834112
 radixing->3 is 512311
4位:digitsTemp[0] is 4
4位:digitsTemp[1] is 4
4位:digitsTemp[2] is 4
4位:digitsTemp[3] is 2
 radixing->0 is 512311
 radixing->1 is 634101
 radixing->2 is 834102
 radixing->3 is 834112
5位:digitsTemp[0] is 1
5位:digitsTemp[1] is 3
5位:digitsTemp[2] is 3
5位:digitsTemp[3] is 3
 radixing->0 is 512311
 radixing->1 is 634101
 radixing->2 is 834102
 radixing->3 is 834112
6位:digitsTemp[0] is 5
6位:digitsTemp[1] is 6
6位:digitsTemp[2] is 8
6位:digitsTemp[3] is 8
 radixing->0 is 512311
 radixing->1 is 634101
 radixing->2 is 834102
 radixing->3 is 834112

-------基數排序的結果-------
0 is 512311
1 is 634101
2 is 834102
3 is 834112

總結

  1. 計數排序 適用于k比較小的場景下,比如“某大型企業有兩萬名員工,希望根據年齡為員工們排序,并計算平均年齡?”,這個問題在不使用數據庫和磁盤相關算法(B樹)的前提下,計數排序是較優的解決方案。
  2. 基數排序是一種原地排序算法,不需要額外的空間進行輔助;但是我的代碼中計數排序是還是開辟了空間,這是一個值得優化的點。

以上,謝謝閱讀,希望你有所收獲!

算法導論公開課筆記(一)算法分析與設計
算法導論公開課筆記(二)快速排序和隨機化算法
算法導論公開課筆記(三)線性時間排序
算法導論公開課筆記(四)順序統計、中值
動態規劃算法

竟然有人,為這個文章贊賞了¥2.0,雖然寫博客的目的不是為了掙錢,但是也好開心!!!
謝謝匿名的大神的鼓勵,事事順利!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • 長外套首先就是給人一種走路帶風的感覺,其次就是遮肉顯瘦。 左邊是Gigi穿高跟鞋的搭配,右邊是肯豆穿平底鞋的搭配,...
    f2c1b5300161閱讀 255評論 0 0