排序算法—基礎篇

最近在看《算法》裏面的排序算法,寫幾篇文章來記錄一下經常使用的排序算法。算法

  • 選擇排序
  • 插入排序
  • 希爾排序

選擇排序

原理

  • 首先找到數組中最小的那個元素,將它和數組中的第一個元素交換位置。 接着在剩下的元素中找到最小的元素, 將它和數組的第二個元素交換位置。如此反覆,直到將整個數組排序。

特性

  • 選擇排序的運行時間和元素的初始順序無關。
  • 選擇排序是不穩定的。(不穩定是指可能會交換相等元素的位置)

時間&空間複雜度

平均 最好 最壞 空間 穩定性
O(n^2) O(n^2) O(n^2) O(1) 不穩定

代碼實現

public class SelectSort {

    public static void sort(int[] a) {

        for (int i = 0; i < a.length; i++) {
            //首先把min指向第i個元素
            int min = i;
            //每次循環從未排序數字中找出最小數的索引,並賦值給min
            for (int j = i + 1; j < a.length; j++) {
                if (a[j] < a[min]) {
                    min = j;
                }
            }
            //交換a[i]和a[min]
            int t = a[i];
            a[i] = a[min];
            a[min] = t;
        }
    }

插入排序

原理

  • 有點相似於咱們打撲克摸牌的過程,每摸一張牌,咱們便經過對比手上已有的牌,將剛拿到的 牌放入合適的位置。

特性

  • 和選擇排序不一樣的是,插入排序所需的時間取決於輸入元素的初始順序。
  • 插入排序適用於部分有序或者已經有序的元素。

時間&空間複雜度

平均 最好 最壞 空間 穩定性
O(n^2) O(n) O(n^2) O(1) 穩定

代碼實現

public class InsertSort {

        public static void sort(int[] a) {
            //將初始i設置爲1
            for (int i = 1; i < a.length; i++) {
                for (int j = i; j > 0 && a[j] < a[j - 1]; j--) {
                    //交換a[j]和a[j-1]
                    int t = a[j];
                    a[j] = a[j - 1];
                    a[j - 1] = t;
                }
            }
        }

希爾排序

定義

  • 希爾排序爲了加快速度簡單地改進了插入排序,基本思想是使數組中任意間隔爲h的元素都是有序的

原理

設待排序序列共n個元素,首先取一個整數gap<n做爲間隔,將所有元素分爲間隔爲gap的gap個子序列並對每個子序列進行直接插入排序。而後,縮小間隔gap,重複上述操做,直至gap縮小爲1,此時全部元素位於同一個序列且有序。
因爲剛開始時,gap較大,每一個子序列元素較少,排序速度較快;待到排序後期,gap變小,每一個子序列元素較多,但大部分元素基本有序,因此排序速度仍較快。數組

clipboard.png

時間複雜度

希爾排序的時間複雜度分析及其複雜,有的增量序列的複雜度至今還沒人可以證實出來,只須要記住結論就行,{1,2,4,8,...}這種序列並非很好的增量序列,使用這個增量序列的時間複雜度(最壞情形)是O(n²),Hibbard提出了另外一個增量序列{1,3,7,...,2^k-1},這種序列的時間複雜度(最壞情形)爲O(n^1.5),Sedgewick提出了幾種增量序列,其最壞情形運行時間爲O(n^1.3),其中最好的一個序列是{1,5,19,41,109,...},須要一個臨時變量用來交換數組內數據位置,因此空間複雜度爲O(1)。spa

代碼實現

public class ShellSort {

    public static void sort(int[] a){
        
        int N=a.length;
        int h=1;
        while (h<N/3) {
            h=h*3+1;//1,4,13,40,121,......
        }
        while (h>=1) {
            for (int i = h; i <N; i++) {
                for (int j = i; j >=h && a[j]<a[j-h]; j-=h) {
                    //交換a[j]和a[j-h]
                    int t=a[j];
                    a[j]=a[j-h];
                    a[j-h]=t;
                }
            }
            h=h/3;
        }        
    }
}
相關文章
相關標籤/搜索