快速排序可能是面试中最常被考察的算法了,求职者一定要非常熟练地掌握掌握这一算法。
下面介绍该算法的两种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。