优缺点:
- 速度快,但是稳定性差
- 空间复杂度:
- 最优:O(logn)
- 最差:O(n)
- 时间复杂度:
- 最好:O(nlogn)
- 最差:O(n^2)
- 平均:O(nlogn)
排序步骤
(从小到大排序)
- 首先选择一个基准作为分界值,通过该分界值分成左右两部分
- 如果必分界值小,就放在分界值右边,如果必分界值大就放在分界值左边
- 分界值左边作为子序列,重复上面步骤,分界值右边为子序列,重复上面步骤。若子序列长度为1,便结束排列。
代码逻辑例子:
通常选择序列第一位做为基准,并设置左右指针,移动左右指针直至两指针相遇
原序列:[ 6 1 2 7 9 3 4 5 10 8 ]
设置 i = 0(左指针), j = 9 (右指针) , 分解值为6
- 移动右指针 j 直至发现小于基准值6的数(5),停止移动
- 移动左指针 i 直至发现大于基准数6的数(7),停止移动
- 交换两个指针的数,获得新的序列,[ 6 1 2 5 9 3 4 7 10 8 ]
- 继续移动右指针 j,直至发现小于基准值6的数(4)
- 继续移动左指针 i,直至发现小于基准值6的数(9)
- 交换两个指针的数,获得新的序列,[ 6 1 2 5 4 3 9 7 10 8 ]
- 继续移动右指针 j ,直至发现小于基准值6的数(3)
- 继续移动左值针 i , 移动至 j 的位置,两指针相遇,停止移动
- 基准数与两指针所指向的位置交换,得到[ 3 1 2 5 4 6 9 7 10 8 ]
- 递归左右子序列
注意:若选择最左数作为基数,那么先移动右指针。若选择最右数作为基数,那么先移动左指针。
具体原因不好解释,可以自行尝试一步一步交换。
源码
#include<iostream>
#include<stdlib.h>
#include<time.h>
#define LEN 10
using namespace std;
void quickSort(int *Arr,int left,int right){
if(left>=right)
return;
int i,j,base;
i = left;
j = right;
base = Arr[left];
while( i < j){
//基数为left,先移动右指针
while( Arr[j] >= base && i < j )
j--;
while( Arr[i] <= base && i < j )
i++;
//交换
if( i < j ){
int t = Arr[i];
Arr[i] = Arr[j];
Arr[j] = t;
}
}
Arr[left] = Arr[i];
Arr[i] = base;
quickSort(Arr,i+1,right);
quickSort(Arr,left,i-1);
}
int main(){
srand(time(NULL));
int Arr[LEN];
cout<<"before:"<<endl;
for(int i=0;i<LEN;i++){
Arr[i] = rand()%98+1;
cout<<Arr[i]<<" ";
}
quickSort(Arr,0,LEN-1);
cout<<endl<<"after:"<<endl;
for(int i=0;i<LEN;i++){
cout<<Arr[i]<<" ";
}
cout<<endl;
return 0;
}
结果
before:
87 77 78 89 60 15 85 29 66 85
after:
15 29 60 66 77 78 85 85 87 89