关于python

时间:2016-08-24 21:10:58

标签: python

我正在尝试实施heapsort但是我得到了意想不到的结果。我认为这是由于我不了解Python如何处理变量(我在谈论副作用)。这是代码:

from math import *

def parent(i):
    return floor((i+1)/2)-1

def left(i):
    return 2*i+1

def right(i):
    return 2*i+2

def maxheapify(A, i):
    l = left(i)
    r = right(i)
    if l < len(A) and A[i] < A[l]:
        largest = l
    else:
        largest = i
    if r < len(A) and A[largest] < A[r]:
        largest = r
    if largest != i:
        temp = A[i]
        A[i] = A[largest]
        A[largest] = temp
        maxheapify(A, largest) 


def buildmaxheap(A):
    for i in range(int(floor(len(A)/2)), -1, -1):
        maxheapify(A, i)

def heapsort(A):
    n = len(A)
    buildmaxheap(A)
    for k in range(len(A), 0, -1):  
        temp = A[0]
        A[0] = A[k-1]
        A[k-1] = temp
        C = A[0:k-1]
        maxheapify(C, 0)
        A = C + A[k-1:n]
    print(A)

现在我跑

A = [2, 4, 1, 3, 7, 5, 9]
heapsort(A)
print(A)

我获得两条印刷线(一条来自堆垛内部,显示分拣工作,一条来自最后一幅印刷):

[1, 2, 3, 4, 5, 7, 9]
[1, 7, 5, 3, 4, 2, 9]

显然,我希望它们都是相同的(这意味着排序实际上有效,A在调用heapsort(A)后排序)

所以我得不到的是:

  1. 如果A被正确排序(在heapsort(A)的最后一行),为什么离开功能块后这种变化不会持续?

  2. 如果这是由于变量A的某些持久性,为什么最终结果不是A的原始值,而是heapsort的中间步骤,这是maxheapify调用的结果?

3 个答案:

答案 0 :(得分:2)

在函数开始时,函数内的列表A与函数外部的列表相同,对一个函数的任何修改都将反映在另一个函数中(它是一个可变对象)。

当您对列表进行分配时,您将新列表对象替换为旧列表对象。这会破坏与外部对象的连接。

您可以分配到A切片,而不是将新列表分配给A,而是原来的对象将会被修改。

A[:] = C + A[k-1:n]

答案 1 :(得分:1)

A[:] = C + A[k-1:n]

这是您所看到的行为的责任。通过将A设置为等于A [0:k-1] + A [k-1:n],您将复制所有A的元素。如果您希望更改在传入的列表中保留,则必须将列表分配给A的所有元素,如下所示:

android:background="@drawable/food_wallpaper"

答案 2 :(得分:1)

以下实现显示了对代码的重写,但在最后一次调用print函数之后包含了一个替代解决方案。注释掉的行可以替换其正上方的行,或者您可以选择在a函数末尾返回heap_sort并重新绑定amain的值而不是函数。

def main():
    a = [2, 4, 1, 3, 7, 5, 9]
    heap_sort(a)
    print(a)

parent = lambda i: (i + 1 >> 1) - 1
left = lambda i: (i << 1) + 1
right = lambda i: i + 1 << 1

def max_heapify(a, i, n):
    l = left(i)
    r = right(i)
    largest = l if l < n and a[i] < a[l] else i
    if r < n and a[largest] < a[r]:
        largest = r
    if largest != i:
        a[i], a[largest] = a[largest], a[i]
        max_heapify(a, largest, n)

def build_max_heap(a, n):
    for i in reversed(range(n + 2 >> 1)):
        max_heapify(a, i, n)

def heap_sort(a):
    n = len(a)
    build_max_heap(a, n)
    for k in reversed(range(n)):
        a[0], a[k] = a[k], a[0]
        c = a[:k]
        max_heapify(c, 0, k)
        a[:k] = c
        # the following would change "a" in this scope only
        # a = c + a[k:]
    # print(a)

if __name__ == '__main__':
    main()