作者: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的更多相关文章

  1. 快速排序算法 quick sort的理解

    最近做了一下算法的一些练习,感觉基础薄弱了,只是用一些已经有的东西来完成练习如quickSort(c++使用的时候是sort(起始位置,终止位置,比较函数),这个需要加头文件),但是不知道怎么推出来, ...

  2. [算法]——快速排序(Quick Sort)

    顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...

  3. 排序算法—快速排序(Quick Sort)

    快速排序(Quick Sort) 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. ...

  4. 【算法】快速排序(Quick Sort)(六)

    快速排序(Quick Sort) 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. ...

  5. 快速排序(Quick Sort)的C语言实现

    快速排序(Quick Sort)的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序,具体步骤 ...

  6. 交换排序—快速排序(Quick Sort)原理以及Java实现

    交换排序—快速排序(Quick Sort) 基本思想: 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素 ...

  7. 快速排序(Quick Sort)

    快速排序是初学者比较难理解的几个算法之一,这里尽可简单化地讲解,希望能帮到大家. 快速排序基本步骤: 从数列中挑出一个元素,称为"基准"(pivot). 重新排序数列,所有元素比基 ...

  8. 算法 quick sort

    // ------------------------------------------------------------------------------------------------- ...

  9. 快速排序(Quick Sort)及优化

    原理介绍 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成 ...

随机推荐

  1. AS问题解决系列1—Unable to execute DX错误

    http://my.oschina.net/1pei/blog/478968 摘要 在将一个开源Android代码import到Android Studio 1.2.2中时,解决了编译期间出现的“Un ...

  2. 理解CRC校验

    举个最简单的例子,A向B发送一个数字,B如何检测数字在传输过程中有没有发生错误呢? A和B之间,定下一个协议,两边都知道一个除数X,A向B发送数字的时候,同时把余数附带后面发过去.比如,两边定的除数是 ...

  3. Codeforces Round #320 (Div. 1) [Bayan Thanks-Round] C. Weakness and Poorness 三分 dp

    C. Weakness and Poorness Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  4. 第二周:01 ICP迭代交互

    本周主要任务01:利用PCL库函数,ICP融合两个角度的点云 任务时间:2014年9月8日-2014年9月14日 任务完成情况:可以使用键盘交互,显示每次ICP迭代结果 任务涉及基本方法: 1.PCL ...

  5. MST最小生成树及克鲁斯卡尔(Kruskal)算法

    最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧.假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树.最小生成树是对边上权重的考虑, ...

  6. 06---Java基础、面向对象

    一.Java基础 1.Java概述 Java语言特点:                     简单性.解释性.面向对象.高性能.分布式处理                     多线程.健壮性.动 ...

  7. android128 zhihuibeijing 科大讯飞 语音识别

    - 科大讯飞 开放平台 http://open.voicecloud.cn/ package com.itheima.voicedemo; import android.app.Activity; i ...

  8. IDispatch接口介绍

    1.         C程序调用时,调用者必须预先知道接口规范(如,参数类型.参数字节长度.参数顺序等).由于不同语言这些规范有所不同,COM未解决不同语言之间调用,提供了IDispatch接口. 2 ...

  9. [001]socket通信--server和client实现迭代的简单例子

    server端: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unist ...

  10. 包括后台的Android美食APP项目开源代码

    项目简介 小食光定位为一款集美食,社交,LBS服务于一体的美食推荐APP.为你发现周边美食的同时提供一个吃货分享的平台. APP截图     功能模块 美食推荐 :提供基础的美食信息查询: 商家推荐  ...