面试-----快速排序看这一篇就够了
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
- 快排的思想是分治
- 我们有一个待排序的数组,长度为n。选定一个基准,将数组分成左右两部分,左边的数小于基准,右边的数大于基准。
- 然后我们分别看分割后左右两部分数组,如果元素个数大于1,就再次分割。
- 直到最后,我们得到了n个数组,每个数组含有1个元素。
- 这n个数组中,每两个挨着的,都是排好序的,所以整体有序。
- 最好情况下,每次将原来的数组分成两份,第二次将两份成四份…最后一个元素一份。每次分割是O(n),
- 假设分割次数为k,则2的k次方等于n,k = logn。每次分割的总时间复杂度是O(n),所以说,平均复杂度是O(n*logn)。
- 最坏就是原数组有序,每次只能分割开1个元素,需要分割n次,时间复杂度是O(n^2)。
代码一:按照思路直接编写,有O(N)的额外空间。
void quick_sort(int a[], int l, int r) {
if (l >= r) return;
int x = a[l];
vector<int> left;
vector<int> right;
for (int i = l + 1; i <= r; i++) {
if (a[i] <= x)
left.push_back(a[i]);
else right.push_back(a[i]);
}
int k = l;
for (int i = 0; i < left.size(); i++) {
a[k] = left[i];
k++;
}
a[k++] = x;
for (int i = 0; i < right.size(); i++) {
a[k] = right[i];
k++;
}
quick_sort(a, l, l + left.size() - 1);
quick_sort(a, l + left.size() + 1, r);
}
代码二:改进,空间复杂度降为O(1)
void quick_sort(int a[], int l, int r) {
if (l >= r) return;
int x = a[l];
int i = l - 1, j = r + 1;
while (i < j) {
while (a[++i] < x);
while (a[--j] > x);
if (i < j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
quick_sort(a, l, j);
quick_sort(a, j + 1, r);
}
快排边界情况较多,理解后直接背过模板代码。
欢迎关注公众号,每周更新面试高频算法题。原理,代码,复杂度,优化等多方面讲解。
个人微信,欢迎交流