我相信问题在于您已经将 do-while (或重复直到,用 Hoare 的术语)循环转换为 while 循环,因此它永远不会执行第一个 j -= 1。
Python 中最简单的转换应该是像这样更改两个内部 while 循环:
while True:
i += 1
if not (i < j and arr[i] < pivot): break
while True:
j -= 1
if not (j >= i and arr[j] >= pivot): break
(我在这里假设if i < j:
应该在第二个while循环之外,并且所有其他初始缩进都是正确的。)
我还没有完全推理出这一点,也没有进行各种测试,但您的翻译中可能不仅仅是这个错误。您可能还需要将外部循环转换为 do-while (Hoare 实际上通过最后的检查使其显式while TRUE
),但我不确定。无论如何,对于您的示例输入,修改后的版本返回9
, 和arr
is [10, 6, 8, 1, 4, 9, 2, 1, 7, 14, 5]
,这是不正确的,但它解决了您的无限循环问题。
下一个问题是一个错误。如果您要在内部循环中执行+= 1
and -= 1
first,则必须从 开始-1
,len(arr)
而不是0, len(arr)-1
(或者,如您所做的那样,1, len(arr)-1
)。
可能还有其他问题。但我不想深入研究你的代码,找出所有可能的错误并解释它们。如果您需要,请告诉我们我们的来源是什么,并解释您从该来源进行的每个转换,这样解释您哪里出错会容易得多。如果没有,直接将 Hoare 的算法翻译成 Python 会简单得多,然后希望你能弄明白。
这是我在网上找到的 Hoare 伪代码的副本(只是将所有制表符替换为两个空格):
Hoare-Partition (A, p, r)
x ← A[p]
i ← p − 1
j ← r + 1
while TRUE
repeat j ← j − 1
until A[j] ≤ x
repeat i ← i + 1
until A[i] ≥ x
if i < j
exchange A[i] ↔ A[j]
else
return j
这是对 Python 的简单翻译;唯一的变化是较小的语法(包括“交换”的拼写方式)和将每个重复/直到变成一段时间 True/break。
def hoare(a, p, r):
x = a[p]
i, j = p-1, r+1
while True:
while True:
j -= 1
if a[j] <= x:
break
while True:
i += 1
if a[i] >= x:
break
if i < j:
a[i], a[j] = a[j], a[i]
else:
return j
对于与您的签名相同的函数:
def hoare0(arr):
return hoare(arr, 0, len(arr)-1)