zoukankan      html  css  js  c++  java
  • 快速排序

    概念引入

    快速排序顾名思义就是比较快速的排序(好吧的确是废话)
    快速排序的主要实现原理其实是分治(如果不知道分治是啥的小朋友可以近似的理解为低配版二分)
    选定一个基准 然后将比基准小的数都放在基准左边 比基准大的数都放在基准右边 (基准的位置确定了)
    然后分别对基准左边的序列和基准右边的序列进行快速排序(分治)直到整个序列有序
    平均情况下需要(log_n)轮 所以时间平均复杂度应该是(nlog_n) 但是如果我们每次恰好选定的基准选到了最大值(那你可真是倒霉) 那我们每次只能确定基准一个在最终序列中的位置, 最终的时间复杂度仍然是(n^2)
    关于如何选择基准和如何移动数字 我们会在下面的章节中讲到

    基准的选择

    一般来说可以随机选择基准:选择序列的最左边或者最右边都行 ,但是刚才我们已经分析过最差的时间复杂度会是(n^2),如果出题人丧心病狂的让你把一个完全逆序的序列排成一个升序,那我们只能(n^2)了,所以我们一般会随机选取一个数
    如果是用随机函数的话,又太过麻烦,如果用一个自己写的函数去选,又可能会影响到快排的效率(快排是(nlog_n)结果你写了一个(n^3)的随机选数 那宁可真是个小机灵鬼
    这里提供一种方法叫做三数中值法,即选择序列中间的数,最左边的数,最右边的数,然后取三个数的平均数来作为基准(如果出题人心理正常的话应该就不会卡你了

    算法实现

    主要的实现方法有两种: 挖坑法和指针法 一般来说指针法使用较为广泛
    首先来看挖坑法:

    • 现在给定一个序列a[] = 4,7,6,5,3,2,8,1 要求将其按升序排序
    • 现在来整个图

      首先,我们选定基准元素Pivot,并记住这个位置index,这个位置相当于一个“坑”。并且设置两个指针left和right,指向数列的最左和最右两个元素:

      接下来,从right指针开始,把指针所指向的元素和基准元素做比较。如果比pivot大,则right指针向左移动;如果比pivot小,则把right所指向的元素填入坑中。

    在当前数列中,1<4,所以把1填入基准元素所在位置,也就是坑的位置。这时候,元素1本来所在的位置成为了新的坑。同时,left向右移动一位。

    此时,left左边绿色的区域代表着小于基准元素的区域。

    接下来,我们切换到left指针进行比较。如果left指向的元素小于pivot,则left指针向右移动;如果元素大于pivot,则把left指向的元素填入坑中。

    在当前数列中,7>4,所以把7填入index的位置。这时候元素7本来的位置成为了新的坑。同时,right向左移动一位。

    此时,right右边橙色的区域代表着大于基准元素的区域。

    下面按照刚才的思路继续排序:

    8>4,元素位置不变,right左移

    2<4,用2来填坑,left右移,切换到left。

    6>4,用6来填坑,right左移,切换到right。

    3<4,用3来填坑,left右移,切换到left。

    5>4,用5来填坑,right右移。这时候left和right重合在了同一位置。

    这时候,把之前的pivot元素,也就是4放到index的位置。此时数列左边的元素都小于4,数列右边的元素都大于4,这一轮交换终告结束。

    • 指针法:
      仍然是刚才的序列a[] = 4,7,6,5,3,2,8,1 要求将其按升序排序

    开局和挖坑法相似,我们首先选定基准元素Pivot,并且设置两个指针left和right,指向数列的最左和最右两个元素:

    接下来是第一次循环,从right指针开始,把指针所指向的元素和基准元素做比较。如果大于等于pivot,则指针向左移动;如果小于pivot,则right指针停止移动,切换到left指针。

    在当前数列中,1<4,所以right直接停止移动,换到left指针,进行下一步行动。

    轮到left指针行动,把指针所指向的元素和基准元素做比较。如果小于等于pivot,则指针向右移动;如果大于pivot,则left指针停止移动。

    由于left一开始指向的是基准元素,判断肯定相等,所以left右移一位。

    由于7 > 4,left指针在元素7的位置停下。这时候,我们让left和right指向的元素进行交换。

    接下来,我们进入第二次循环,重新切换到right向左移动。right先移动到8,8>2,继续左移。由于2<8,停止在2的位置。

    切换到left,6>4,停止在6的位置。

    元素6和2交换。

    进入第三次循环,right移动到元素3停止,left移动到元素5停止。

    元素5和3交换。

    进入第四次循环,right移动到元素3停止,这时候请注意,left和right指针已经重合在了一起。

    当left和right指针重合之时,我们让pivot元素和left与right重合点的元素进行交换。此时数列左边的元素都小于4,数列右边的元素都大于4,这一轮交换终告结束。

    以上就是快速排序的一般思路 (sort大法好) 虽然现在有现成的sort可以用但是快排的思想还是要掌握的

    点个关注>.)<

    以上插图及过程参考博客

  • 相关阅读:
    sinaapp+wordpress
    用JavaScript实现本地缓存
    Javascript的IE和Firefox(火狐)兼容性
    150个javascript特效
    学习Javascript闭包(Closure)
    JS bingo卡片
    Response.Write详细介绍[转]
    JS实现鼠标经过时背景色缓慢改变
    为什么引用不了App_Code里的类
    SQL SERVER 2008 R2配置管理器出现“远程过程调用失败”【0x800706be】的解决办法
  • 原文地址:https://www.cnblogs.com/2004-08-20/p/13257609.html
Copyright © 2011-2022 走看看