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

第二章 初级排序算法

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