算法第四版 第二章 初級排序算法

第二章 初級排序算法

1 總覽

1.1 排序算法的模板

public class Example {
  public static void sort(Comparable[] a) { /*排序代碼*/ }
  private static boolean less(Comparable v, Comparable w) { return v.compareTo(w)<0; }
  private static void exch(Comparable[] a, int i, int j) {
    Comparable t = a[i]; a[i] = a[j]; a[j] = t;
  }
  private static void show(Comparable[] a) {
    for (Comparable c : a) {
      System.out.print(c+" ");
    }
    System.out.println();
  }
  
  public static boolean isSorted(Comparable[] a) {
    for (int i=0; i<a.length-1; i++) {
      if (less(a[i], a[i+1])) {
        return false;
      }
    }
    return true;
  }
  
  public static void main(String[] args) {
    Comparable[] a = ...; //data source
    sort(a);
    assert isSorted(a);
    show(a);  
  }
}

1.2 排序算法

  • 選擇排序
  • 插入排序
  • 希爾排序
  • 歸併排序
  • 快速排序
  • 堆排序

1.3 性能指標

交換, 比較 的次數.

2 初級排序算法

2.1 選擇排序

2.1.1 原理

在數組中找到最小的元素, 然後將其與第一個元素交換位置(, 如果是本身的話就和自己交換). 然後找到剩下元素中最小的元素, 將它與第二個元素交換位置. 如此反覆, 直到排序完成.

2.1.2 實現

public class Selection {
  public static void sort(Comaprable[] a) {
    int N = a.length;
    for (int i=0; i<N; i++) {
      int minIndex = i;
      for (int j=i+1; j<N; j++) {
        if less(a[j], a[i]) {
          minIndex = j;
        }
      }
      exch(a, i, j);
    }
  }
}

2.1.3 代價分析

交換次數 比較次數
nn n22\dfrac{n^2}2

爲什麼訪問次數是 n22\dfrac{n^2}2?

對於第一個元素, 最多對比 n1n-1 次. 對於第二個元素, 最多對比 n2n-2 次, … , 對於第倒數第二個元素, 需要訪問 1 次.
(n1)+(n2)+(n3)++3+2+1=[(n1)+1](n1)2n22 (n-1)+(n-2)+(n-3)+\cdots+3+2+1 = \dfrac{[(n-1)+1]\cdot(n-1)}{2} \approx \dfrac{n^2}2

2.2 插入排序

2.2.1 原理

插入排序的原理就和整理撲克牌一樣, 當抽了一張牌以後, 需要把它插入相應的位置, 這就意味着比當前大的所有 “牌” 都需要向右移動一個位置. 插入排序所需的時間取決於輸入中元素的初始順序.

2.2.2 實現

public class Insertion {
  public static void sort(Comparable[] a) {
    //將 a 按升序排序 (小->大)
    int N = a.length;
    for (int i=0; i<N; i++) {
      //將 a[i] 插入到 a[i-1], a[i-2], ... , a[0] 中
      for (int j=i; j>0 && less(a[j], a[j-1]); j--) {
        exch(a, j, j-1);
      }
    }
  }
}

2.2.3 代價分析

交換次數 比較次數
平均 n24\dfrac{n^2}4 n24\dfrac{n^2}4
最壞 n22\dfrac{n^2}2 n22\dfrac{n^2}2
最好 00 n1n-1

最壞情況: 倒序

數組 交換次數 (當前) 比較次數 (當前)
5, 4, 3, 2, 1 - -
4, 5, 3, 2, 1 1 1
3, 4, 5, 2, 1 2 2
2, 3, 4, 5, 1 3 3
1, 2, 3, 4, 5 4 4
總計 10 10

1+2++(n2)+(n1)n22 1+2+\cdots+(n-2)+(n-1)\approx\dfrac {n^2}2

最好情況: 已經排序完成

數組 交換次數 (當前) 比較次數 (當前)
1, 2, 3, 4, 5 - -
1, 2, 3, 4, 5 0 1
1, 2, 3, 4, 5 0 1
1, 2, 3, 4, 5 0 1
1, 2, 3, 4, 5 0 1
總計 0 4

2.2.4 部分有序

2.2.4.1 定義

倒置: 數組中的兩個順序顛倒的元素.

  • E X A M P L E 中, 有 E-A, X-A, X-M, X-P, X-L, X-E, M-L, M-E, P-L, P-E, L-E 這些倒置.

部分有序: 如果數組中倒置的數量小於數組大小的某個倍數, 那麼我們說這個數組是 部分有序 的.

2.2.4.2 典型的部分有序數組
  • 數組中每個元素距離它的最終位置都不遠;
  • 一個有序的大數組接一個小數組;
  • 數組中只有幾個元素的位置不確定.
2.2.4.3 事實

插入排序對部分有序的數組很有效. 當倒置的數量很少時, 插入排序很可能比其他任何算法都要快.

2.3 希爾排序

2.3.1 原理

是基於插入排序的排序算法.

希爾排序爲了加快速度, 簡單地改進了插入排序. (交換不相鄰的元素以對數組的局部進行排序, 並最終用插入排序將局部有序的數組排序.

思想: 使數組中任意間隔 h 的元素都是有序的. 這樣的數組被稱爲 h 有序數組. (一個 h 有序數組就是 h 個互相獨立的有序數組編織在一起組成的一個數組.)

L E E A M H L E P S O L T S X
L ----- M ----- P ----- T
  E ----- H ----- S ----- S
    E ----- L ----- O ----- X

2.3.2 實現

public class Shell {
  public static void sort(Comparable[] a) {
    int N = a.length;
    int h = 1;
    while (h<N/3) { h = 3*h+1; } //?
    while (h>=1) {
      for (int i=h; i<N; i++) {
        for (int j=i; j>=h && less(a[j], a[j-h]); j-=h) {
          exch(a, j, j-h);
        }
      }
      h/=3;
    }
  }
}

2.3.3 代價分析

3 習題

3.1 題目1

寫下選擇排序是如何將數組 E A S Y Q U E S T I O N 排序的.

i Array
0 A E S Y Q U E S T I O N
1 A E S Y Q U E S T I O N
2 A E E S Y Q U S T I O N
3 A E E I S Y Q U S T O N
4 A E E I N S Y Q U S T O
5 A E E I N S Y Q U S T O
6 A E E I N S S Y Q U T O
7 A E E I N S S T Y Q U O
8 A E E I N S S T O Y Q U
9 A E E I N S S T O Q Y U
10 A E E I N S S T O Q U Y

3.2 題目2

寫下插入排序是如何將數組 E A S Y Q U E S T I O N 排序的.

i Array
0 E A S Y Q U E S T I O N
1 A E S Y Q U E S T I O N
2 A E S Y Q U E S T I O N
3 A E S Y Q U E S T I O N
4 A E Q S Y U E S T I O N
5 A E Q S U Y E S T I O N
6 A E E Q S U Y S T I O N
7 A E E Q S S U Y T I O N
8 A E E Q S S T U Y I O N
9 A E E I Q S S T U Y O N
10 A E E I O Q S S T U Y N
11 A E E I N O Q S S T U Y
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章