• 《算法导论》第7章 快速排序 (四种变形)



    这一章的正文及思考题部分讲到了快速排序及其几种变形,包括:Hoare快排,
    普通快排,随机快排,三数取中快排。

    这些快排的区别主要是划分方法PARTITION算法的不同:如何选取主元,划分出的
    两部分范围是什么。根据划分出的范围不同,各变形的QUICKSORT有微小的差别。


    1. Hoare快排

    Hoare划分是最初的版本,与《算法导论》中的划分版本相比,它选取第一个元素A[p]为主元。
    划分后的两部分是:A[p..j]和A[j+1..r],主元可能放入某一个之中。

    int hoare_partition(int A[], int p, int r)
    {
         int x = A[p];
         int i = p - 1;
         int j = r + 1;
    
         while (1) {
    
              do j--;
              while (A[j] > x);
    
              do i++;
              while (A[i] < x);
    
              if (i < j)
                   swap(A, i, j);
              else
                   return j;
         }
    }
    
    void hoare_quick_sort(int A[], int p, int r)
    {
         if (p < r) {
              int q = hoare_partition(A, p, r);
              hoare_quick_sort(A, p, q);
              hoare_quick_sort(A, q + 1, r);
         }
    }
    


    2. 普通快排

    选取最后一个元素A[r]为主元后,j 从头遍历到尾,i 是两范围的分隔。
    划分结果为[p, q - 1]和[q + 1, r]。

    int partition(int A[], int p, int r)
    {
         int x = A[r];
         int i = p - 1;
         int j;
    
         for (j = p; j <= r - 1; j++) {
              if (A[j] <= x) {
                   i++;
                   swap(A, i, j);
              }
         }
    
         swap(A, i + 1, r);
         return i + 1;
    }
    
    void quick_sort(int A[], int p, int r)
    {
         if (p < r) {
              int q = partition(A, p, r);
              quick_sort(A, p, q - 1);
              quick_sort(A, q + 1, r);
         }
    }
    


    3. 随机快排

    通过头文件stdlib.h中的rand()方法生成[p, r]之间的随机数作为主元。
    rand() % n 将生成 [0, n)之间的随机数。
    为了重用partition方法,将选定的主元交换到位置 r。

    int randomized_partition(int A[], int p, int r)
    {
         int i = p + rand() % (r - p + 1);     
         swap(A, i, r);
         return partition(A, p, r);
    }
    
    void randomized_quick_sort(int A[], int p, int r)
    {
         if (p < r) {
              int q = randomized_partition(A, p, r);
              randomized_quick_sort(A, p, q - 1);
              randomized_quick_sort(A, q + 1, r);
         }
    }
    


    4. 三数取中快排

    每次划分前,从当前子数组里随机取出三个数,取这三个数的中间数作为主元的索引。

    int median_partition(int A[], int p, int r)
    {
         int range = r - p + 1;
         int med1 = p + rand() % range;
         int med2 = p + rand() % range;
         int med3 = p + rand() % range;
         int med  = (A[med1] < A[med2]) ?
              (A[med2] < A[med3] ? med2 : (A[med1] < A[med3] ? med3 : med1)):
              (A[med1] < A[med3] ? med1 : (A[med2] < A[med3] ? med2 : med3));
    
         swap(A, med, r);
         return partition(A, p, r);
    }
    
    void median_quick_sort(int A[], int p, int r)
    {
         if (p < r) {
              int q = median_partition(A, p, r);
              median_quick_sort(A, p, q - 1);
              median_quick_sort(A, q + 1, p);
         }
    }
    
    
    //测试方法
    
    int main(void)
    {
         int A[SIZE] = { 2, 8, 7, 1, 3, 5, 6, 4 };
         print(A, SIZE);
    
         //hoare_quick_sort(A, 0, SIZE - 1);
         //quick_sort(A, 0, SIZE - 1);
         //randomized_quick_sort(A, 0, SIZE - 1);
         median_quick_sort(A, 0, SIZE - 1);
         print(A, SIZE);
    
         return 1;
    }
    














  • 相关阅读:
    javascript高级知识点——函数原型
    javascript高级知识点——临时作用域
    javascript中的部分函数应用
    javascript高级知识点——闭包
    使用HIPQTools播放视频—记录
    wpa_suppliant编译小结
    内存溢出和内存泄漏
    C代码规范
    Makefiel(一)
    Lua语言
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157861.html
Copyright © 2020-2023  润新知