快速排序使用分而治之(divided and conpuer 即D&C)的策略。
快速排序的平均时间复杂度为O(nlogn),最差情形时间复杂度O(n2),额外空间为O(logn),是一个不稳定的算法。
快速排序是由冒泡排序改进而得的,它的基本思想是:在待排序的 n 个元素中任取一个元素(通常取第一个元素)作为基准,把该uansu放入适当的位置后 ,数据序列被次元素划分成两部分,所有关键字比该元素关键字小的元素放置在前一部分,所有关键字比该关键字元素大的元素放置在后一部分,并把该元素排在这两部分的中间(称该元素归位),这个过程称作一趟快速排序。之后对所有划分出来的两部分分别重复上述过程,直至每部分内只有一个元素或为空为止。
简而言之,每趟将表的第一个元素放入适当位置,将表一分为二,对子表按递归方式继续这种划分,直至划分的子表长为1或0。
一趟快速排序的划分过程是采用从两头向中间扫描的办法,同时交换与基准元素逆序的元素。
举个例子
设待排序的表有10个元素,其关键字为72,6,57,88,60,42,83,73,48,85,用快速排序方法进行排序的过程如下
第一次排序:
基准为6,左指针left指向基准后一个元素8,右指针right指向最后一个元素5
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
基准 空 | 左指针left | 右指针 right |
72作为基准,即其他所有数据都和它做比较,小于它的放置在前半部分,大于它的放置在后半部分。此刻已经被取出,即代表72的存储空间可以填入其他数字。有些类似于“挖坑填数”。
基准72暂时取出,在排序过程中不会出现,只作为基准比较,只有最后一步的时候才将其插入进正确的位置。
由于右指针right为85>基准72,满足条件,所以right-1。
right-1后指向数据为48<基准72,所以需要改变数字的位置。right指针不变,等待下一个数字来填补这一个空位之后才能改变
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
48 | |||||||||
left | right 空 |
|
然后right指针保持不同,转而执行left指针。
由于left指针所指数据6<基准72,满足条件,所以left+1
left+1所指向数据57<基准72,满足条件,left+1
left+1所指向数据88>基准72,不满足条件,则改变位置。left指针不变,等待下一个数字来填补这个空位之后才能改变
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
88 | |||||||||
| left 空 | right |
right数据73>72,满足条件,right-1
right-1所指向数据83>72,满足条件,right-1
right-1所指向数据42<72,不满足条件,改变位置。right指针不变,等待下一个数字来填补这一个空位之后才能改变
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 88 | 85 |
42 | |||||||||
left | right 空 |
|
left数据60<72,满足条件,left+1
left+1后与right指针相等,停止程序,将基准72插入剩下的那个空位之中
48 | 6 | 57 | 42 | 60 | 42 | 83 | 73 | 88 | 85 |
72 | |||||||||
| right 空 |
整理可得
48 | 6 | 57 | 42 | 60 | 72 | 83 | 73 | 88 | 85 |
满足条件,前半部分都是比基准小的,后半部分都是比基准大的
然后再分别对绿色区域,和蓝色区域的数据进行快速排序,直至子表长为1或0停止,就使得有序了
第二次排序:
42 | 6 | 48 | 57 | 60 | 72 | 73 | 83 | 88 | 85 |
第三次排序:
6 | 42 | 48 | 57 | 60 | 72 | 73 | 83 | 85 | 88 |
#include<stdio.h>
#include<iostream>
using namespace std;
void quickSort(int *a,int s,int t){
int l=s,r=t; //左指针,右指针
int x; //基准
if(s<t){ //区间里至少存在两个元素的情况
x=a[l]; //区间的第一个元素作为基准
while(l!=r){ //从区间两端交替向中间扫描,直至l>=r为止
while(r>l && a[r]>=x)
r--; //从右向左扫描,找到第一个小于基准的值
a[l]=a[r];//交换
while(l<r && a[l]<=x)
l++; //从左向右扫描,找到第一个大于基准的值
a[r]=a[l];//交换
}
a[l]=x;
/*
注意这里用的是s,t,因为l和r在排序过程中其值改变,
并没有指向整个列表的第一个元素和最后一个元素
*/
quickSort(a,s,l-1);//对左区间递归排序
quickSort(a,l+1,t);//对右区间递归排序
}
}
int main(){
int n;
cout<<"输入要排序的数字个数:";
cin>>n;
int *a=new int(n);
//初始化
cout<<"输入要排序的数字:";
for(int i=0;i<n;i++){
cin>>a[i];
}
//调用快速排序
quickSort(a,0,n-1);
//显示排序后的数组
cout<<"排序后:";
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}