def extract(self): """ Extract root element of the Heap. Returns ======= root_element : TreeNode The TreeNode at the root of the heap, if the heap is not empty. None If the heap is empty. """ if self._last_pos_filled == -1: return None else: element_to_be_extracted = TreeNode(self.heap[0].key, self.heap[0].data) self._swap(0, self._last_pos_filled) self.heap[self._last_pos_filled] = TreeNode( float('inf') if self.heap_property == 'min' else float('-inf'), None) self._heapify(0) self.heap.pop() self._last_pos_filled -= 1 return element_to_be_extracted
def insert(self, key, data=None): """ Insert a new element to the heap according to heap property. Parameters ========== key The key for comparison. data The data to be inserted. Returns ======= None """ new_node = TreeNode(key, data) self.heap.append(new_node) self._last_pos_filled += 1 i = self._last_pos_filled self.heap[i]._leftmost, self.heap[ i]._rightmost = self.d * i + 1, self.d * i + self.d while True: parent = (i - 1) // self.d if i == 0 or self._comp(self.heap[parent].key, self.heap[i].key): break else: self._swap(i, parent) i = parent
def test_BinaryHeap(): max_heap = BinaryHeap(heap_property="max") assert max_heap.extract() is None max_heap.insert(100, 100) max_heap.insert(19, 19) max_heap.insert(36, 36) max_heap.insert(17, 17) max_heap.insert(3, 3) max_heap.insert(25, 25) max_heap.insert(1, 1) max_heap.insert(2, 2) max_heap.insert(7, 7) assert str(max_heap) == \ ("[(1, 100, 100, 2), (3, 19, 19, 4), " "(5, 36, 36, 6), (7, 17, 17, 8), " "(None, 3, 3, None), (None, 25, 25, None), " "(None, 1, 1, None), (None, 2, 2, None), (None, 7, 7, None)]") expected_extracted_element = max_heap.heap[0].key assert max_heap.extract().key == expected_extracted_element expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] sorted_elements = [] for _ in range(8): sorted_elements.append(max_heap.extract().key) assert expected_sorted_elements == sorted_elements elements = [ TreeNode(7, 7), TreeNode(25, 25), TreeNode(100, 100), TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] min_heap = BinaryHeap(elements=elements, heap_property="min") expected_extracted_element = min_heap.heap[0].key assert min_heap.extract().key == expected_extracted_element expected_sorted_elements = [2, 3, 7, 17, 19, 25, 36, 100] sorted_elements = [min_heap.extract().key for _ in range(8)] assert expected_sorted_elements == sorted_elements
def test_TernaryHeap(): max_heap = TernaryHeap(heap_property="max") assert raises(IndexError, lambda: max_heap.extract()) max_heap.insert(100, 100) max_heap.insert(19, 19) max_heap.insert(36, 36) max_heap.insert(17, 17) max_heap.insert(3, 3) max_heap.insert(25, 25) max_heap.insert(1, 1) max_heap.insert(2, 2) max_heap.insert(7, 7) assert str(max_heap) == \ ('[(100, 100, [1, 2, 3]), (25, 25, [4, 5, 6]), ' '(36, 36, [7, 8]), (17, 17, []), ' '(3, 3, []), (19, 19, []), (1, 1, []), ' '(2, 2, []), (7, 7, [])]') assert max_heap.extract().key == 100 expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] sorted_elements = [] for _ in range(8): sorted_elements.append(max_heap.extract().key) assert expected_sorted_elements == sorted_elements elements = [ TreeNode(7, 7), TreeNode(25, 25), TreeNode(100, 100), TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] min_heap = TernaryHeap(elements=DynamicOneDimensionalArray( TreeNode, 9, elements), heap_property="min") expected_extracted_element = min_heap.heap[0].key assert min_heap.extract().key == expected_extracted_element expected_sorted_elements = [2, 3, 7, 17, 19, 25, 36, 100] sorted_elements = [min_heap.extract().key for _ in range(8)] assert expected_sorted_elements == sorted_elements
def test_DHeap(): assert raises(ValueError, lambda: DHeap(heap_property="none", d=4)) max_heap = DHeap(heap_property="max", d=5) assert max_heap.extract() is None max_heap.insert(100, 100) max_heap.insert(19, 19) max_heap.insert(36, 36) max_heap.insert(17, 17) max_heap.insert(3, 3) max_heap.insert(25, 25) max_heap.insert(1, 1) max_heap = DHeap(max_heap.heap, heap_property="max", d=4) max_heap.insert(2, 2) max_heap.insert(7, 7) assert str(max_heap) == \ ('[(100, 100, [1, 2, 3, 4]), (25, 25, [5, 6, 7, 8]), ' '(36, 36, []), (17, 17, []), (3, 3, []), (19, 19, []), ' '(1, 1, []), (2, 2, []), (7, 7, [])]') assert max_heap.extract().key == 100 expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] sorted_elements = [] for _ in range(8): sorted_elements.append(max_heap.extract().key) assert expected_sorted_elements == sorted_elements elements = [ TreeNode(7, 7), TreeNode(25, 25), TreeNode(100, 100), TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] min_heap = DHeap(elements=DynamicOneDimensionalArray( TreeNode, 9, elements), heap_property="min") assert min_heap.extract().key == 1 expected_sorted_elements = [2, 3, 7, 17, 19, 25, 36, 100] sorted_elements = [min_heap.extract().key for _ in range(8)] assert expected_sorted_elements == sorted_elements
def extract(self): """ Extract root element of the Heap. Returns ======= root_element : TreeNode The TreeNode at the root of the heap, if the heap is not empty. None If the heap is empty. """ if self._last_pos_filled == -1: raise IndexError("Heap is empty.") else: element_to_be_extracted = TreeNode(self.heap[0].key, self.heap[0].data) self._swap(0, self._last_pos_filled) self.heap.delete(self._last_pos_filled) self._last_pos_filled -= 1 self._heapify(0) return element_to_be_extracted
def test_AVLTree(): a = AVLTree('M', 'M') a.insert('N', 'N') a.insert('O', 'O') a.insert('L', 'L') a.insert('K', 'K') a.insert('Q', 'Q') a.insert('P', 'P') a.insert('H', 'H') a.insert('I', 'I') a.insert('A', 'A') assert str(a) == ("[(None, 'M', 'M', None), (8, 'N', 'N', 6), " "(None, 'O', 'O', None), (4, 'L', 'L', 0), " "(None, 'K', 'K', None), (None, 'Q', 'Q', None), " "(2, 'P', 'P', 5), (9, 'H', 'H', None), " "(7, 'I', 'I', 3), (None, 'A', 'A', None)]") assert [a.balance_factor(n) for n in a.tree if n is not None] == \ [0, -1, 0, 0, 0, 0, 0, -1, 0, 0] a1 = AVLTree(1, 1) a1.insert(2, 2) a1.insert(3, 3) a1.insert(4, 4) a1.insert(5, 5) assert str(a1) == ( "[(None, 1, 1, None), (0, 2, 2, 3), (None, 3, 3, None), " "(2, 4, 4, 4), (None, 5, 5, None)]") a3 = AVLTree(-1, 1) a3.insert(-2, 2) a3.insert(-3, 3) a3.insert(-4, 4) a3.insert(-5, 5) assert str(a3) == ("[(None, -1, 1, None), (3, -2, 2, 0), " "(None, -3, 3, None), (4, -4, 4, 2), " "(None, -5, 5, None)]") a2 = AVLTree() a2.insert(1, 1) a2.insert(1, 1) assert str(a2) == "[(None, 1, 1, None)]" a3 = AVLTree() a3.tree = ArrayForTrees(TreeNode, 0) for i in range(7): a3.tree.append(TreeNode(i, i)) a3.tree[0].left = 1 a3.tree[0].right = 6 a3.tree[1].left = 5 a3.tree[1].right = 2 a3.tree[2].left = 3 a3.tree[2].right = 4 a3._left_right_rotate(0, 1) assert str(a3) == ("[(4, 0, 0, 6), (5, 1, 1, 3), (1, 2, 2, 0), " "(None, 3, 3, None), (None, 4, 4, None), " "(None, 5, 5, None), (None, 6, 6, None)]") a4 = AVLTree() a4.tree = ArrayForTrees(TreeNode, 0) for i in range(7): a4.tree.append(TreeNode(i, i)) a4.tree[0].left = 1 a4.tree[0].right = 2 a4.tree[2].left = 3 a4.tree[2].right = 4 a4.tree[3].left = 5 a4.tree[3].right = 6 a4._right_left_rotate(0, 2) assert str(a4) == ("[(1, 0, 0, 5), (None, 1, 1, None), (6, 2, 2, 4), " "(0, 3, 3, 2), (None, 4, 4, None), (None, 5, 5, None), " "(None, 6, 6, None)]") a5 = AVLTree(is_order_statistic=True) a5.tree = ArrayForTrees(TreeNode, [ TreeNode(10, 10), TreeNode(5, 5), TreeNode(17, 17), TreeNode(2, 2), TreeNode(9, 9), TreeNode(12, 12), TreeNode(20, 20), TreeNode(3, 3), TreeNode(11, 11), TreeNode(15, 15), TreeNode(18, 18), TreeNode(30, 30), TreeNode(13, 13), TreeNode(33, 33) ]) a5.tree[0].left, a5.tree[0].right, a5.tree[0].parent, a5.tree[0].height = \ 1, 2, None, 4 a5.tree[1].left, a5.tree[1].right, a5.tree[1].parent, a5.tree[1].height = \ 3, 4, 0, 2 a5.tree[2].left, a5.tree[2].right, a5.tree[2].parent, a5.tree[2].height = \ 5, 6, 0, 3 a5.tree[3].left, a5.tree[3].right, a5.tree[3].parent, a5.tree[3].height = \ None, 7, 1, 1 a5.tree[4].left, a5.tree[4].right, a5.tree[4].parent, a5.tree[4].height = \ None, None, 1, 0 a5.tree[5].left, a5.tree[5].right, a5.tree[5].parent, a5.tree[5].height = \ 8, 9, 2, 2 a5.tree[6].left, a5.tree[6].right, a5.tree[6].parent, a5.tree[6].height = \ 10, 11, 2, 2 a5.tree[7].left, a5.tree[7].right, a5.tree[7].parent, a5.tree[7].height = \ None, None, 3, 0 a5.tree[8].left, a5.tree[8].right, a5.tree[8].parent, a5.tree[8].height = \ None, None, 5, 0 a5.tree[9].left, a5.tree[9].right, a5.tree[9].parent, a5.tree[9].height = \ 12, None, 5, 1 a5.tree[10].left, a5.tree[10].right, a5.tree[10].parent, a5.tree[10].height = \ None, None, 6, 0 a5.tree[11].left, a5.tree[11].right, a5.tree[11].parent, a5.tree[11].height = \ None, 13, 6, 1 a5.tree[12].left, a5.tree[12].right, a5.tree[12].parent, a5.tree[12].height = \ None, None, 9, 0 a5.tree[13].left, a5.tree[13].right, a5.tree[13].parent, a5.tree[13].height = \ None, None, 11, 0 # testing order statistics a5.tree[0].size = 14 a5.tree[1].size = 4 a5.tree[2].size = 9 a5.tree[3].size = 2 a5.tree[4].size = 1 a5.tree[5].size = 4 a5.tree[6].size = 4 a5.tree[7].size = 1 a5.tree[8].size = 1 a5.tree[9].size = 2 a5.tree[10].size = 1 a5.tree[11].size = 2 a5.tree[12].size = 1 a5.tree[13].size = 1 assert raises(ValueError, lambda: a5.select(0)) assert raises(ValueError, lambda: a5.select(15)) assert a5.rank(-1) is None def test_select_rank(expected_output): output = [] for i in range(len(expected_output)): output.append(a5.select(i + 1).key) assert output == expected_output output = [] expected_ranks = [i + 1 for i in range(len(expected_output))] for i in range(len(expected_output)): output.append(a5.rank(expected_output[i])) assert output == expected_ranks test_select_rank([2, 3, 5, 9, 10, 11, 12, 13, 15, 17, 18, 20, 30, 33]) a5.delete(9) a5.delete(13) a5.delete(20) assert str(a5) == ("[(7, 10, 10, 5), (None, 5, 5, None), " "(0, 17, 17, 6), (None, 2, 2, None), '', " "(8, 12, 12, 9), (10, 30, 30, 13), (3, 3, 3, 1), " "(None, 11, 11, None), (None, 15, 15, None), " "(None, 18, 18, None), '', '', (None, 33, 33, None)]") test_select_rank([2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33]) a5.delete(10) a5.delete(17) test_select_rank([2, 3, 5, 11, 12, 15, 18, 30, 33]) a5.delete(11) a5.delete(30) test_select_rank([2, 3, 5, 12, 15, 18, 33]) a5.delete(12) test_select_rank([2, 3, 5, 15, 18, 33]) a5.delete(15) test_select_rank([2, 3, 5, 18, 33]) a5.delete(18) test_select_rank([2, 3, 5, 33]) a5.delete(33) test_select_rank([2, 3, 5]) a5.delete(5) test_select_rank([2, 3]) a5.delete(3) test_select_rank([2]) a5.delete(2) test_select_rank([])
def test_BinaryHeap(): max_heap = BinaryHeap(heap_property="max") assert raises(IndexError, lambda: max_heap.extract()) max_heap.insert(100, 100) max_heap.insert(19, 19) max_heap.insert(36, 36) max_heap.insert(17, 17) max_heap.insert(3, 3) max_heap.insert(25, 25) max_heap.insert(1, 1) max_heap.insert(2, 2) max_heap.insert(7, 7) assert str(max_heap) == \ ("[(100, 100, [1, 2]), (19, 19, [3, 4]), " "(36, 36, [5, 6]), (17, 17, [7, 8]), " "(3, 3, []), (25, 25, []), (1, 1, []), " "(2, 2, []), (7, 7, [])]") assert max_heap.extract().key == 100 expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] l = max_heap.heap[0].left l = max_heap.heap[0].right sorted_elements = [] for _ in range(8): sorted_elements.append(max_heap.extract().key) assert expected_sorted_elements == sorted_elements elements = [ TreeNode(7, 7), TreeNode(25, 25), TreeNode(100, 100), TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] min_heap = BinaryHeap(elements=DynamicOneDimensionalArray( TreeNode, 9, elements), heap_property="min") assert min_heap.extract().key == 1 expected_sorted_elements = [2, 3, 7, 17, 19, 25, 36, 100] sorted_elements = [min_heap.extract().key for _ in range(8)] assert expected_sorted_elements == sorted_elements non_TreeNode_elements = [(7, 7), TreeNode(25, 25), TreeNode(100, 100), TreeNode(1, 1), (2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36)] assert raises( ValueError, lambda: BinaryHeap(elements=non_TreeNode_elements, heap_property='min'))
def test_AVLTree(): a = AVLTree('M', 'M') a.insert('N', 'N') a.insert('O', 'O') a.insert('L', 'L') a.insert('K', 'K') a.insert('Q', 'Q') a.insert('P', 'P') a.insert('H', 'H') a.insert('I', 'I') a.insert('A', 'A') trav = BinaryTreeTraversal(a) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order ] == ['A', 'H', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'] assert [node.key for node in pre_order ] == ['N', 'I', 'H', 'A', 'L', 'K', 'M', 'P', 'O', 'Q'] assert [a.balance_factor(n) for n in a.tree if n is not None] == \ [0, -1, 0, 0, 0, 0, 0, -1, 0, 0] a1 = AVLTree(1, 1) a1.insert(2, 2) a1.insert(3, 3) a1.insert(4, 4) a1.insert(5, 5) trav = BinaryTreeTraversal(a1) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [1, 2, 3, 4, 5] assert [node.key for node in pre_order] == [2, 1, 4, 3, 5] a3 = AVLTree(-1, 1) a3.insert(-2, 2) a3.insert(-3, 3) a3.insert(-4, 4) a3.insert(-5, 5) trav = BinaryTreeTraversal(a3) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [-5, -4, -3, -2, -1] assert [node.key for node in pre_order] == [-2, -4, -5, -3, -1] a2 = AVLTree() a2.insert(1, 1) a2.insert(1, 1) trav = BinaryTreeTraversal(a2) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [1] assert [node.key for node in pre_order] == [1] a3 = AVLTree() a3.tree = ArrayForTrees(TreeNode, 0) for i in range(7): a3.tree.append(TreeNode(i, i)) a3.tree[0].left = 1 a3.tree[0].right = 6 a3.tree[1].left = 5 a3.tree[1].right = 2 a3.tree[2].left = 3 a3.tree[2].right = 4 a3._left_right_rotate(0, 1) trav = BinaryTreeTraversal(a3) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [5, 1, 3, 2, 4, 0, 6] assert [node.key for node in pre_order] == [2, 1, 5, 3, 0, 4, 6] a4 = AVLTree() a4.tree = ArrayForTrees(TreeNode, 0) for i in range(7): a4.tree.append(TreeNode(i, i)) a4.tree[0].left = 1 a4.tree[0].right = 2 a4.tree[2].left = 3 a4.tree[2].right = 4 a4.tree[3].left = 5 a4.tree[3].right = 6 a4._right_left_rotate(0, 2) trav = BinaryTreeTraversal(a4) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [1, 0, 5, 3, 6, 2, 4] assert [node.key for node in pre_order] == [3, 0, 1, 5, 2, 6, 4] a5 = AVLTree(is_order_statistic=True) a5.tree = ArrayForTrees(TreeNode, [ TreeNode(10, 10), TreeNode(5, 5), TreeNode(17, 17), TreeNode(2, 2), TreeNode(9, 9), TreeNode(12, 12), TreeNode(20, 20), TreeNode(3, 3), TreeNode(11, 11), TreeNode(15, 15), TreeNode(18, 18), TreeNode(30, 30), TreeNode(13, 13), TreeNode(33, 33) ]) a5.tree[0].left, a5.tree[0].right, a5.tree[0].parent, a5.tree[0].height = \ 1, 2, None, 4 a5.tree[1].left, a5.tree[1].right, a5.tree[1].parent, a5.tree[1].height = \ 3, 4, 0, 2 a5.tree[2].left, a5.tree[2].right, a5.tree[2].parent, a5.tree[2].height = \ 5, 6, 0, 3 a5.tree[3].left, a5.tree[3].right, a5.tree[3].parent, a5.tree[3].height = \ None, 7, 1, 1 a5.tree[4].left, a5.tree[4].right, a5.tree[4].parent, a5.tree[4].height = \ None, None, 1, 0 a5.tree[5].left, a5.tree[5].right, a5.tree[5].parent, a5.tree[5].height = \ 8, 9, 2, 2 a5.tree[6].left, a5.tree[6].right, a5.tree[6].parent, a5.tree[6].height = \ 10, 11, 2, 2 a5.tree[7].left, a5.tree[7].right, a5.tree[7].parent, a5.tree[7].height = \ None, None, 3, 0 a5.tree[8].left, a5.tree[8].right, a5.tree[8].parent, a5.tree[8].height = \ None, None, 5, 0 a5.tree[9].left, a5.tree[9].right, a5.tree[9].parent, a5.tree[9].height = \ 12, None, 5, 1 a5.tree[10].left, a5.tree[10].right, a5.tree[10].parent, a5.tree[10].height = \ None, None, 6, 0 a5.tree[11].left, a5.tree[11].right, a5.tree[11].parent, a5.tree[11].height = \ None, 13, 6, 1 a5.tree[12].left, a5.tree[12].right, a5.tree[12].parent, a5.tree[12].height = \ None, None, 9, 0 a5.tree[13].left, a5.tree[13].right, a5.tree[13].parent, a5.tree[13].height = \ None, None, 11, 0 # testing order statistics a5.tree[0].size = 14 a5.tree[1].size = 4 a5.tree[2].size = 9 a5.tree[3].size = 2 a5.tree[4].size = 1 a5.tree[5].size = 4 a5.tree[6].size = 4 a5.tree[7].size = 1 a5.tree[8].size = 1 a5.tree[9].size = 2 a5.tree[10].size = 1 a5.tree[11].size = 2 a5.tree[12].size = 1 a5.tree[13].size = 1 assert raises(ValueError, lambda: a5.select(0)) assert raises(ValueError, lambda: a5.select(15)) assert a5.rank(-1) is None def test_select_rank(expected_output): output = [] for i in range(len(expected_output)): output.append(a5.select(i + 1).key) assert output == expected_output output = [] expected_ranks = [i + 1 for i in range(len(expected_output))] for i in range(len(expected_output)): output.append(a5.rank(expected_output[i])) assert output == expected_ranks test_select_rank([2, 3, 5, 9, 10, 11, 12, 13, 15, 17, 18, 20, 30, 33]) a5.delete(9) a5.delete(13) a5.delete(20) trav = BinaryTreeTraversal(a5) in_order = trav.depth_first_search(order='in_order') pre_order = trav.depth_first_search(order='pre_order') assert [node.key for node in in_order] == [2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33] assert [node.key for node in pre_order ] == [17, 10, 3, 2, 5, 12, 11, 15, 30, 18, 33] test_select_rank([2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33]) a5.delete(10) a5.delete(17) test_select_rank([2, 3, 5, 11, 12, 15, 18, 30, 33]) a5.delete(11) a5.delete(30) test_select_rank([2, 3, 5, 12, 15, 18, 33]) a5.delete(12) test_select_rank([2, 3, 5, 15, 18, 33]) a5.delete(15) test_select_rank([2, 3, 5, 18, 33]) a5.delete(18) test_select_rank([2, 3, 5, 33]) a5.delete(33) test_select_rank([2, 3, 5]) a5.delete(5) test_select_rank([2, 3]) a5.delete(3) test_select_rank([2]) a5.delete(2) test_select_rank([])