我有两种heapsort
算法。第一个是我写的,第二个是从某个网站上摘下来的。据我说,两者都有相同的逻辑,但第二个比第一个表现得更好。为什么会发生这种情况?我能看到的唯一区别是我的使用递归,而另一个使用迭代。仅此一项就可以成为差异化因素吗?
我的代码:
def heapify(arr,i,n):
pivot = arr[i] #the value of the root node
left,right = (i<<1)+1,(i<<1)+2 #indices of the left and right subtree root nodes
if right <= n-1: #if right is within the array, so is left
if arr[left] <= pivot and arr[right] <= pivot:
return #if both are less than the root node, it's already heapified
maximum = left if arr[left] >= arr[right] else right #else find which child has a higher value
arr[maximum],arr[i] = arr[i],arr[maximum] #swap the root node with that child
return heapify(arr,maximum,n) #make the changed child the new root and recurse
else:
if left <= n-1: #right is outside the array, so check for left only
if arr[left] <= pivot:
return
arr[i],arr[left] = arr[left], arr[i] #same logic as above
return heapify(arr,left,n)
else:
return
def heapit(array,n):
for i in range((len(array)-1)/2,-1,-1): #all elements after (len(array)-1)/2 are the leaf nodes, so we have to heapify earlier nodes
heapify(array,i,n)
def heapsort(array):
n = len(array)
for i in range(n,0,-1):
heapit(array,i) #make the array a heap
array[0],array[i-1] = array[i-1],array[0] #swap the root node with the last element
另一个代码:
def HeapSort(A):
def heapify(A):
start = (len(A) - 2) / 2
while start >= 0:
siftDown(A, start, len(A) - 1)
start -= 1
def siftDown(A, start, end):
root = start
while root * 2 + 1 <= end:
child = root * 2 + 1
if child + 1 <= end and A[child] < A[child + 1]:
child += 1
if child <= end and A[root] < A[child]:
A[root], A[child] = A[child], A[root]
root = child
else:
return
heapify(A)
end = len(A) - 1
while end > 0:
A[end], A[0] = A[0], A[end]
siftDown(A, 0, end - 1)
end -= 1
即使对于大小约为 100,000 的小型阵列,差异也变得很大。我通过将要排序的数组传递给函数来调用任一代码:HeapSort(list)
或heapsort(list)
.
编辑:
我已经用这个heapsort
函数替换了这个函数:
def heapsort(array):
n = len(array)
heapit(array,n)
array[n-1],array[0] = array[0],array[n-1]
for i in range(n-1):
heapify(array,0,n-1-i)
array[n-i-2],array[0] = array[0],array[n-i-2]
这提供了相当的性能,但它仍然较慢。对于 100 万美元的阵列,结果几乎是 20 秒:4 秒。还有什么可以做的?