快速排序算法 Quick sort
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046189.html
首先随机选择一个轴,并调整数组内各个数字,使得比轴值大的数在轴的右边,比轴小的数在抽的左边。然后在递归的对左边和右边进行快速排序。
在调整的过程中,可以使用交替填坑的算法。
例如对于序列 4 2 3 0 1 5 第一次随机选择轴值为3。那么首先把轴值与第一个数交换。并保存数值3,得到序列:
2 4 0 1 5
p q
现在取两个指针p,q分别指向序列的第一个数和最后一个数。即p指向3,q指向5。现在p指向的数字为坑,可以被替换掉,那么另q指向第一个比轴值小且在p后面的数,即1。那么把1覆盖掉p指向的坑。并且另p++,现在序列变为:
1 2 4 0 5
p q
现在q指向的1为坑,现在另p找到第一个比轴值3大的且在q之前的数,即4。那么把4填入q指向的坑中。q--,序列变为:
1 2 0 4 5
p q
现在p指向的4为坑,把第一个比轴值3小且在p后面的数为0,那么把0填入坑中,p++,序列变为:
1 2 0 4 5
q p
现在p指向的0为坑,发现p>q,那么把轴值填入坑中,即完成了partition的过程。最终序列为:
1 2 0 4 5 轴值为3,其左侧的数都比3小,右侧的数都比3大。
然后对序列1 2 3和4 5,递归的调用快速排序算法就可以了。
代码如下,分别实现了递归和非递归的快排。
int partation(vector<int> & arr, int l, int r)
{
int p = rand() % (r - l + ) + l;
int pval = arr[p];
swap(arr[p], arr[l]);
while( l < r )
{
while( l < r && arr[r] >= pval ) r--;
arr[l] = arr[r];
while( l < r && arr[l] < pval ) l++;
arr[r] = arr[l];
}
arr[l] = pval;
return l;
} void qs_st(vector<int> & arr, int l, int r)
{
if( l >= r ) return;
stack<pair<int, int> > st;
int m = partation(arr, l, r);
if( m - > l ) st.push(make_pair(l, m - ));
if( m + < r )st.push(make_pair(m + , r));
while( !st.empty() )
{
int l = st.top().first;
int r = st.top().second;
st.pop();
int m = partation(arr, l, r);
if( m - > l ) st.push(make_pair(l, m - ));
if( m + < r ) st.push(make_pair(m + , r));
}
} void qs(vector<int> & arr, int l, int r)
{
if(l >= r) return;
int m = partation(arr, l, r);
qs(arr, l, m - );
qs(arr, m + , r);
}
quick_sort
对于快速排序算法的复杂度我们可以进行如下的计算:
对于一个长度为$n$的序列,我们定义指数函数$I(i,j)$:在快速排序算法中如果第$i$个元素和第$j$个元素比较过就为1否则为0。
那么总的比较次数$X$为:
\begin{equation} X = \sum_{i=1}^{n}\sum_{j=i+1}^{n}I(i,j) \end{equation}
我们可以得到$X$的期望为:
\begin{eqnarray} E(X) &=& E(\sum_{i=1}^{n}\sum_{j=i+1}^{n}I(i,j))\\ &=& \sum_{i=1}^{n}\sum_{j=i+1}^{n}E(I(i,j))\\ &=&\sum_{i=1}^{n}\sum_{j=i+1}^{n}P(\mbox{i is compared with j})\\ &\leq& \sum_{i=1}^{n}\sum_{j=i+1}^{n} \frac{2}{j-i+1}\\ &=&\sum_{i=1}^{n}\sum_{k=1}^{n-i} \frac{2}{k+1}\\ &<& \sum_{i=1}^{n}\sum_{k=1}^{n} \frac{2}{k+1}\\ &=& O(n\log n) \end{eqnarray}
其中第5步,i和j比较的概率,可以这么计算,不妨设i和j分别为排完序后的位置且i<j,那么如果i和j之间的数当过轴,那么i和j在后面的过程中就绝对不会在进行比较。
因此i和j比较过只有可能小于i或大于j的数当做轴,那么在下面的递归过程中,最终会形成一个由i到j组成的序列,i为序列的第一个,j为序列的最后一个,那么i和j比较过只有可能i为轴或j为轴。
其中i为轴的概率为在j-i+1个数中选择1个即1/(j-i+1),同理j被选作为轴的概率也为1/(j-i+1),即i和j被比较过的概率为2/(j-i+1)。
快速排序算法 Quick sort的更多相关文章
- 快速排序算法 quick sort的理解
最近做了一下算法的一些练习,感觉基础薄弱了,只是用一些已经有的东西来完成练习如quickSort(c++使用的时候是sort(起始位置,终止位置,比较函数),这个需要加头文件),但是不知道怎么推出来, ...
- [算法]——快速排序(Quick Sort)
顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...
- 排序算法—快速排序(Quick Sort)
快速排序(Quick Sort) 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. ...
- 【算法】快速排序(Quick Sort)(六)
快速排序(Quick Sort) 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. ...
- 快速排序(Quick Sort)的C语言实现
快速排序(Quick Sort)的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序,具体步骤 ...
- 交换排序—快速排序(Quick Sort)原理以及Java实现
交换排序—快速排序(Quick Sort) 基本思想: 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素 ...
- 快速排序(Quick Sort)
快速排序是初学者比较难理解的几个算法之一,这里尽可简单化地讲解,希望能帮到大家. 快速排序基本步骤: 从数列中挑出一个元素,称为"基准"(pivot). 重新排序数列,所有元素比基 ...
- 算法 quick sort
// ------------------------------------------------------------------------------------------------- ...
- 快速排序(Quick Sort)及优化
原理介绍 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成 ...
随机推荐
- VPN介绍--虚拟网络
VPN属于远程访问技术,简单地说就是利用公网链路架设私有网络.例如 公司员工出差到外地,他想访问企 原理 业内网的 服务器资源,这种访问就属于远程访问.怎么才能让外地员工访问到内网资源呢?VPN的 ...
- SQL Server查询所有用户表
select name from sysobjects where xtype='u' order by name
- [置顶] 【玩转cocos2d-x之七】场景类CCScene和布景类CCLayer
原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12708811 场景类CCScene和布景类CCLayer都是作为一个容器来使 ...
- [AngularJS - thoughtram] Exploring Angular 1.3: Binding to Directive Controllers
The post we have: http://www.cnblogs.com/Answer1215/p/4185504.html gives a breif introduce about bin ...
- [019]转--C++ operator关键字(重载操作符)
原博客:http://www.cnblogs.com/speedmancs/archive/2011/06/09/2076873.html operator是C++的关键字,它和运算符一起使用,表示一 ...
- java_客户端防表单重复提交和服务器端session防表单重复提交
用户输入FormServlet链接 FormServlet-〉form.jsp->DoFormServlet FormServlet:产生token,放在session中 form.jsp:hi ...
- Android4.4 + WebAPI 实现拍照上传
网上有很多关于拍照上传的实现方法,如果用新版本android去运行有可能会发现根本实现不了.主要原因是android从4.4版本开始通过intent.ACTION_GET_CONTENT打开选择器后, ...
- Android四大组件之服务-Service 原理和应用开发详解
一.Android 服务简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟Acti ...
- Android_CntextMenu_example_textSize
menu.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item ...
- logstash multiline 把文件处理为单个 event
需求 多个文本文件需要存到 ES 中去. 每一个文件存放为一个 doc. 每一个文件都是多行的,行数不定,且没有固定的内容格式. update time: Mon Jun :: CST package ...