您的位置:首页 > 其它

排序算法5之快速排序

2015-12-22 20:59 363 查看

快速排序

很早就听说了快速排序的大名,然后看算法导论的相关视频也感觉讲的很有意思,现在总结一下。针对待排序数组{a1,a2……an}\{{a_1,a_2……a_n}\}快速排序可以分解为三步:

寻找基准数,比较通常就是选择待排序的首项目或者中间项目;

2.根据与基准数的大小关系, 将待排序数组分成两个子序列:{b1,b2……bq−1}\{{b_1,b_2……b_{q-1}}\}和{cq+1,……cn}\{{c_{q+1},……c_n}\}。其中{b1,b2……bq−1}\{{b_1,b_2……b_{q-1}}\}均小于基准数,{cq+1,……cn}\{{c_{q+1},……c_n}\}均大于基准数,这样基准数的位置就确定了在q处。

然后利用递归对两个子序列进行排序。

下图是对步骤2的介绍,只是该图是将基准元素设置为最后一个元素,i和j的意义分别是,j作为遍历指针遍历从左往右遍历数组,i记录小于等于基准元素的位置,当j指向的元素小于等于基准元素时,就交换(i+1)和j指向的元素,同时i++。当j指向最后基准元素时,交换(i+1)和j指向元素的位置,返回i就是上面提到的q:



另外一种方法是,基准元素指向首项目,然后i和j分别指向首项目和尾项目。j先从右向左遍历,直至遇到某项目小于等于基准元素,交换i和j指向的项目大小;然后i从从左向右遍历,直至遇到某个项目大于基准元素,交换i和j指向的项目大小。当i和j相等时,停止遍历,返回i或者j就是上面提到的q。下面的code是我按照原理二写的。

#include<iostream>
using namespace std;

int quickSort(int* p,int start,int end)
{
int i=start,j=end;
int tmp=p[i];
bool flag=true;
while(i<j)
{
if(p[j]<=tmp&&flag)
{
p[i]=p[j];
flag=false;
}
if(flag)
j--;
if(p[i]>tmp&&(!flag))
{
p[j]=p[i];
flag=true;
}
if(!flag)
i++;
}
p[i]=tmp;
return i;
}
void QuickSort(int* p,int start,int end)
{

if(start<end)
{
int index=quickSort(p,start,end);
QuickSort(p,start,index-1);
QuickSort(p,index+1,end);
}
}
int main()
{
int data[10]={5,4,3,2,1,2,3,7,10,11};
QuickSort(data,0,9);
for(int i=0;i<sizeof(data)/sizeof(data[0]);i++)
cout<<"第"<<(i+1)<<"个项目:"<<data[i]<<endl;
return 0;
}


code可以进行优化:

int quickSort(int* p,int start,int end)
{
int i=start,j=end;
int tmp=p[i];
bool flag=true;
while(i<j)
{
while(i<j&&p[j]>tmp)
j--;
if(i<j)
p[i]=p[j];
while(i<j&&p[i]<=tmp)
i++;
if(i<j)
p[j]=p[i];
}
p[i]=tmp;
return i;
}


下面是按照第一种原理写出来的code,感觉比第二种确实要简单一些。

void swap(int& a,int& b)
{
int tmp;
tmp=a;
a=b;
b=tmp;
}
int quickSort(int* p,int start,int end)
{
int i=start-1,j=start;
int tmp=p[end];
for(;j<=end;j++)
if(p[j]<=tmp)
swap(p[j],p[++i]);

return i;
}


性能分析

时间复杂度:就平均性能而言,快速排序被认为是目前最好的一种内部排序,通常快排的平均时间复杂度是Ω(nlog(n))\Omega(nlog(n)),但是若待排序数组已经排序好了,或者几乎是有序的,那么快速排序将退化为冒泡排序,时间复杂度Ω(n2)\Omega(n^2)。所以这种情况一般会先随机打乱数组或者随机选择基准元素的位置。

空间复杂度:最坏情况下,若每趟排序之后,枢轴位置均偏向子序列的一端(有序),栈的最大深度为Ω(n)\Omega(n)。如果在一趟划分之后比较分割所得两部分的长度,且先对长度短的子序列中的记录进行快速排序,则栈的最大深度可降为Ω(logn)\Omega(logn)。

快速排序是不稳定排序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: