Python Hoare分割算法的解释

Python Hoare分割算法的解释,python,partitioning,hoare-logic,Python,Partitioning,Hoare Logic,根据许多网站中给出的伪代码,我编写了这个Hoare分区算法,该算法采用一个数组,子数组的开始和结束索引根据给定的轴进行分区。它工作得很好,但是有人能解释一下逻辑,它是如何工作的吗?下面是代码: def hoare(arr,start,end): pivot = 4 i,j = start,end while i < j: while i < j and arr[i] <= pivot: i += 1

根据许多网站中给出的伪代码,我编写了这个
Hoare
分区算法,该算法采用一个数组,子数组的开始和结束索引根据给定的轴进行分区。它工作得很好,但是有人能解释一下逻辑,它是如何工作的吗?下面是代码:

def hoare(arr,start,end):
     pivot = 4
     i,j = start,end
     while i < j:
        while i < j and arr[i] <= pivot:
            i += 1
        while j >= i and arr[j] > pivot:
            j -= 1
        if i < j:
            arr[i],arr[j] = arr[j],arr[i]
     return j    
def hoare(arr,start,end):
枢轴=4
i、 j=开始,结束
而i枢轴时:
j-=1
如果i

分区还有另一种变体,
Lomuto
算法。它做了一些类似的事情,虽然因为我一开始不理解Hoare算法,所以我无法发现区别。有谁能解释一下算法中发生了什么,在这种情况下,哪一种算法的性能更好?

我建议用一副牌和两个典当/硬币来模拟这个过程,以表示
I
j
。基本上,算法同时完成这两件事:

  • 找到阵列应拆分的位置,以便在此位置的左侧和右侧具有正确数量的“桶”。这是通过在分区的“中间”集合的
    i
    j
    值来完成的
  • 将数组元素移动到中间的左侧或右侧,具体取决于它们是否小于或大于轴
这意味着在任何时候,
i
要么在它的中间,要么在它的左边。对于
j
,情况正好相反。知道了这一点,我们可以看到
while
循环所做的是找到一个位于中间左侧但应该位于右侧的元素,反之亦然。也就是说,找到两个错误的元素。然后交换这些

<> > <代码> < <代码> >代码> j>代码>在中间相遇,左边的元素<>代码> > <>代码>,因为它们小于<代码>枢轴< /代码>;或者从另一侧交换的元素,因此也比
pivot
小。(对于中间右侧的图元,反之亦然。)

一个可能引起混淆的原因是,从零开始的数组索引可以被认为是指向一个元素,或者指向两个元素之间的点。例如,索引
0
基本上意味着“在数组的第0个元素和第一个元素之间”,当你访问一个元素时,你取这个位置后面的一个元素-使
数组[0]
直观地得出数组的第一个元素。

两者都是分区算法。分区算法在数组中移动对象,使小于某个元素的所有对象都在一边,而大于某个元素的所有对象都在另一边。这可用于快速排序数组或查找中值

霍尔的工作原理是将两个边界向中间移动,一个从左边移动,一个从右边移动。以下步骤在循环中完成:

  • 左边界将移动,直到到达比所选元素更大的位置
  • 右边界将移动,直到它到达比所选元素更小的位置
  • 如果没有跨越边界,那么这两个边界将被交换
  • 这个过程反复进行,直到边界在中间相遇。结果是一个分区,左边的东西越少,右边的东西越大


    Lomuto是一个类似的过程,但只使用一个边界(通常从左侧向上)。这使得它更容易实现,但有些慢(更大的常数项具有相同的渐近复杂性)。

    如果有助于其他人解释的话,我找到了这个演示文稿:呵呵,我也查找了同一个文档,尽管是在不同的位置:!谢谢这很有教育意义。你能解释一下,什么时候我更喜欢这种算法而不是
    Lomuto
    算法,或者反之亦然?@Cupidvogel我不熟悉Lomuto算法。我浏览了问题评论中链接的演示文稿,其中包括一项复杂性分析,该分析平均会使霍尔的算法更快。@millimoose我读到,当存在许多重复值(即超过2/3的数组具有相同的值)时,与霍尔相比,Lomuto的性能较差