递归如何在堆排序中工作?

时间:2015-02-18 03:23:56

标签: recursion heapsort

假设我有一个数组A =< 1,6,2,7,3,8,4,9,5> Heapsort的伪代码:

BUILD-MAX-HEAP(A)
n = A.heapsize = A.length
for i = floor(n/2) down to 1
   MAX-HEAPIFY(A,i)

MAX-HEAPIFY(A,i)
n = A.heap-size
l = LEFT(i)
r = RIGHT(i)
if l <= n and A[l] > A[i]
   largest = l
if r <= n and A[r] > A[largest]
   largest = r
if largest != i
   exchange A[i] <-> A[largest]
   MAX-HEAPIFY(A,largest)

我知道BUILD-MAX-HEAP将首先调用MAX-HEAPIFY(A,4),它将交换7和9,然后在MAX-HEAPIFY(A,3)之后它将切换8和2.然后它将调用MAX-HEAPIFY(A,2),这是我感到困惑的地方。这是当MAX-HEAPIFY(A,2)被调用

时堆的外观

首先要做的是交换6和7,然后调用MAX-HEAPIFY(A,4)(因为4现在最大),交换6和9,然后调用MAX- HEAPIFY(A,8)但是没有任何事情会发生,因为你已经到达了一个叶子,所以它会返回到调用它的函数。

MAX-HEAPIFY(A-8)被MAX-HEAPIFY(A,4)调用,所以返回它

MAX-HEAPIFY(A,4)被MAX-HEAPIFY(A,2)调用,所以返回它

但现在A [2]&lt; A [4](因为7&lt; 9),正是在这一点上,我想知道如何再次调用MAX-HEAPIFY(A,2)来交换7和9.当一个递归函数(或子程序)返回时对于调用它的那个,没有更多的代码可以执行(因为MAX-HEAPIFY只在函数的末尾调用MAX-HEAPIFY),所以它会返回递归堆栈,在我看来它感觉就像7仍然是9的父母

很抱歉,如果这令人困惑,但有人可以告诉我这一点,以帮助我了解这是如何递归地最大化堆积自己?

1 个答案:

答案 0 :(得分:1)

以下是我在遵循算法时得到的一系列步骤(请注意我们在每个算法结束时递归时的缩进级别)。每次我们退出函数时,我们只返回主程序(调用max_heapify,数字4为1)。我不肯定你的解释是什么,但我希望以下内容更清楚。

for i in (4,3,2,1):
    MAX-HEAPIFY(A,i)

MAX-HEAPIFY(A,4):
    largest=4  # initialized
    l=8
    r=9
    largest=8  # calculated
    swap A[4] and a[8]:
    A = <1,6,2,9,3,8,4,7,5>
    MAX-HEAPIFY(A, 8):
        largest=8  # initialized
        l=16
        r=17
        ...return
    ...return

MAX-HEAPIFY(A,3):
    largest=3  # initialized
    l=6
    r=7
    largest=6  # calculated
    swap A[3] and A[6]:
    A = <1,6,8,9,3,2,4,7,5>
    MAX-HEAPIFY(A, 6):
        largest=6
        l=12
        r=13
        ...return
    ...return

MAX-HEAPIFY(A,2):
    largest=2 # initialized
    l=4
    r=5
    largest=4 # calculated
    swap A[2]and A[4]:
    A = <1,9,8,6,3,2,4,7,5>
    MAX-HEAPIFY(A, 4):
        largest=4  # initialized
        l=8
        r=9
        largest=8
        swap A[4] and A[8]:
        A = <1,9,8,7,3,2,4,6,5>
        MAX-HEAPIFY(A, 8):
            largest=8  # initialized
            l=16
            r=17
            ...return
        ...return
     ...return

MAX-HEAPIFY(A,1):
    largest=1  # initialized
    l=2
    r=3
    largest=2  # calculated
    swap A[1] and A[2]:
    A = <9,1,8,7,3,2,4,6,5>
    MAX-HEAPIFY(A, 2):
        largest=2:  # initialized
        l=4
        r=5
        largest=4:  # calculated
        swap A[2] and A[4]:
        A = <9,7,8,1,3,2,4,6,5>
        MAX-HEAPIFY(A, 4):
            largest=4:  # initialized
            l=8
            r=9
            largest=8:  # calculated
            swap A[4] and A[8]:
            A = <9,7,8,6,3,2,4,1,5>
            MAX-HEAPIFY(A, 8):
                largest=8:  # initialized
                l=16
                r=17        
                ...return
            ...return
        ...return
    ...return

Done!
A = <9,7,8,6,3,2,4,1,5>

然后我甚至将你的算法(几乎直接)翻译成python(注意我必须对python的基于0的索引进行一些调整):

def build_max_heap(A):
    for i in range(len(A)//2, 0, -1): 
        max_heapify(A, i)

def left(x):
    return 2 * x

def right(x):
    return 2 * x + 1


def max_heapify(A, i):
    n = len(A)
    largest = i
    l = left(i)
    r = right(i)
    if l<=n and A[l-1] > A[i-1]:
        largest = l
    if r <=n and A[r-1] > A[largest-1]:
        largest = r
    if largest !=i:
        A[i-1], A[largest-1] = A[largest-1], A[i-1]
        max_heapify(A,largest)

if __name__ == '__main__':
    A = [1,6,2,7,3,8,4,9,5]
    build_max_heap(A)  # modifies in-place
    print(A)

这打印: [9,7,8,6,3,2,4,1,5] (这与我们的手动迭代一致)

...还有一次检查,使用python的heapq模块及其私有方法_heapify_max

import heapq
A = [1,6,2,7,3,8,4,9,5]
heapq._heapify_max(A)
print(A)

...打印相同: [9,7,8,6,3,2,4,1,5]