Quick Sort的两种实现方法---Python

1.思想:

  1. 取一个参考值,让序列所有的元素排序后,左侧子序列的值都比参考值小,右侧子序列的值都比参考值大。

  2. 分别对左侧和右侧的子序列做1中的递归操作。

基于上述思想,常用的实现方法有两种,一种是简单、容易理解的Lomuto scheme,另一种是效率更高的Hoare scheme。下面的代码参考自维基百科的伪代码实现,不清楚的可以移步维基,仔细研究。

2.Lomuto partition scheme:

《Programming Pearls》and 《Introduction to Algorithms》都采用这种框架。这个框架通常选择最后一个元素作为pivot,设置游标i,使用j作为索引遍历数组,保证游标i左侧的元素都<= pivot,右侧的元素全都>pivot。 ​

Python Implementation-1

# Segment 1

def partition(array, l, r):
    pivot = array[r]
    i = l - 1
    for j in range(l, r):
        if array[j] <= pivot:
            i += 1
            array[i], array[j] = array[j], array[i]
    array[i + 1], array[r] = array[r], array[i + 1]
    return i + 1
​
# Segment 2

def partition(array, l, r):
    pivot = array[r]
    i = l
    for j in range(l, r):
        if array[j] <= pivot:
            array[i], array[j] = array[j], array[i]
            i += 1
    array[i], array[r] = array[r], array[i]
    return i

def QuickSort(array, l, r):
    if l < r:
        q = partition(array, l, r)
        QuickSort(array, l, q - 1)
        QuickSort(array, q + 1, r)
    return array
​
# from wikipedia: segment 1 or 2 is both ok.

3.Hoare partition scheme

--- From wikipedia

该方法设置两个索引,从数组的两端相向移动,直到它们分别发现了可转换的元素:左索引array[i]>pivot,右索引array[j]<=pivot,显然,这两个位置的元素应该交换。当两个索引相遇,停止移动,返回最后一个index。

优点

  1. 效率高,交换次数相当于Lumoto 方法的1/3,平均来看;

  2. 对于等值数组,交换次数为0;

  3. 对于已排序数组,pivot=array[first],array[last]都会导致​的时间复杂度,而pivot=array[mid]反而会达到最优时间复杂度​。

Python Implementation-2

# Modified from wiki

def partition(array,l,r):
    pivot = array[l] 
    left = l +1 
    right = r 
    while left <= right:
        while left <= right and array[left] <= pivot:
            left += 1
        while left <= right and array[right] >= pivot:
            right -= 1
        if left <= right:
            array[left],array[right] = array[right],array[left]
    array[l],array[right] = array[right],array[l]
    return right
​
# Copy from online resource

def partition(array,l,r):
    pivot = array[l]
    left = l+1
    right = r
    done = False
    while not done:
        while left<=right and array[left]<=pivot:
            left += 1
        while left<=right and array[right]>=pivot:
            right -= 1
        if right < left:
            done = True
        else:
            array[left],array[right]= array[right],array[left]
    array[right],array[l]= array[l],array[right]
    return right

def QuickSort(array, l, r):
    if l<r:
        k = partition(array, l, r)
        QuickSort(array,l,k-1)
        QuickSort(array,k+1,r)
    return array

边界条件分析:

为什么array[l],array[right] = array[right],array[l]是对的

  1. array[left]<=pivot时,left会不断增加,但是由于前面有array[right]>pivot阻隔,至多到left=right,然后right还可以左移一位,从而使left>right,此时array[left]>pivot,array[right]<=pivot显然交换是对的;

  2. array[left]>pivot时,left暂停,array[right]>=pivot不断左移,至right=left,此时right再左移一位,right<left, array[left]>pivot,array[right]<=pivot

  3. 所有的情况只有上面两种结局,最后的状态都是array[right]<=pivot,array[left]>pivot(等值数组显然不是这种情况)。

Python Implementation-3

def QuickSort(array,l,r):
    if l>=r:
        return
    left = l
    right = r
    pivot = array[left]
    while left < right:
        while left < right and array[right] > pivot:
            right -= 1
        array[left] = array[right]
        while left < right and array[left] <= pivot:
            left += 1
        array[right] = array[left]
    array[right] = pivot
    QuickSort(array, l, left-1)
    QuickSort(array, left+, r)
    return array

边界条件分析:

  1. while left<right终止条件为left=right,保证不会出现索引溢出。

  2. array[right]>pivot使right -= 1直至left=right,由于此时array[left]<=pivot,那么整个过程相当于交换了array[left] and array[right]

  3. array[right]<=pivotleft<right,那么array[right]先复制进left位置,当array[left]<=pivot使得left+=1直至left=right时,注意此时array[right]<=pivot但是left<right的限制使得至多left=right

  4. 所有的情况都可以归结为这两种结束方式,left added to right or right decreased to left,构成一个交换的闭环。

另外一点需要注意的是,array[right]>pivot and array[left]<=pivot一定是完整的> and <=,不然无法处理元素和pivot相等的情况,而且由于不是>= and <=right and left至多以=结束,不会出现上面实现方式中的left>right,所以终止判别条件是left<right , instead of left<=right

猜你喜欢

转载自blog.csdn.net/weixin_37621790/article/details/86682313
今日推荐