快速排序可能是面試中最常被考察的算法了,求職者一定要非常熟練地掌握掌握這一算法。
下面介紹該算法的兩種C++實現方法:
- 方法一:
void quickSort(vector<int> &nums, int b, int e) {
if (b < e) {
int pivot = nums[b]; //選取第一個元素爲pivot
int i = b, j = e;
while (i < j) {
while (i < j && nums[j] > pivot) {
j--;
}
if (i < j) {
nums[i++] = nums[j];
}
while (i < j && nums[i] < pivot) {
i++;
}
if (i < j) {
nums[j--] = nums[i];
}
}
nums[i] = pivot;
quickSort(nums, b, i - 1);
quickSort(nums, i + 1, e);
}
}
這種方法將partition子程序與主程序寫在一起,看起來更加簡潔。
- 方法二
int partition(vector<int> &nums, int left, int right) {
int pivot = nums[left], l = left + 1, r = right; //選取第一個元素爲pivot
while (l <= r) {
if (nums[l] > pivot && pivot > nums[r])
swap(nums[l++], nums[r--]);
if (nums[r] >= pivot)
r--;
if (nums[l] <= pivot)
l++;
}
swap(nums[r], nums[left]);
return r;
}
void quickSort2(vector<int> &nums, int b, int e) {
if (b < e) {
int index = partition(nums, b, e);
quickSort2(nums, b, index - 1);
quickSort2(nums, index + 1, e);
}
}
通常情況下,我們把partition子程序獨立出來,這樣思路更清晰。另外partition子程序在處理“第N大的數”這類問題的時候也很有幫助。
複雜性分析
當劃分比較平衡,即左右兩邊的元素個數都接近n/2的時候,通過主定理不難得出快速排序的算法複雜度爲O(nlogn)。
但如果數組本身基本有序時,如果還是選擇第一個或者最後一個元素作爲pivot,那麼每次劃分後左右兩邊就會極不平衡,時間複雜度就會退化爲O(n^2)。可考慮採用以下方法進行優化:
- 隨機選擇一個元素作爲pivot,可利用語言自帶的rand函數實現;
- 選擇第一個、最後一個、最中間一個三者中的中值作爲pivot。