范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

一篇文章理解快排

  一 前言
  算法对于程序员来说,是一个不得不去过的门槛,除了面试,工作中用到的机会却很少,偶尔用到的算法都有封装好的库调用下,就可以了,少有机会去写一个,偶尔有机会写个和算法相关的函数,可能心中也有几分忐忑,没有充分测试,总是怀疑其中隐藏什么大bug,在不该爆发的场合突然爆发,留下的一地的尴尬。
  更可气的是,算法学起来的时候看起来都明白了,很简单嘛,真正动手去写的时候,却很难写出无bug的哪怕是简单的算法代码来,说起来还是没有深刻的理解,在一些细节上总是模糊不清,似是而非。所以学习算法这件事情来说,关键是要理解深刻的背后思想,不能是简单地过一遍,而是学一分就深刻理解一分,一分不理解就不要看其他的,揉碎了融入自己的思想里面,变成自己的内功,才算有收获。 二 为什么是快速排序
  首先的问题是为什么要排序,除了一些我们想知道排名的场合,比如高考排名等?如果不是这些场合是不是就不要排序了,排序是计算机里面的最基本需求,排序的目的想想还是挺多的,比如我们需要知道Top K值,比如我们需要取一个城市工资的中位数,这个数值比所谓的平均值要靠谱的多,还比如有了排序,就可以做范围查询,有了排序就可以二分查找法,快速查到要搜索的数据,40亿的排序数据查找一个数,只需要最多32次,简直称得上魔法。
  那为什么是快速排序那,其实也没啥特别的,就觉得快排的思想挺有意思的,二是性能也很优秀,时间复杂度为O(nlogn), 如果面试偶尔让现场手写个快排代码,也不至于没有啥准备。
  虽然快排也有很多种实现,这篇是介绍的最简单的实现,没做什么优化,虽然不是最有用的,但是因为最简单,所以容易理解深刻,也容易写,也记得住。 三 快速排序3.1 快排具体过程
  总体来说,快排就三步: 从数组中选择一个基准值; 以这个基准值为界,将大于这个基准值的数放在基准值的右边,将小于基准值的数放在基准值的左边; 对左右两个区间递归秩序是第一步和第二步。 3.1.1 基准分区
  第一步和第三步都比较简单,关键是第二步,按照步骤说明下:
  说明: 1) 对上述的数组选择一个基准值,最简单的办法选择第一个元素作为基准值,赋值给tmp。 选择基准值后,第一个元素相当于空出来了。
  比较
  说明:我们设置两个指针(其实这里面是下标),分别指向数组的头部和尾部,从尾部开始判断array[j]是不是大于基准值, 因为1<6,所以需要将array[i] = array[j] ,因为比基准值小,所以要移动到前面去,且把i指针向后移动一位,因为i指针原来值的位置已经被填了值,即是处理过了。
  说明: 我们判断i处的值是否小于基准值,小于则继续对后移动,一直移动到了array[i] == 9的位置,这时候条件不满足了。
  说明:因为array[i] > 基准值6,则需要将array[j] = array[i], 即将i索引处的值9 赋值到j索引指向的位置。
  填上基准值
  说明: i==j了,说明本轮结束了,将基准值回填,这样经过了一轮的比较,我们就得到了第一个元组的正确位置,通过6将整个集合分成了两个部分,一个是左边的子集,全部小于6,一个是右边的子集全部大于6,如下:
  3.1.2 两个子集再递归
  通过上图我们得到了 左边子集 + 基准元组+ 右边子集,然后我们分别对左边子集再执行类似的操作,右边子集再进行类似的操作,就完成了整个数组的排序。
  左边子集的元素范围是 【 开始索引,i-1】 右边子集的范围是【i+1,结尾索引】 3.1.3 转成实际代码// 分区 int partion(int a[], int l, int r) {   int tmp = a[l];   while (l < r) {     // 从后对前判断元素是否大于基准值,大于则r 指针对前移动     while (a[r] > tmp && l < r) {       r--;     }     // 小于则赋值给首个元素,即将值移动到前面    // 如果l==r 则相当于a[0] = a[0] 无影响     a[l] = a[r];    // 从前对后判断是否小于基准值,小于等于对后移动     while (a[l] <= tmp && l < r) {       l++;     }     // 将值移动到后面     a[r] = a[l];   }   a[r] = tmp;   return r; }   void qsort(int a[], int left, int right) {   if (left < right) {     int mid = partion(a, left, right);     // 对前面的子集进行排序     qsort(a, left, mid - 1);    // 对右边的子集进行排序     qsort(a, mid + 1, right);   } }
  虽然代码没做任何其他优化,好处是便于理解也足够简单。 3.2 快排的时间复杂度
  复杂度重点在于按照基准值的分区,其他的只是递归计算而已,因为分区的时候我们用的两个指针的技术条件是i == j,扫描了整个数组空间,所以分区函数的时间复杂度是O(n),所以总的时间复杂度为: O(n) = n + T(L) + T(R) 然后T(L)和T(R) 又可以做递归分解,我们按照树的形式将时间分解如下:
  如上图所示,整个算法的耗时,就是每层耗时,而每层耗时的时间即是分区函数的时间:
  第一层: n个元素,分区所占时间为n;
  第二层:L子集分区时间为L,R子集分区时间为R,那第二层整体的分区所占时间为L+R,而L+R = n- 1 所以第二层耗时看作是n-1.
  第三层:LL +LR+RL+RR = L-1+R -1 即n-3, 依次类推: O(n) = n + n-1 + n-3 + ....看这个是不是等差数列,不,别上当,再计算一层看看:
  第四层:LLL+ LLR+LRL+LRR +RLL+RLR+RRL+RRR = LL -1 + LR -1 + RL-1 +RR -1 = (LL+LR)-2 + (RL+RR)-2 = L -1 -2 + R-1 -2 = L+R -6 = n - 7 看到了吧,这种树如果是完全二叉树,每层耗时递减得很快,完全二叉树的数量: 2的h次方(h为树高度)减去1,指数级别的增加;
  完全二叉树的高度最低为log2n ,n为节点数,按照刚刚每次计算的耗时,如果n很大,每层接近耗时为n,则总耗时为树的高度* 每层耗时 = n log2n,即时间复杂度为O(nlog2n)这是最好的情况,如果特殊情况,本身是倒序的,那么树就变成链表,就是n n最坏的时间复杂度为O(n^2)。 四 应用和优化4.1 快排找第k大元素
  快速排序算法除了可以排序外,还可以方便找第k大的元素,因为我们每次快排都找到了第一个元组的正确位置index,如果我们要找的第k大元素的k 小于index,那么我们就在小于基准值的集合里面去继续找第k大元素,如果第k大元素大于index,那么第k大元素在大于基准值的集合去找,但是不是找第k元素了,而是找第k-index的元素,这样每次我们都能过滤掉一个集合,性能显然很快。 4.2 优化快排
  单边递归优化  分区后,继续对左右两边排序,我们可以把一边在本轮直接处理了,所以叫单边优化: quick_sort(arr, l, x - 1); // 对左子集排序 quick_sort(arr, x + 1 , r); // 对右子集排序
  可以做成: void quick_sort(int *arr, int l, int r) {     while (l < r) {         // 分区         int ind = partition(arr, l, r);         // 对大于基准值的右子集正常调用递归函数          quick_sort(arr, ind + 1, r);         // 用本层处理左侧的排序         r = ind - 1;     }     return ; }
  减少了递归的层次,提升了性能。
  三点取中法  如果基准值选择得好,那么整个递归排序展开就是完全二叉树,性能最好,所以基准值选择很重要,有种优化是选择开头元素,结束元素,中间元素三个元素中,中间那个,当然上面的代码就不适用了,很大程度上避免选择基准值的问题。
  分区函数优化  分区的时候我们每次只是将其中i处和j处的值其中一个赋值给另外一个,如果我们只要满足条件就做移动,直到i和j都不满足的时候,交换两者的值,减少赋值过程,这样性能更快。

中老男人的眉毛变长,意味着什么?说明长寿吗?原因要心中有数你这是长寿眉,你为啥要拔掉啊!王叔一声吆喝,吓得老王镊子都掉了。老王对于自己的形象十分在意,经常拿着镊子在脸上夹来夹去,最近他发现自己的眉毛有几根长得非常之长,看着十分碍眼。于是决你了解圆桌骑士的传说吗?召唤,就在此时重聚,只此一次罗杰杜彼圆桌骑士系列腕表臻品展缘起亚瑟王十二圆桌骑士相传在崇尚平等与自由的亚瑟王麾下有一群威名远扬的高贵骑士他们怀着满腔热忱无畏艰险无惧挑战誓死保卫王国知衣数据报告女款装业洞察ampampamp趋势分析西装,近两年最热门的时尚单品之一,以其刚与柔高级与性感的完美结合,展示着前所未有的女性独特魅力,成为各个服装品牌的爆款种子选手。知衣科技出品西装行业洞察趋势分析,通过解析秀场市场上国产新品!驭帅13新配色有点帅,克莱上脚KT8,AG3新配色曝光最近国产品牌有点闷声发大财的感觉了,新品都悄悄和大家见面了,这些产品非常有意思,李宁的驭帅13安踏的KT8代匹克为李月汝做的大三角,还有阿隆戈登的第三代签名鞋,都以一种特殊的方式曝赵睿郭艾伦最终还是胳膊拧不过大腿?那周琦呢?今天,是CBA新赛季本土球员注册期的最后一天。郭艾伦周琦这两位CBA的招牌球员到底何去何从,或许将迎来最终答案,但似乎悬念并不大。本来,国手赵睿也在这份不确定名单里,不过昨晚他通过中国男篮二队发布第二期集训通知16人集训名单中10人来自CUBA北京时间8月31日,中国篮协官方公布国家二队男篮运动员第二期集训名单,韩登出任主教练,16名参加集训的球员中,有10人来自大学校队。中国男篮二队在今年4月初启动,主要目的是策应204年1。2亿续约!钱多任性的尼克斯,在下一盘大棋?尼克斯去年没进季后赛,但这不妨碍他们花钱的野心。继布伦森后,巴雷特也拿到了亿元合同,包含杂七杂八的激励条款在内,最高可达4年1。2亿。协议最快下周一签署,之所以推迟,其原因在于尼克中午12点,中国足坛爆发大新闻,陈戌源助手被立案调查最近这一段时间,关于中国足球,尤其是男足这个领域,大家相对比较关注的是此前在广东u15运动会上的一场假球案,这也是引起了球迷的关注。而这个假球,原本是要中国足协内部进行审查的,但后勇士天赋男库明加出战世预赛,他表现怎样?刚果(金)男篮在世预赛目前的战绩为4胜5负,排名小组第五。他们在比赛中暴露出许多问题,防守纪律性整体性差,回防慢慢悠悠,在比赛中出现过被对手抢断后,一人回防,四人站在前场看的情况对名嘴新赛季篮网成为你们的噩梦,是夺冠热门,你看好新三巨头吗近日ESPN名嘴麦克格林伯格在节目中谈到了新赛季的篮网。格林伯格说道他们将打得很出色,将成为你们最糟糕的噩梦,因为杜兰特欧文和本西蒙斯都将目标明确,动力十足,我觉得以篮网目前的阵容国安签新帅细节内幕曝光,对他心仪已久,印证从未打算重用谢峰日前,北京国安正式官宣荷兰名帅斯坦利正式接手球队。随后,国内媒体就披露了斯坦利跟国安签约的细节。首先,国安在本赛季中超开打前,就有意请斯坦利执教球队。只是,国安俱乐部不确定斯坦利能
借助科技势能同程数科持续深耕旅行产业链近日,同程旅行发布2022十一假期旅行趋势报告,报告显示休闲度假和城市周边深度游仍是人们假日生活的刚需。近一周十一相关旅游搜索热度环比上涨172,假期出行的机票酒店搜索热度上涨13为削减成本,百事可乐考虑买断55岁以上员工工龄甚至裁员当地时间9月29日,福克斯商业(FoxBusiness)报道称,百事可乐可能会因为经济原因而采取一些削减成本的措施。报道称,这家饮料巨头正在考虑向55岁以上的员工提供买断工龄的机会借助科技势能同程数科持续深耕旅行产业链近日,同程旅行发布2022十一假期旅行趋势报告,报告显示休闲度假和城市周边深度游仍是人们假日生活的刚需。近一周十一相关旅游搜索热度环比上涨172,假期出行的机票酒店搜索热度上涨1310月起,这些新规将影响你我生活10月小长假将至,一大批新规也将落地。水果味电子烟将全面下架,验车以及交通标识也将发生重大变化,来看看这些即将影响到你我生活的新规。海关总署调整必须实施检验的进出口商品目录海关总署说教无用,因为没人喜欢被改变试图说服一个人的时候,许多人会习惯性地摆事实讲道理,这是一种最简单的沟通方式我把自己了解的所有知识都讲解给你,我把自己所有的生活经验都呈现给你,我把所有可以安身立命的方法都告诉你不10月起,这些新规将影响你我生活10月小长假将至,一大批新规也将落地。水果味电子烟将全面下架,验车以及交通标识也将发生重大变化,来看看这些即将影响到你我生活的新规。海关总署调整必须实施检验的进出口商品目录海关总署说教无用,因为没人喜欢被改变试图说服一个人的时候,许多人会习惯性地摆事实讲道理,这是一种最简单的沟通方式我把自己了解的所有知识都讲解给你,我把自己所有的生活经验都呈现给你,我把所有可以安身立命的方法都告诉你不商务部三方面发力促进消费持续恢复商务部新闻发言人束珏婷29日表示,商务部从抓重点拓场景畅流通三方面发力促进消费持续恢复。束珏婷在商务部当日举行的网上例行新闻发布会上说,近期稳增长促消费政策持续发力,国内消费市场呈商务部三方面发力促进消费持续恢复商务部新闻发言人束珏婷29日表示,商务部从抓重点拓场景畅流通三方面发力促进消费持续恢复。束珏婷在商务部当日举行的网上例行新闻发布会上说,近期稳增长促消费政策持续发力,国内消费市场呈煤炭运销一体化煤炭运销的四流合一煤炭运销是依据煤炭买卖合同组织货源安排发运并完成煤款回收的过程。整个过程中需要我们及时掌握生产矿铁路等运输部门及用户的情况,协调各方关系,满足用户需求的同时,提高企业的运转效率。而煤炭运销一体化煤炭运销的四流合一煤炭运销是依据煤炭买卖合同组织货源安排发运并完成煤款回收的过程。整个过程中需要我们及时掌握生产矿铁路等运输部门及用户的情况,协调各方关系,满足用户需求的同时,提高企业的运转效率。而