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);
}
參考資料:
- <<算法 第四版>>