当多个值等于pivot时,Hoare分区不起作用

时间:2016-07-09 23:30:08

标签: python algorithm sorting quicksort hoare-logic

我正在尝试编写自己的hoare分区函数以更好地理解它。我认为我很好地遵循了它的定义和伪代码,但即使它似乎在许多场合都按预期工作,但当它传入一个多个值等于pivot的列表时,它会分崩离析并进入无限循环。我的错误在哪里,我应该如何修改它以修复错误?

def partition(lst, left_index, right_index):
    pivot = lst[right_index]


    while True:
        #Increment left index until value at that index is greater or equal to pivot
        while True:
            if lst[left_index] >= pivot: break
            left_index += 1

        #Increment right index until value at that index is less or equal to pivot
        while True:
            if lst[right_index] <= pivot: break
            right_index -= 1

        if left_index < right_index:
            lst[left_index], lst[right_index] = lst[right_index], lst[left_index]
        else:
            return right_index

return partition(0, end)

1 个答案:

答案 0 :(得分:2)

您正在使用lst[left_index] >= pivotlst[right_index] <= pivot中的透视值测试相等性。这有效地防止了两个索引跳过枢轴值元素。因此,当两个或多个透视值元素被推向列表中间时,left_indexright_index会被一个不可逾越的障碍隔开。删除其中一条break行中的等号,非停顿问题就会消失。

然而,由于此更改,移动left_index的循环可能会将其推到right_index以上一个位置,甚至在right_index停留在其初始位置时超出界限。同样,移动right_index的循环可能会将其推到left_index以下的一个位置,甚至在left_index停留在其初始位置时也会超出界限。为防止这种情况发生,您必须将这些循环中的while True:更改为while left_index < right_index:

请注意,根据您是否删除left_indexright_index的相等性检查,分区会略有不同。当枢轴元素变成列表中的最小值或最大值时,对边界情况很重要。考虑到在开头right_index表示相对于输入范围的内部位置,left_index指向边界位置,您必须允许left_index跳过枢轴值,而right_index必须指示1}}停止在枢轴值处(相反的逻辑将使left_index保持在其初始位置直到算法结束,而right_index可以一直向下推到{{ 1}},不产生任何分区。)

因此,更正的代码将是:

left_index