• 【算法导论】学习笔记——第7章 快速排序


    对于包含n个数的输入数组来说,快速排序是一种最坏情况时间复杂度为theta(n^2)的排序算法。虽然最坏情况时间复杂度很差,但是快速排序通常是实际排序应用中最好的选择,因为它的平均性能非常好,期望时间复杂度是theta(nlgn),而且常数因子非常小,并可进行原址排序。
    1. 快速排序的描述
    快速排序可采用分治思想实现。
    分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每个元素。
    解决:通过递归调用快速排序,对数组A[p..q-1]和A[q+1..r]进行排序。
    合并:因为子数组都是原址排序的,所以不需要合并操作,A[p..r]已经有序。
    代码实现如下:

     1 void swap(int A[], int i, int j) {
     2     int tmp = A[i];
     3     A[i] = A[j];
     4     A[j] = tmp;
     5 }
     6 
     7 int Partition(int A[], int p, int r) {
     8     int x = A[r];
     9     int i = p - 1, j;
    10 
    11     for (j=p; j<r; ++j) {
    12         if (A[j] <= x) {
    13             ++i;
    14             swap(A, i, j);
    15         }
    16     }
    17     swap(A, i+1, r);
    18     return i+1;
    19 }
    20 
    21 void QuickSort(int A[], int p, int r) {
    22     int q;
    23 
    24     if (p < r) {
    25         q = Partition(A, p, r);
    26         QuickSort(A, p, q-1);
    27         QuickSort(A, q+1, r);
    28     }
    29 }

    Partition过程总是选择一个x=A[r]作为主元(Pivot Element),并围绕该元素花费子数组A[p..r]。显然,Partition的时间复杂度为theta(n),n = r-p+1。

    2. 快速排序的性能
    最坏情况下,划分极不均匀,即划分为n-1与0,则T(n) = T(0) + T(n-1) + theta(n),复杂度为theta(n^2);最好情况下,划分足够均匀,即花费为floor(n/2)与ceil(n/2)-1,则T(n) = 2T(n/2) + theta(n),复杂度为theta(nlgn)。通常,在划分比例为常数比例的情况下,复杂度均为theta(nlgn)。
    证明:最坏情况下快速排序复杂度为theta(n^2)。
      T(n) = max(T(q)+T(n-q-1)) + theta(n),0<=q<=n-1,采用数学归纳法
        <= max(c*q^2+c*(n-q-1)^2) + theta(n),0<=q<=n-1
        = c*max(q^2+(n-q-1)^2) + theta(n)
        <= c*n^2 - c*(2n-1) + theta(n).
      只要c*(2n-1)显著大于theta(n),结论即成立。
    7.2.5 证明:以划分比例1-a:a作递归树,因为0<a<=1/2,所以1-a>=a,设高度为h,所以当叶结点深度最小(即高度最小)满足(a^h)n = 1,解得h = -lgn/lga,同理,当叶结点深度最大(即高度最高)时,满足((1-a)^h) = 1,解得
    h = -lgn/lg(1-a)。注意,在第k层划分后的数量一定为(a^x)*((1-a)(k-x))*,易知,划分后的最大数量比例为(1-a)^k,最小数量比例a^k。分别令将这两个比例*n为1,即可求解。

    3. 快速排序的随机化版本
    即采用随机抽样的随机化技术使得主元素随机选取,在等概率随机选取的情况下,期望运行时间为O(nlgn)。
    代码如下:

     1 void swap(int A[], int i, int j) {
     2     int tmp = A[i];
     3     A[i] = A[j];
     4     A[j] = tmp;
     5 }
     6 
     7 int Partition(int A[], int p, int r) {
     8     int x = A[r];
     9     int i = p - 1, j;
    10 
    11     for (j=p; j<r; ++j) {
    12         if (A[j] <= x) {
    13             ++i;
    14             swap(A, i, j);
    15         }
    16     }
    17     swap(A, i+1, r);
    18     return i+1;
    19 }
    20 
    21 int Randomized_Partition(int A[], int p, int r) {
    22     int n = r-p+1;
    23     int i = p+rand()%n, tmp;
    24 
    25     tmp = A[r];
    26     A[r] = A[i];
    27     A[i] = tmp;
    28     return Partition(A, p, r);
    29 }
    30 
    31 void QuickSort(int A[], int p, int r) {
    32     int q;
    33 
    34     if (p < r) {
    35         q = Randomized_Partition(A, p, r);
    36         QuickSort(A, p, q-1);
    37         QuickSort(A, q+1, r);
    38     }
    39 }
  • 相关阅读:
    unity, sceneview 中拾取球体gizmos
    C#, float.ToString()的一个坑
    unity, SerializedObject.FindProperty不要写在Editor的OnEnable里,要写在OnInspectorGUI里
    unity, 查看.anim中的动画曲线(和帧)
    unity, Graphics.Blit (null, null, mat,0);
    unity, GL.TexCoord or GL.Color must put before GL.Vertex!!!
    (MyEclipse) MyEclipse完美破解方法(图)
    博客园kubrick主题
    sina微博加入到博客园
    MyEclipse 2014 破解图文详细教程
  • 原文地址:https://www.cnblogs.com/bombe1013/p/3932483.html
Copyright © 2020-2023  润新知