快速排序(面试版)
快速排序是由冒泡排序改进而得的。在冒泡排序中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。而快速排序可以通过两个不相邻记录的一次交换,来消除多个逆序,会大大加快排序的速度。
快速排序基本思想:
1、先从数列中取出一个数作为基准数。
2、分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3、再对左右区间(重新选择中心元素)重复第二步,直到各区间只有一个数。
快速排序基本步骤
举例
代码实现
int Partition(SqList &L,int low,int high)
{//对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置
L.r[0] = L.r[low]; //用子表的第一个记录做枢轴记录
pivotkey = L.r[low].key;//枢轴记录关键字保存在pivotkey中
while(low<high) //从表两端交替地向中间扫描
{
while(low<high && L.r[high].key>=pivotkey) --high;
L.r[low] = L.r[high]; //将比枢轴记录小的记录移到低端
while(low<high && L.r[low].key<=pivotkey) ++low;
L.r[high] = L.r[low]; //将比枢轴记录大的记录移到高端
}
L.r[low] = L.r[0];//将枢轴记录放到此时low=high的位置 ,也可以写成 L.r[high] = L.r[0];
return low; // return high也可以
}
void QSort(SqList &L,int low,int high)
{//调用前置初值:low=1;high=L.length;
//对顺序表L中的子序列L.r[low..high]快速排序
if(low<high) //长度大于一
{
pivotloc = Partition(L,low,high);
//将L.r[low..high]一分为二,pivotloc为枢轴元素
Qsort(L,low,pivotloc-1);//对左子表递归排序
Qsort(L,pivotloc+1,high);//对右子表递归排序
}
}
void QuickSort(SqList &L)
{
QSort(L,1,L.length); //对顺序表L的1~L.length(所有的元素)个元素进行排序
}
算法分析
(1)时间复杂度
从快速排序算法的递归树可知,快速排序的趟数取决于递归树的深度。平均情况下,快速排序的时间复杂度是O(nolg2n).
(2)空间复杂度
最好情况下的空间复杂度是O(log2n)
最坏情况下为O(n)
算法特点
- 记录非顺次的移动导致排序方法是不稳定的
- 排序过程需要定位表的下界和上界,所以适合用于顺序结构,很难用于链式结构
- 当n较大时,在平均情况下快速排序是所有内部排序方法中速度最快的一种,所以其适合初始记录无序、n较大时的情况
快速排序 C++sort函数
1 sort 函数头文件
#include<algorithm>
2 Sort函数有三个参数:
sort(begin,end,cmp)
(1)第一个是要排序的数组的起始地址。(begin)
(2)第二个是结束的地址(最后一位要排序的地址的下一地址,对于一个vector来说是a.end())(end)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。(cmp)
3 cmp参数不写默认升序
cmp 函数中return a<b 默认降序
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a<b; //降序
}
int main()
{
int a[n];
sort(a,a+n);
....
return 0;
}
cmp函数中return a>b 默认升序
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b; //升序
}
int main()
{
int a[n];
sort(a,a+n);
....
return 0;
}
4. 其实排序完全可以不用自己写cmp函数就可以实现排序
升序:sort(begin,end,less());
降序:sort(begin,end,greater());
5. 利用sort函数对数组排序
#include<iostream>
#include<algorithm> //调用sort函数
using namespace std;
bool com(int a, int b)
{
return a > b;//从大到小排序
}
int main(){
int a[10] = {9,6,3,8,5,2,7,4,1,0};
for(int i = 0; i < 10; i++)
sort(a, a+10, cmp); //在这里就不需要对cmp函数传入参数了,这是规则
for(int i = 0; i < 10; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}
6 利用sort 对字符排序
使用迭代器
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
string a="hello world";
sort(a.begin(),a.end());
cout<<a; //运行结果 空格dehllloorw
return 0;
}
7 利用sort 对字符串排序
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
string a[5];
for(int i=0;i<5;i++)
cin>>a[i];
sort(a,a+5);
cout<<endl;
for(int i=0;i<5;i++)
cout<<a[i]<<endl;
return 0;
}
8 利用sort对结构体排序
例题 生日
题目描述:
cjf君想调查学校OI组每个同学的生日,并按照从大到小的顺序排序。但cjf君最近作业很多,没有时间,所以请你帮她排序。
输入格式
有2行,
第1行为OI组总人数n;
第2行至第n+1行分别是每人的姓名s、出生年y、月m、日d。
输出格式
有n行,即n个生日从大到小同学的姓名。(如果有两个同学生日相同,输入靠后的同学先输出)
输入样例:
3
Yangchu 1992 4 23
Qiujingya 1993 10 13
Luowen 1991 8 1
输出样例:
Luowen
Yangchu
Qiujingya
代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
string name;
int y,m,d;
int shu;
}stu[105];
bool cmp(student a,student b)
{
if(a.y!=b.y) return a.y<b.y;
if(a.m!=b.m) return a.m<b.m;
if(a.d!=b.d) return a.d<b.d;
return a.shu>b.shu;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>stu[i].name >>stu[i].y >>stu[i].m >>stu[i].d;
stu[i].shu =i;
}
sort(stu,stu+n,cmp);//对结构体排序
for(int i=0;i<n;i++) cout<<stu[i].name <<endl;
return 0;
}