Reputation: 77
i have this python Heapsort-Code made from a pseudocode from the net.
But it gives the wrong result.
def heapSortUp(a):
heapifyUp(a, len(a))
end = len(a)-1
while end > 0:
a[end], a[0] = a[0], a[end]
end -= 1
siftUp(a, 0, end)
return a
def heapifyUp(a, count):
end = 1
while end < count:
siftUp(a, 0, end)
end += 1
def siftUp(a, start, end):
child = end
while child > start:
parent = int(math.floor((child-1)/2)) # floor = abrunden
if a[parent] < a[child]:
a[parent], a[child] = a[child], a[parent]
child = parent
else:
return
I especially want to use the siftUP version.
by computing print heapSortUp([1,5,4,2,9,8,7])
it returns: [8, 7, 9, 2, 1, 4, 5, 7, 5]
Upvotes: 3
Views: 539
Reputation: 2129
For Ascending heap sort you can use this code:
def heapSort(a):
count = len(a)
heapify(a, count)
end = count-1
while end > 0:
a[end], a[0] = a[0], a[end]
end = end - 1
siftDown(a, 0, end)
def heapify(a, count):
start = math.floor((count - 1) / 2)
while start >= 0:
siftDown(a, start, count-1)
start = start - 1
def siftDown(a, start, end):
root = start
while root * 2 + 1 <= end:
child = root * 2 + 1
swap = root
if a[swap] < a[child]:
swap = child
if child+1 <= end and a[swap] < a[child+1]:
swap = child + 1
if swap != root:
a[root], a[swap] = a[swap], a[root]
root = swap
else:
return
Or you can use this code:
def heapSortDown(lst):
for start in range(math.floor((len(lst)-2)/2), -1, -1):
sift(lst, start, len(lst)-1)
for end in range(len(lst)-1, 0, -1):
lst[end], lst[0] = lst[0], lst[end]
sift(lst, 0, end - 1)
return lst
def sift(lst, start, end):
root = start
while True:
child = root * 2 + 1
if child > end: break
if child + 1 <= end and lst[child] < lst[child + 1]:
child += 1
if lst[root] < lst[child]:
lst[root], lst[child] = lst[child], lst[root]
root = child
else:
break
and For Decending:
def heapSortDown(lst):
for start in range(math.floor((len(lst)-2)/2), -1, -1):
sift(lst, start, len(lst)-1)
for end in range(len(lst)-1, 0, -1):
lst[end], lst[0] = lst[0], lst[end]
sift(lst, 0, end - 1)
return lst
def sift(lst, start, end):
root = start
while True:
child = root * 2 + 1
if child > end: break
if child + 1 <= end and lst[child] > lst[child + 1]:
child += 1
if lst[root] > lst[child]:
lst[root], lst[child] = lst[child], lst[root]
root = child
else:
break
Upvotes: 1
Reputation: 31429
The problem is that you need to sift down not up in heapSortUp(a)
def heapSortUp(a):
heapifyUp(a, len(a))
end = len(a)-1
while end > 0:
a[end], a[0] = a[0], a[end]
end -= 1
siftDown(a, 0, end)
return a
The reason you need to sift down is because sifting up invalidates the heap. This can be shown with a simple example.
Take a heap 4,3,2,1
. After one iteration of the sort you will have placed 4 at the end and 1 at the front. So the heap looks like this as a tree
1
3 2
However when you sift up you swap the 1
and 2
. This implies that 2 has greater priority than 3. If you continue doing the sort (as it is written) you will up the array 1,3,2,4
To get the actual sort you needed to sift down the one so that the heap looked like after the first iteration.
3
1 2
I leave the siftDown implementation to you.
Upvotes: 3