根据许多网站提供的伪代码,我编写了这个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
还有另一种分区变体,即Lomuto
算法。它做了类似的事情,虽然因为我首先不了解Hoare
算法,所以我无法发现差异。任何人都可以解释算法中发生了什么,在哪种情况下哪一个能提供更好的性能?
答案 0 :(得分:2)
我建议使用一副牌和两个棋子/硬币来模拟这个,以表示i
和j
。基本上,算法同时完成这两件事:
i
和j
的值来完成的。这意味着,i
可以随时位于其中间或左侧。对j
来说恰恰相反。知道了这一点,我们可以看到while
循环所做的是找到一个位于中间左侧但应位于右侧的元素,反之亦然。也就是说,找到错误的一半中的两个元素。然后交换这些。
当i
和j
在中间相遇时,左侧会有while
跳过的元素,因为它们小于pivot
;或者从另一侧交换的元素,因此也小于pivot
。 (反之亦然,中间的元素。)
可能的混淆源是可以认为从零开始的数组索引指向一个元素,或指向两个元素之间的。例如。索引0
基本上意味着“在'第0个'和数组中的第一个元素之间”,当你访问一个元素时,你将跟随这个位置 - 使{ {1}}导致直观地数组的第一个元素。
答案 1 :(得分:0)
Hoare和Lamuto都是分区算法。分区算法在数组中移动数据,以便小于某个元素的所有内容都在一侧结束,而一切元素在另一侧结束。这可用于快速排序数组或查找中位数。
Hoare的工作原理是将两个边界向中间移动,一个从左边移动,一个从右边移动。以下步骤在循环中完成:
重复此过程,直到边界在中间相遇。结果是一个分区,左侧的所有内容都较少,而右侧的内容则较大。
Lomuto是一个类似的过程,但只使用一个边界(通常从左边向上)。这使得它更容易实现,但速度稍慢(具有相同渐近复杂度的较大常数项)。