关于快速排序算法本质的重要说明 - 考试考了不会就不要怪我

说明,本文章的针对已经大致的理解了快速排序的同学

双向扫描 VS 单向扫描

我们都知道,快速排序算法存在两种实现机制,一种是单向扫描法,一种是优化后的双向扫描法

单向扫描:

首先,我们需要知道,单向扫描是最正规的《算法导论》上给出的基本实现的过程
伪代码如下
data - array wait to sort
n - the count of the array
i - head point
j - tail point

quicksort (left,right)
    if left>=right return 
    else
        partition(left,mid,right)   //引用传址
        quicksort(left,i-1)
        quicksort(i+1,right)
        return

partition (left,mid,right)
    i=j=left-1
    temp = data[right]
    for j to right-1
        if data[j]<temp
            t = data[i+1]
            data[++i] = data[j]
            data[j] = t
    t = data[right]
    data[right] = data[i+1]
    data[i+1] = t
在单向扫描的过程中,我们的枢纽点选定的就是最后一个元素(随机化的过程我们只需要一步就是将我们的选取的枢纽点迁移到最后的 位置,没有什么多余的影响)

双向扫描:

双向扫描的伪代码:
data - array wait to sort
n - the count of the array
i - head point
j - tail point
//先动头指针的情况,之后会详细说明
quicksort (left,right)
    if left>=right return
    else
        i = left
        j = right
        temp = data[left]
        while i!=j
            while i<j and temp<=data[j] j--
            while i<j and temp>=data[i] i++
            if i!=j swap(i,j)
        swap(i,left)
        quicksort(left,i-1)
        quicksort(i+1,right)
        return 

比较和注意事项

1.效率:
首先,我们来关注一下,那一个的效率更加的优秀
对于双向扫描的单向扫描的流程我们会发现,对于对于所有比枢纽点小的元素我们都要进行一次swap操作,但是双向扫描不一样,我们会发想,双向扫描对并不是对所有的小于枢纽点的元素都进行了swap操作,真是这一点,导致我们的双向扫描的效率高于单向扫描,我的上一篇的博客用Python对两种扫描方式进行了实验发现,实际上双向扫描确实比单向扫描快很多
本轮:双向扫描 better than 单向扫描

2.算法的细节
我们这里需要着重分析一下,对于不同的情况,我们的双向扫描的枢纽点的选取非常的重要(枢纽点的选取直接影响到我们的头尾指针的次序关系)
首先,我们先来假设一段序列经过快速排序的一次partition划分之后枢纽点的位置是i,如下简图所示
0 1 2 3 4 . . . . . . i . . . . . . n
那么我们的枢纽点在没有划分之前的位置 j 有很大的不同(下面解释利用升序排列,降序排列同理不用证明)
1. j < i
在这时候,我们必须要先动尾指针
原因如下:
                 正面解释:我们先动尾指针可以保证我们最后尾指针停止的点处的元素的值一定是比枢纽点小(分两种情况,如果我们直接找到一个比枢纽点小的元素(没有强制终止,头尾指针不同)那么必定比枢纽点小,如果一直找到头尾指针相同的时候强制终止,这时候,因为上次的交换保证我们的此处的点的值必定比我们的枢纽点小)这时候我们进行最后的交换的时候,可以保证我们的枢纽点左边的元素都比枢纽点小,右边的元素都比枢纽点大,正确
反面解释:我们如果采用头指针先动的话,按照上面的描述过程,我们的乳沟在最后头尾指针强制终止的时候必定导致我们的最后一次交换之后,枢纽点右边的元素都比枢纽点大,但是左边存在一个数比我们的枢纽点大(这个书就是我们的强制头尾指针相遇的位置处的元素值,这个值必定比枢纽点大),错误
2. j > 1
解释和上面的是镜像的关系,很好证明

针对于单向扫描的时候,我们只需要将枢纽点和最后一个位置的元素进行交换就可以了
其实上面的双向扫描的这个缺点,在我们的随机化的挑选枢纽点的位置的时候,我们可以预处理将我们的枢纽点强制的放在第一个或者最后一个(这样可以保证我们采用先头指针动或者先尾指针动的选择方案)
本轮:单向扫描 > 双向扫描

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值