快速排序是对冒泡排序的一种改进。
基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序。
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边,这个过程称为一趟快速排序。
值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序算法:
- 设置两个变量i,j,排序开始的时候,i=0,j=N-1;
- 以第一个数组元素作为关键数据,赋值给key,key=A[0];
- 从j开始向前搜索(
j--
),找到第一个小于key的值A[j]; - 从i开始向后搜索(
i++
),找到第一个大于key的值A[i],将A[i]和A[j]交换; - 重复第3、4步,直到i=j=k(3、4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变i,j的值,使得
j--
、i++
,直到找到为止,交换A[k]和A[0]。找到符合条件的值,进行交换的时候,i、j指针位置不变。另外,i==j
这一过程正好是i+或j-完成的时候,此时令循环结束)。
有位博主介绍的很易懂,贴个链接:
https://blog.csdn.net/qq_28584889/article/details/88136498
因此,我们可以得到下面的结论:当基准数选择最左边的数字时,那么就应该先从右边开始搜索;当基准数选择最右边的数字时,那么就应该先从左边开始搜索。不论是从小到大排序还是从大到小排序!
时间复杂度:O(nlogn)
C++实现:
#include <iostream>
using namespace std;
void quicks(int *a,int left,int right)
{
if (left>=right) {
return;
}
int i,j,base,temp;
i=left;
j=right;
base=a[left];
while (i<j) {
while (a[j]>=base&&i<j) {
j--;
}
while (a[i]<=base&&i<j) {
i++;
}
if (i<j) {
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
//基准数归位
a[left]=a[i];
a[i]=base;
quicks(a, left, i-1);//递归左边
quicks(a, i+1, right);//递归右边
}
int main(){
int a[]={6,5,4,3,2,1};
int n=sizeof(a)/sizeof(int);
quicks(a, 0, n-1);
for (int i=0; i<n; i++) {
cout<<a[i]<<" ";
}
}