1. 程式人生 > >【面試排序練習】——隨筆記錄(一)

【面試排序練習】——隨筆記錄(一)

筆者之前的部落格提到過七種經典排序演算法,他們分別是:

  • 時間複雜度為:O(n²)的演算法:氣泡排序,選擇排序,插入排序
  • 時間複雜度為:O(n*㏒n)的演算法:歸併排序,快速排序,堆排序,希爾排序

那麼本篇的內容將要介紹兩種時間複雜度為O(n)的排序演算法,分別是:計數排序基數排序

這兩種演算法不是基於比較的的排序演算法,主要思想原形是基於桶排序,所謂的桶排序不是一種具體的實現而是一種思想。

一、計數排序

原理及思路:

例如現在需要將員工的身高進行從低到高排序,我們已知成年人的身高在100cm到300cm之間,這個時候我們可以設定100號到300號這200個桶,然後將員工根據身高的大小放入每一個桶中,然後依次到處100號到300號中的員工,這樣最後的結果就有序了。

程式碼舉例:

import java.util.*;

public class CountingSort {
    public int[] countingSort(int[] A, int n) {
        // write code here
        //如果陣列為空,則無需排序
        if(A == null || n<1){
            return A;
        }
        //否則
        //首先我們需要設定一些桶,這裡桶的數量我用 陣列中的最大數減最小數決定
        //所以首先我們要取到陣列中的最大數和最小數
        //宣告兩個變量表示
        int max = A[0];
        int min = A[0];
        //遍歷陣列,找出最大最小值
        for(int i=0;i<n;i++){
            if(max < A[i]){
                max = A[i];
            }
            if(min > A[i]){
                min = A[i];
            }
        }
        //根據最大最小值建立一個數組表示桶
        int temp[] = new int[max-min+1];
        //遍歷陣列將陣列中的值放入桶中,同時桶陣列記錄數量,這時用桶陣列的下標表示目標陣列和最小值的差別,桶陣列中存放數量
        for(int i=0;i<n;i++){
            temp[A[i]-min] += 1;
        }
        //存放完成後將桶中數字依次倒出,
        int index = 0; //表示下標
        for(int i=0;i<max-min+1;i++){
            while(temp[i] > 0){
                //從桶中取出一個樹
                A[index++] = i + min;
                //桶中數量減一
                temp[i]--;
            }
        }
        return A;
    }

}

二、基數排序

原理及思路:

還是例如將公司員工的身高進行從低到高排序,我們已知身高用十進位制表示,那麼我們可以建立0號到9號一共十個桶,第一步現將所有元素的各位與桶編號對比,並將其放入對應的桶中,然後從0號到9號依次倒出;第二步,根據倒出來以後的順序依次將十位數和桶編號比較,然後放入對應的桶中,再依次將桶中的元素倒出來;第三步,將百位數做和前面兩次一樣的操作,最後依次倒出桶中的元素,那麼最後的陣列就是排序後的結果。

程式碼舉例:

import java.util.*;

public class RadixSort {
    public int[] radixSort(int[] A, int n) {
        // write code here
        if(A == null || n<1){
            return A;
        }
        //首先我們需要建立十個桶,每個桶中存放最多n個數
        int[][] temp = new int[10][n];
        //記錄存放的資料數
        int[] count = new int[10];
        //定義變量表示身高區間
        int i = 1;
        while(i<1000){
            //遍歷陣列
            for(int j=0;j<n;j++){
                //求計算的位數,這裡i是會變的
                int pos = A[j]/i%10;
                //將元素放入對應的桶
                temp[pos][count[pos]++] = A[j];
            }
            //設定引數表示下標
            int index = 0;
            //接下來要將桶中的元素倒出來,依次根據一維座標和二維座標取出
            for(int k=0;k<10;k++){
                for(int m=0;m<count[k];m++){
                    A[index++] = temp[k][m];
                }
                //全部取出後將計數陣列置為0
                count[k] = 0;
            }
            //提高位數
            i*=10;
        }
        return A;
    }
}

經典排序總結

經典排序演算法空間複雜度

1、O(1)

時間複雜度為O(n²):氣泡排序、插入排序、選擇排序

時間複雜度為O(n*㏒n):堆排序,希爾排序

2、O(㏒n)~O(n)

快速排序,這個區間具體的值取決於被排列的陣列的分佈情況的好壞

3、O(n)

歸併排序

4、O(m)

計數排序,基數排序。這裡的m指的是桶的大小

經典排序演算法的穩定性

1、不穩定的演算法

希爾排序,堆排序,選擇排序,快速排序

2、穩定的演算法

氣泡排序,插入排序,歸併排序,計數排序,基數排序,桶排序