快速排序及三向切分快速排序


author: i.sshe
email: [email protected]
github: https://github.com/isshe


1.快速排序

  是一種分治的排序算法。切分元素的選擇關係到算法的性能,因此在排序前,應先把數據打亂。

2.快速排序的過程:

  1). 選擇切分元素(一般選擇切分區域第一個位置 k )。
  2). i 指向第二個元素(第一個 k ),j指向最後一個元素。
  3). i 向右移動,遇到大於等於切分元素 k 的元素時,停下。
  4). j 向左移動,遇到小於等於 k 的元素時,停下。
  5). 如果i < j,交換 i 和 j 兩個位置的值。
  6). 循環2-5過程,直到 i >= j.
  7). 交換 k 位置和 i/j 位置的值。(i和j的選擇,和先從左開始掃描 或 先從右開始掃描有關係)

3.1 概觀:

這裏寫圖片描述

3.2 排序過程示意圖:

這裏寫圖片描述

3.3 代碼:

//這份代碼是先從左邊開始掃描
void quick_sort(int *array, int left, int right)
{
     int    i = 0;
     int    j = 0;
     int    select = 0;
     int    temp = 0;

     if (left >= right)
     {
         return;
     }

     i = left;      //or left+1
     j = right;
     select = array[left];

     while(1)
     {
         while(array[i] <= select)
         {
              i++;
              if (i == right) break;
         }
         while(array[j] >= select)
         {
             j--;
             if (j == left) break;
         }

         if (i >= j)
         {
              break;
         }

         temp = array[i];
         array[i] = array[j];
         array[j] = temp;
     }

     temp = array[j];
     array[j] = array[left];
     array[left] = temp;

     quick_sort(array, left, j-1);
     quick_sort(array, j+1, right);
}

4. 需要注意的細節:

  1). 原地切分:不要使用輔助數組,【更不要在遞歸的切分方法中創建空數組(不是很理解)】。
  2). 別越界: 主要是切分元素是最大或最小的情況.
  3). 保持隨機性: 在排序前把數據打亂.
  4). 終止循環: 同時注意越界問題.
  5). 有元素和切分元素相同的情況: 左掃描時,>=; 右掃描時,<=;(等於是關鍵)
  6). 終止遞歸: 常見錯誤是沒有把切分元素放在正確位置.

5. 快速排序優點:

  1). 內循環簡潔;
  2). 比較的次數少.

6.算法改進:

  1). 切換到插入排序.(if (hi <= lo + M) {InsertSort(); return }), 這裏的M一般取5~15, 最佳值和系統有關.
  2). 三取樣切分: 選擇數組中一小部分元素的中位數來切分數組.(一小部分一般取3!)[代價是需要計算中位數]
  3). 熵最優的排序: 實際應用中,一般都有大量重複元素, 這時候採用三向切分能提高性能.
  4). 三向切分: 把數據分三部分,左邊小於切分元素,中間等於,右邊大於. (lt標記小於部分,i標記等於,gt標記大於)

7. 三向切分

三向切分概觀:
  這裏寫圖片描述
三向切分排序過程示意圖:
  這裏寫圖片描述
三向切分代碼:

void quick_sort3way(int *array, int left, int right)
{
    int lt = 0;
    int i = 0;
    int gt = 0;
    int v = 0;

    if (left >= right)
    {
         return ;
    }

    v = array[left];        //選擇的元素
    lt = left;
    i = left + 1;
    gt = right;

    while (i <= gt)
    {
         if (array[i] < v)
         {
             exchange(array, lt, i);
             lt++;
             i++;
         }
         else if (array[i] > v)  //注意這裏,i不用++
         {
              exchange(array, i, gt);
              gt--;
//              i++;
         }
         else
         {
              i++;
         }
    }

    quick_sort3way(array, left, lt - 1);
    quick_sort3way(array, gt + 1, right);
}

參考資料:

  1. <<算法 第四版>>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章