快速排序时间复杂度是O(nlogn)

快速排序思路


(整个图大概有六七分钟,完整的演示了快速排序的全部内容)

下面给出一次快速排序的思路:

排序主要思想就是twoPointers 思想(twoPointers是什么?)

①定义两个变量 i 和 j分别指向待排序数组的首尾,定义一个临时变量temp存储 i 指向的元素内容(一次排序目的就是令temp在序列中寻找一个合适的位置,使temp左侧元素都不超过temp,右侧的元素都大于temp)
②令 j 不断向左移动,直到找到某一元素A[ j ] <= 该元素,然后将它挪到A[ i ]所在位置(A[ i ]处的元素已经保存在了temp中),j 进入等待状态, 进入③
③令 i 不断向右移动, 直到某一元素值A[ i ] > 该元素, 将A[ i ]挪到A[ j ]所在位置(原来的元素已经挪到了该去的地方), i 进入等待状态, 进入②
④ ②③不断循环,当i 和 j 指向同一个位置时该位置就是temp应该插入的位置,直接插入就行了(原来的元素已经挪到了该去的地方)

好了,现在temp左侧的元素一定不大于它,temp右侧的元素一定大于它,等于说当整个数组全部排好序后temp的位置就在这里

下面进行[ 0, temp-1 ] 和 [temp+1, n-1]位置元素的排序,方法和上面的相同,然后再不断的切割不断地排序,直到某一区间仅有一个元素为止,这就要用到递归了

下面给出一次排序的代码

int Partition(int A[], int left, int right)
{int temp = A[left];while(left < right){while(temp < A[right] && left < right) right--;A[left] = A[right];while(temp >= A[left] && left < right) left++;A[right] = A[left];}A[left] = temp;return left;
}

有了一次排序后我们就可以递归进行多次排序

void QuickSOrt(int A[], int left, int right)
{if(left < right){int pos = Partition(A, left, right);QuickSOrt(A, left, pos-1);QuickSOrt(A, pos+1, right);}
}

下面是完整代码

#include <iostream>
#include<cstdio>
using namespace std;int Partition(int A[], int left, int right)
{int temp = A[left];while(left < right){while(temp < A[right] && left < right) right--;A[left] = A[right];while(temp >= A[left] && left < right) left++;A[right] = A[left];}A[left] = temp;return left;
}void QuickSOrt(int A[], int left, int right)
{if(left < right){int pos = Partition(A, left, right);QuickSOrt(A, left, pos-1);QuickSOrt(A, pos+1, right);}}int main()
{int A[11] = {35,18,16,72,24,65,12,88,46,28,55};QuickSOrt(A, 0, 10);for(int i = 0; i< 11; i++){printf("%d ", A[i]);}return 0;
}

输出:

快速排序优化

快速排序的特点是元素的排列越随机(不按顺序的程度高)效率越高,但序列中元素接近有序时会达到最坏的时间复杂度O(n2),原因在于我们总令temp是待排区间最左侧的元素,比如1 2 3 5 4,我们取到了1,它左边没区间,右边区间只减少了1
优化的具体做法是尽可能的令temp在区间内随机取值,这样,该算法的数学期望就稳定在O(nlogn) (详细证明见《算法导论》)

c语言中有个随机数生成器,它的写法具体是这样的:

#include<cstdio>
#include<cstdlib>
#include<ctime>
...
void _rand()
{srand((unsigned) time(NULL)); //随机数生成器必备语句for(int i = 0; i< 10; i++)printf("%d  ", rand());  //rand()生成随机数printf("\nRAND_MAX = %d", RAND_MAX);  // 生成最大值
}

输出结果

它输出最大值为32767,如果我们想令它生成范围在[a , b]之间该怎么办呢?

rand() % (b-a+1) => 输出区间在[0, b-a]之间,再 +a 就是区间[a , b]了, 即

rand() % (b-a +1) + a

如果想生成大于32767的区间该怎么办呢?
一种方法是:rand() / RAND_MAX 生成[0 , 1]的浮点数,再乘(b-a)+ a即可

(int)(round(1.0*rand() / RAND_MAX * (b-a)+a))

回到快速排序上
我们要做的是令待排序元素temp在[ i, j ]中随机取,不要忘记,已经排序好的元素时不会出现在区间内的,所以我们取一个随机元素A[p], 让它和A[ i ] 交换即可,没有任何影响。而且temp变量还可以 = A[ i ],前面的代码不会发生变化


int randPartition(int A[], int left, int right)
{//变化开始处srand((unsigned)time(NULL));int p = 1.0*rand() / RAND_MAX*(right-left) +left;swap(A[left], A[p]);//变化终止处int temp = A[left];while(left < right){while(temp < A[right] && left < right) right--;A[left] = A[right];while(temp >= A[left] && left < right) left++;A[right] = A[left];}A[left] = temp;return left;
}


输出结果相同
over

快速排序入门(动图演示)相关推荐

  1. 十大经典排序算法Python版实现(附动图演示)

    来源:大数据DT 本文约5200字,建议阅读10分钟 排序算法是<数据结构与算法>中最基本的算法之一.本文介绍10种常见的内部排序算法,及如何用Python实现. 排序算法可以分为内部排序 ...

  2. 一文读懂Python版的十大经典排序算法(附动图演示)

    来源:大数据DT 本文约5200字,建议阅读10分钟 排序算法是<数据结构与算法>中最基本的算法之一.本文介绍10种常见的内部排序算法,及如何用Python实现. 排序算法可以分为内部排序 ...

  3. 数据结构与算法--经典10大排序算法(动图演示)【建议收藏】

    十大经典排序算法总结(动图演示) 算法分类 十大常见排序算法可分为两大类: 比较排序算法:通过比较来决定元素的位置,由于时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序 非比较类型排 ...

  4. 十大经典排序算法(动图演示,收藏好文)

     0.算法概述  0.1 算法分类 十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线 ...

  5. 十大经典排序C++实现及动图演示

    0.算法概述 0.1 算法分类 十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序: ...

  6. c 语言从大到小排序算法,10 大经典排序算法(动图演示+ C 语言代码)

    原标题:10 大经典排序算法(动图演示+ C 语言代码) 来源:C语言与CPP编程 以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要. ...

  7. 程序员面试必备:动图演示十大经典排序算法及代码实现

    0.算法概述 0.1 算法分类 十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序: ...

  8. 十大经典排序算法(动图演示)(转)

    十大经典排序算法(动图演示) 本文转自https://www.cnblogs.com/onepixel/articles/7674659.html 0.算法概述 0.1 算法分类 十种常见排序算法可以 ...

  9. 一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽)

    声明 1)该文章整理自网上的大牛和专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除. 3)博主才疏学浅,文中如 ...

  10. 算法 - 十大经典排序算法(动图演示)

    [TOC] 算法 - 十大经典排序算法(动图演示) ​ 在计算机科学与数学中,一个排序算法(英语:Sorting algorithm)是一种能将一串资料依照特定排序方式进行排列的一种算法.最常用到的排 ...

最新文章

  1. Loadrunner 性能测试服务器监控指标
  2. centos mate桌面_CentOS 7安装桌面汇总
  3. Spring和SpringMVC的区别
  4. 对话李飞飞,揭秘国际体育赛事风“云”背后的黑科技
  5. DP备份任务失败原因解析
  6. html打印边距影响内容大小,关于web打印的问题,如何控制纸张大小和页边距
  7. mysql 其他引擎
  8. Python 03 基础作业
  9. 北大FAIR自动化所快手提出基于动量对比学习的层次Transformer—HiT,用于视频文本检索!代码已开源!...
  10. ihtml2document能不能根据id获取dom_JavaScript学习笔记(十三)-- DOM(上)
  11. 7.数据对象映射模式
  12. “学霸系统”课堂展示
  13. 基于MATLAB的极限与求导(附完整代码)
  14. 在路上——黄山、宏村
  15. 就北京来说,有对 PM2.5 有用的空气净化器么?
  16. 电压源和电流源的区别
  17. 2021年阿里巴巴Java岗位面试(已拿offer)
  18. 【经验】经验总结-经验教训
  19. 计算机数值方法知识,计算机数值方法.pdf
  20. 冲量在线要做数据流通基础设施服务商

热门文章

  1. Python3写爬虫(五)爬取糗事百科段子
  2. DeepFM模型调参
  3. 解决Linux服务器执行出现 -bash: ./xxx.sh: /bin/sh^M: bad interpreter: No such file or directory
  4. 大学毕业后很迷茫不知道干什么?看完这几点你就知道了
  5. java 苹果内支付_一款集成支付宝、微信支付的Java源码,支持安卓、苹果,maven项目可以看看。申精...
  6. 影响神经网络训练速度的因素使得神经网络训练速度加快的方法
  7. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
  8. 如何优雅的对 Docker 容器进行健康检查
  9. 数据结构之栈 篇四——栈应用实现进制转换
  10. 如何提升应届生职场竞争力