Computer Science 112 Fundamentals of Programming II Heaps

  • Slides: 19
Download presentation
Computer Science 112 Fundamentals of Programming II Heaps

Computer Science 112 Fundamentals of Programming II Heaps

Complete Binary Tree A binary tree is complete if each of its levels, with

Complete Binary Tree A binary tree is complete if each of its levels, with the possible exception of the last level, has a complete complement of nodes

Array Representation A complete binary tree lends itself to an array representation

Array Representation A complete binary tree lends itself to an array representation

Primary Use: Heaps • A heap is a complete binary tree in which items

Primary Use: Heaps • A heap is a complete binary tree in which items are generally less than those one level below and greater than those one level above • A heap provides logarithmic access to items that are in a natural order • Heaps are used to implement priority queues and the O(nlogn) heap sort

Examples 3 4 6 2 7 8 3 5 4 6 7 8

Examples 3 4 6 2 7 8 3 5 4 6 7 8

The Heap Interface heap. is. Empty() heap. add(item) heap. pop() heap. peek() item in

The Heap Interface heap. is. Empty() heap. add(item) heap. pop() heap. peek() item in heap len(heap) str(tree) iter(heap)

Using a Heap heap = Array. Heap() heap. add("D") heap. add("B") heap. add("A") heap.

Using a Heap heap = Array. Heap() heap. add("D") heap. add("B") heap. add("A") heap. add("C") heap. add("F") heap. add("E") heap. add("G") print(heap) print("F" in heap) for item in heap: print(item, end = " ") while not heap. is. Empty(): print(heap. pop()) ||G |B ||E A ||F |C ||D True A B C D E F G

Using a Heap heap = Array. Heap(range(1, 8)) print("nn. Heap with 1. . 7:

Using a Heap heap = Array. Heap(range(1, 8)) print("nn. Heap with 1. . 7: ") print(heap) print("for loop: ") for item in heap: print(item, end=" ") Heap with 1. . 7: ||7 |3 ||6 1 ||5 |2 ||4 for loop: 1 2 3 4 5 6 7

The Array. Heap Class class Array. Heap(Abstract. Collection): def __init__(self, source. Collection = None):

The Array. Heap Class class Array. Heap(Abstract. Collection): def __init__(self, source. Collection = None): self. _heap = list() Abstract. Collection. __init__(self, source. Collection) # Heap methods go here

Adding an Item to a Heap • Insert the new item at the bottom

Adding an Item to a Heap • Insert the new item at the bottom of the heap (the position after the current last item in the array) • Walk the new item up the heap, swapping it with the current parent, until the current parent is less than the new item

The add Method class Array. Heap(Abstract. Collection): def __init__(self, source. Collection = None): self.

The add Method class Array. Heap(Abstract. Collection): def __init__(self, source. Collection = None): self. _heap = list() Abstract. Collection. __init__(self, source. Collection) def add(self, item): self. _size += 1 self. _heap. append(item) cur. Pos = len(self. _heap) - 1 while cur. Pos > 0: parent = (cur. Pos - 1) // 2 parent. Item = self. _heap[parent] if parent. Item <= item: break else: self. _heap[cur. Pos] = self. _heap[parent] = item cur. Pos = parent

Popping an Item from a Heap • Removes and returns the root item •

Popping an Item from a Heap • Removes and returns the root item • Replace the first item with the one at the bottom (last in the array) • Walk that item down the heap until it reaches its proper place

The pop Method def pop(self): self. _size -= 1 top. Item = self. _heap[0]

The pop Method def pop(self): self. _size -= 1 top. Item = self. _heap[0] bottom. Item = self. _heap. pop( len(self. _heap) - 1) if len(self. _heap) == 0: return bottom. Item self. _heap[0] = bottom. Item last. Index = len(self. _heap) - 1 cur. Pos = 0 while True: left. Child = 2 * cur. Pos + 1 right. Child = 2 * cur. Pos + 2 if left. Child > last. Index: break if right. Child > last. Index: max. Child = left. Child; else: left. Item = self. _heap[left. Child] right. Item = self. _heap[right. Child] if left. Item < right. Item: max. Child = left. Child else: max. Child = right. Child max. Item = self. _heap[max. Child] if bottom. Item <= max. Item: break else: self. _heap[cur. Pos] = self. _heap[max. Child] = bottom. Item cur. Pos = max. Child return top. Item

Runtime Complexity Analysis • Insertion divides position by 2 each time items are swapped:

Runtime Complexity Analysis • Insertion divides position by 2 each time items are swapped: logarithmic in worst case • Removal multiplies position by 2 each time items are swapped: logarithmic in worst case

Heap Sort • Copy the elements in the list to a heap • For

Heap Sort • Copy the elements in the list to a heap • For each position in the list, pop an element from the heap and assign it to that position

Heap Sort Implementation from heap import Array. Heap def heap. Sort(lyst): heap = Array.

Heap Sort Implementation from heap import Array. Heap def heap. Sort(lyst): heap = Array. Heap(lyst) for i in range(len(lyst)): lyst[i] = heap. pop()

Heap Sort Analysis from heap import Array. Heap def heap. Sort(lyst): heap = Array.

Heap Sort Analysis from heap import Array. Heap def heap. Sort(lyst): heap = Array. Heap(lyst) for i in range(len(lyst)): lyst[i] = heap. pop() N insertions when the heap is built from the list Each insertion is O(log 2 N) N removals when the elements are transferred back to the list Each removal is O(log 2 N) Total running time (all cases): O(Nlog 2 N) Total memory: ?

A Better Version? from heap import Array. Heap def heap. Sort(lyst): heap = Array.

A Better Version? from heap import Array. Heap def heap. Sort(lyst): heap = Array. Heap() while not lyst. is. Empty(): heap. add(lyst. pop()) while not heap. is. Empty(): lyst. add(heap. pop())

For Friday O(n) Sorting with Bucket Sort

For Friday O(n) Sorting with Bucket Sort