《算法导论》第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;
}














原文地址:https://www.cnblogs.com/xiaomaohai/p/6157861.html