From accee3e598e45d33d5b8022c646126adc507efe4 Mon Sep 17 00:00:00 2001 From: prshnt19 Date: Tue, 3 Mar 2020 02:57:25 +0530 Subject: [PATCH 1/7] DHeap added --- pydatastructs/trees/__init__.py | 1 + pydatastructs/trees/heaps.py | 178 ++++++++++++++++++++++++ pydatastructs/trees/tests/test_heaps.py | 43 +++++- 3 files changed, 221 insertions(+), 1 deletion(-) diff --git a/pydatastructs/trees/__init__.py b/pydatastructs/trees/__init__.py index 5f110bf0c..682d604b2 100644 --- a/pydatastructs/trees/__init__.py +++ b/pydatastructs/trees/__init__.py @@ -17,6 +17,7 @@ from .heaps import ( BinaryHeap, + DHeap, BinomialHeap ) __all__.extend(heaps.__all__) diff --git a/pydatastructs/trees/heaps.py b/pydatastructs/trees/heaps.py index 66f7f4b7b..4265e9e54 100644 --- a/pydatastructs/trees/heaps.py +++ b/pydatastructs/trees/heaps.py @@ -5,6 +5,7 @@ __all__ = [ 'BinaryHeap', + 'DHeap', 'BinomialHeap' ] @@ -186,6 +187,183 @@ def __str__(self): return str(to_be_printed) +class DHeap(Heap): + """ + Represents D-ary Heap. + + Parameters + ========== + + elements : list, tuple + Optional, by default 'None'. + List/tuple of initial elements in Heap. + + heap_property : str + The property of binary heap. + If the key stored in each node is + either greater than or equal to + the keys in the node's children + then pass 'max'. + If the key stored in each node is + either less than or equal to + the keys in the node's children + then pass 'min'. + By default, the heap property is + set to 'min'. + + Examples + ======== + + >>> from pydatastructs.trees.heaps import DHeap + >>> min_heap = DHeap(heap_property="min",d=3) + >>> min_heap.insert(1, 1) + >>> min_heap.insert(5, 5) + >>> min_heap.insert(7, 7) + >>> min_heap.extract().key + 1 + >>> min_heap.insert(4, 4) + >>> min_heap.extract().key + 4 + + >>> max_heap = BinaryHeap(heap_property='max') + >>> max_heap.insert(1, 1) + >>> max_heap.insert(5, 5) + >>> max_heap.insert(7, 7) + >>> max_heap.extract().key + 7 + >>> max_heap.insert(6, 6) + >>> max_heap.extract().key + 6 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/D-ary_heap + """ + __slots__ = ['_comp', 'heap', 'm', 'heap_property', '_last_pos_filled'] + + def __new__(cls, elements=None, heap_property="min", d=3): + obj = Heap.__new__(cls) + obj.heap_property = heap_property + obj.d = d + if heap_property == "min": + obj._comp = lambda key_parent, key_child: key_parent <= key_child + elif heap_property == "max": + obj._comp = lambda key_parent, key_child: key_parent >= key_child + else: + raise ValueError("%s is invalid heap property"%(heap_property)) + if elements is None: + elements = [] + obj.heap = elements + obj._last_pos_filled = len(elements) - 1 + obj._build() + return obj + + def _build(self): + for i in range(self._last_pos_filled + 1): + self.heap[i].left, self.heap[i].right = \ + self.d*i + 1, self.d*i + self.d + for i in range((self._last_pos_filled + 1)//self.d, -1, -1): + self._heapify(i) + + def _swap(self, idx1, idx2): + idx1_key, idx1_data = \ + self.heap[idx1].key, self.heap[idx1].data + self.heap[idx1].key, self.heap[idx1].data = \ + self.heap[idx2].key, self.heap[idx2].data + self.heap[idx2].key, self.heap[idx2].data = \ + idx1_key, idx1_data + + def _heapify(self, i): + while True: + target = i + l = self.d*i + 1 + r = self.d*i + self.d + + for j in range(l, r+1): + if j <= self._last_pos_filled: + target = j if self._comp(self.heap[j].key, self.heap[target].key) \ + else target + else: + break + + if target != i: + self._swap(target, i) + i = target + else: + break + + def insert(self, key, data): + """ + 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].left, self.heap[i].right = 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 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 __str__(self): + to_be_printed = ['' for i in range(self._last_pos_filled + 1)] + for i in range(self._last_pos_filled + 1): + node = self.heap[i] + if node.left <= self._last_pos_filled: + if node.right <= self._last_pos_filled: + children = [x for x in range(node.left, node.right + 1)] + else: + children = [x for x in range(node.left, self._last_pos_filled + 1)] + else: + children = [] + to_be_printed[i] = (node.key, node.data, children) + return str(to_be_printed) + + class BinomialHeap(Heap): """ Represents binomial heap. diff --git a/pydatastructs/trees/tests/test_heaps.py b/pydatastructs/trees/tests/test_heaps.py index 5c455f86c..66d84c01e 100644 --- a/pydatastructs/trees/tests/test_heaps.py +++ b/pydatastructs/trees/tests/test_heaps.py @@ -1,4 +1,4 @@ -from pydatastructs.trees.heaps import BinaryHeap, BinomialHeap +from pydatastructs.trees.heaps import BinaryHeap, BinomialHeap, DHeap from pydatastructs.miscellaneous_data_structures.binomial_trees import BinomialTree from pydatastructs.utils.misc_util import TreeNode, BinomialTreeNode from pydatastructs.utils.raises_util import raises @@ -47,6 +47,47 @@ def test_BinaryHeap(): sorted_elements = [min_heap.extract().key for _ in range(8)] assert expected_sorted_elements == sorted_elements +def test_DHeap(): + # assert raises(ValueError, DHeap(heap_property="none", d=3)) + max_heap = DHeap(heap_property="max", d=3) + 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) == \ + ('[(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, [])]') + + 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_BinomialHeap(): # Corner cases From f994cb465e97d7700171ff51ba9cc90420faa9e3 Mon Sep 17 00:00:00 2001 From: prshnt19 Date: Wed, 4 Mar 2020 12:51:07 +0530 Subject: [PATCH 2/7] BinaryHeap and TernaryHeap as Child of DHeap --- .gitignore | 1 + pydatastructs/trees/__init__.py | 1 + pydatastructs/trees/heaps.py | 224 +++++++++--------------- pydatastructs/trees/tests/test_heaps.py | 55 +++++- 4 files changed, 135 insertions(+), 146 deletions(-) diff --git a/.gitignore b/.gitignore index 52b147513..675b4b466 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ htmlcov *~ __pycache__/ .pytest_cache/ +.idea/ # Backup Files # ################ diff --git a/pydatastructs/trees/__init__.py b/pydatastructs/trees/__init__.py index 682d604b2..456dc7589 100644 --- a/pydatastructs/trees/__init__.py +++ b/pydatastructs/trees/__init__.py @@ -17,6 +17,7 @@ from .heaps import ( BinaryHeap, + TernaryHeap, DHeap, BinomialHeap ) diff --git a/pydatastructs/trees/heaps.py b/pydatastructs/trees/heaps.py index 4265e9e54..96a70328b 100644 --- a/pydatastructs/trees/heaps.py +++ b/pydatastructs/trees/heaps.py @@ -5,6 +5,7 @@ __all__ = [ 'BinaryHeap', + 'TernaryHeap', 'DHeap', 'BinomialHeap' ] @@ -15,9 +16,10 @@ class Heap(object): """ pass -class BinaryHeap(Heap): + +class DHeap(Heap): """ - Represents Binary Heap. + Represents D-ary Heap. Parameters ========== @@ -42,8 +44,8 @@ class BinaryHeap(Heap): Examples ======== - >>> from pydatastructs.trees.heaps import BinaryHeap - >>> min_heap = BinaryHeap(heap_property="min") + >>> from pydatastructs.trees.heaps import DHeap + >>> min_heap = DHeap(heap_property="min",d=3) >>> min_heap.insert(1, 1) >>> min_heap.insert(5, 5) >>> min_heap.insert(7, 7) @@ -66,13 +68,14 @@ class BinaryHeap(Heap): References ========== - .. [1] https://en.m.wikipedia.org/wiki/Binary_heap + .. [1] https://en.wikipedia.org/wiki/D-ary_heap """ - __slots__ = ['_comp', 'heap', 'heap_property', '_last_pos_filled'] + __slots__ = ['_comp', 'heap', 'm', 'heap_property', '_last_pos_filled'] - def __new__(cls, elements=None, heap_property="min"): + def __new__(cls, elements=None, heap_property="min", d=3): obj = Heap.__new__(cls) obj.heap_property = heap_property + obj.d = d if heap_property == "min": obj._comp = lambda key_parent, key_child: key_parent <= key_child elif heap_property == "max": @@ -89,8 +92,8 @@ def __new__(cls, elements=None, heap_property="min"): def _build(self): for i in range(self._last_pos_filled + 1): self.heap[i].left, self.heap[i].right = \ - 2*i + 1, 2*i + 2 - for i in range((self._last_pos_filled + 1)//2, -1, -1): + self.d*i + 1, self.d*i + self.d + for i in range((self._last_pos_filled + 1)//self.d, -1, -1): self._heapify(i) def _swap(self, idx1, idx2): @@ -104,15 +107,15 @@ def _swap(self, idx1, idx2): def _heapify(self, i): while True: target = i - l = 2*i + 1 - r = 2*i + 2 + l = self.d*i + 1 + r = self.d*i + self.d - if l <= self._last_pos_filled: - target = l if self._comp(self.heap[l].key, self.heap[target].key) \ - else i - if r <= self._last_pos_filled: - target = r if self._comp(self.heap[r].key, self.heap[target].key) \ - else target + for j in range(l, r+1): + if j <= self._last_pos_filled: + target = j if self._comp(self.heap[j].key, self.heap[target].key) \ + else target + else: + break if target != i: self._swap(target, i) @@ -120,7 +123,6 @@ def _heapify(self, i): else: break - def insert(self, key, data): """ Insert a new element to the heap according to heap property. @@ -142,10 +144,10 @@ def insert(self, key, data): self.heap.append(new_node) self._last_pos_filled += 1 i = self._last_pos_filled - self.heap[i].left, self.heap[i].right = 2*i + 1, 2*i + 2 + self.heap[i].left, self.heap[i].right = self.d*i + 1, self.d*i + self.d while True: - parent = (i - 1)//2 + parent = (i - 1)//self.d if i == 0 or self._comp(self.heap[parent].key, self.heap[i].key): break else: @@ -181,15 +183,20 @@ def __str__(self): to_be_printed = ['' for i in range(self._last_pos_filled + 1)] for i in range(self._last_pos_filled + 1): node = self.heap[i] - to_be_printed[i] = (node.left if node.left <= self._last_pos_filled else None, - node.key, node.data, - node.right if node.right <= self._last_pos_filled else None) + if node.left <= self._last_pos_filled: + if node.right <= self._last_pos_filled: + children = [x for x in range(node.left, node.right + 1)] + else: + children = [x for x in range(node.left, self._last_pos_filled + 1)] + else: + children = [] + to_be_printed[i] = (node.key, node.data, children) return str(to_be_printed) -class DHeap(Heap): +class BinaryHeap(DHeap): """ - Represents D-ary Heap. + Represents Binary Heap. Parameters ========== @@ -214,8 +221,8 @@ class DHeap(Heap): Examples ======== - >>> from pydatastructs.trees.heaps import DHeap - >>> min_heap = DHeap(heap_property="min",d=3) + >>> from pydatastructs.trees.heaps import BinaryHeap + >>> min_heap = BinaryHeap(heap_property="min") >>> min_heap.insert(1, 1) >>> min_heap.insert(5, 5) >>> min_heap.insert(7, 7) @@ -238,130 +245,69 @@ class DHeap(Heap): References ========== - .. [1] https://en.wikipedia.org/wiki/D-ary_heap + .. [1] https://en.m.wikipedia.org/wiki/Binary_heap """ - __slots__ = ['_comp', 'heap', 'm', 'heap_property', '_last_pos_filled'] - - def __new__(cls, elements=None, heap_property="min", d=3): - obj = Heap.__new__(cls) - obj.heap_property = heap_property - obj.d = d - if heap_property == "min": - obj._comp = lambda key_parent, key_child: key_parent <= key_child - elif heap_property == "max": - obj._comp = lambda key_parent, key_child: key_parent >= key_child - else: - raise ValueError("%s is invalid heap property"%(heap_property)) - if elements is None: - elements = [] - obj.heap = elements - obj._last_pos_filled = len(elements) - 1 - obj._build() + def __new__(cls, elements=None, heap_property="min"): + obj = DHeap.__new__(cls, elements, heap_property, 2) return obj - def _build(self): - for i in range(self._last_pos_filled + 1): - self.heap[i].left, self.heap[i].right = \ - self.d*i + 1, self.d*i + self.d - for i in range((self._last_pos_filled + 1)//self.d, -1, -1): - self._heapify(i) - - def _swap(self, idx1, idx2): - idx1_key, idx1_data = \ - self.heap[idx1].key, self.heap[idx1].data - self.heap[idx1].key, self.heap[idx1].data = \ - self.heap[idx2].key, self.heap[idx2].data - self.heap[idx2].key, self.heap[idx2].data = \ - idx1_key, idx1_data - - def _heapify(self, i): - while True: - target = i - l = self.d*i + 1 - r = self.d*i + self.d - - for j in range(l, r+1): - if j <= self._last_pos_filled: - target = j if self._comp(self.heap[j].key, self.heap[target].key) \ - else target - else: - break - if target != i: - self._swap(target, i) - i = target - else: - break - - def insert(self, key, data): - """ - Insert a new element to the heap according to heap property. - - Parameters - ========== +class TernaryHeap(DHeap): + """ + Represents Ternary Heap. - key - The key for comparison. - data - The data to be inserted. + Parameters + ========== - Returns - ======= + elements : list, tuple + Optional, by default 'None'. + List/tuple of initial elements in Heap. - None - """ - new_node = TreeNode(key, data) - self.heap.append(new_node) - self._last_pos_filled += 1 - i = self._last_pos_filled - self.heap[i].left, self.heap[i].right = self.d*i + 1, self.d*i + self.d + heap_property : str + The property of binary heap. + If the key stored in each node is + either greater than or equal to + the keys in the node's children + then pass 'max'. + If the key stored in each node is + either less than or equal to + the keys in the node's children + then pass 'min'. + By default, the heap property is + set to 'min'. - 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 + Examples + ======== - def extract(self): - """ - Extract root element of the Heap. + >>> from pydatastructs.trees.heaps import BinaryHeap + >>> min_heap = BinaryHeap(heap_property="min") + >>> min_heap.insert(1, 1) + >>> min_heap.insert(5, 5) + >>> min_heap.insert(7, 7) + >>> min_heap.extract().key + 1 + >>> min_heap.insert(4, 4) + >>> min_heap.extract().key + 4 - Returns - ======= + >>> max_heap = BinaryHeap(heap_property='max') + >>> max_heap.insert(1, 1) + >>> max_heap.insert(5, 5) + >>> max_heap.insert(7, 7) + >>> max_heap.extract().key + 7 + >>> max_heap.insert(6, 6) + >>> max_heap.extract().key + 6 - 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 + References + ========== - def __str__(self): - to_be_printed = ['' for i in range(self._last_pos_filled + 1)] - for i in range(self._last_pos_filled + 1): - node = self.heap[i] - if node.left <= self._last_pos_filled: - if node.right <= self._last_pos_filled: - children = [x for x in range(node.left, node.right + 1)] - else: - children = [x for x in range(node.left, self._last_pos_filled + 1)] - else: - children = [] - to_be_printed[i] = (node.key, node.data, children) - return str(to_be_printed) + .. [1] https://en.wikipedia.org/wiki/D-ary_heap + """ + def __new__(cls, elements=None, heap_property="min"): + obj = DHeap.__new__(cls, elements, heap_property, 3) + return obj class BinomialHeap(Heap): diff --git a/pydatastructs/trees/tests/test_heaps.py b/pydatastructs/trees/tests/test_heaps.py index 66d84c01e..5fcd46258 100644 --- a/pydatastructs/trees/tests/test_heaps.py +++ b/pydatastructs/trees/tests/test_heaps.py @@ -1,4 +1,4 @@ -from pydatastructs.trees.heaps import BinaryHeap, BinomialHeap, DHeap +from pydatastructs.trees.heaps import BinaryHeap, TernaryHeap, BinomialHeap, DHeap from pydatastructs.miscellaneous_data_structures.binomial_trees import BinomialTree from pydatastructs.utils.misc_util import TreeNode, BinomialTreeNode from pydatastructs.utils.raises_util import raises @@ -20,10 +20,10 @@ def test_BinaryHeap(): 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)]") + ("[(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, [])]") expected_extracted_element = max_heap.heap[0].key assert max_heap.extract().key == expected_extracted_element @@ -47,9 +47,49 @@ def test_BinaryHeap(): 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 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) == \ + ('[(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, [])]') + + 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_DHeap(): - # assert raises(ValueError, DHeap(heap_property="none", d=3)) - max_heap = DHeap(heap_property="max", d=3) + assert raises(ValueError, lambda: DHeap(heap_property="none", d=3)) + max_heap = DHeap(heap_property="max", d=4) assert max_heap.extract() is None max_heap.insert(100, 100) max_heap.insert(19, 19) @@ -58,6 +98,7 @@ def test_DHeap(): 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=3) max_heap.insert(2, 2) max_heap.insert(7, 7) assert str(max_heap) == \ From 7bc73560c42bcbfcf2c69a3ad758464a5f6c6dee Mon Sep 17 00:00:00 2001 From: prshnt19 Date: Thu, 5 Mar 2020 15:54:25 +0530 Subject: [PATCH 3/7] Docstring updated --- .gitignore | 1 - pydatastructs/trees/heaps.py | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 675b4b466..52b147513 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,6 @@ htmlcov *~ __pycache__/ .pytest_cache/ -.idea/ # Backup Files # ################ diff --git a/pydatastructs/trees/heaps.py b/pydatastructs/trees/heaps.py index 96a70328b..0a132e2c4 100644 --- a/pydatastructs/trees/heaps.py +++ b/pydatastructs/trees/heaps.py @@ -29,7 +29,6 @@ class DHeap(Heap): List/tuple of initial elements in Heap. heap_property : str - The property of binary heap. If the key stored in each node is either greater than or equal to the keys in the node's children @@ -45,7 +44,7 @@ class DHeap(Heap): ======== >>> from pydatastructs.trees.heaps import DHeap - >>> min_heap = DHeap(heap_property="min",d=3) + >>> min_heap = DHeap(heap_property="min", d=3) >>> min_heap.insert(1, 1) >>> min_heap.insert(5, 5) >>> min_heap.insert(7, 7) @@ -55,7 +54,7 @@ class DHeap(Heap): >>> min_heap.extract().key 4 - >>> max_heap = BinaryHeap(heap_property='max') + >>> max_heap = DHeap(heap_property='max', d=2) >>> max_heap.insert(1, 1) >>> max_heap.insert(5, 5) >>> max_heap.insert(7, 7) @@ -206,7 +205,6 @@ class BinaryHeap(DHeap): List/tuple of initial elements in Heap. heap_property : str - The property of binary heap. If the key stored in each node is either greater than or equal to the keys in the node's children @@ -264,7 +262,6 @@ class TernaryHeap(DHeap): List/tuple of initial elements in Heap. heap_property : str - The property of binary heap. If the key stored in each node is either greater than or equal to the keys in the node's children @@ -279,8 +276,8 @@ class TernaryHeap(DHeap): Examples ======== - >>> from pydatastructs.trees.heaps import BinaryHeap - >>> min_heap = BinaryHeap(heap_property="min") + >>> from pydatastructs.trees.heaps import TernaryHeap + >>> min_heap = TernaryHeap(heap_property="min") >>> min_heap.insert(1, 1) >>> min_heap.insert(5, 5) >>> min_heap.insert(7, 7) @@ -290,7 +287,7 @@ class TernaryHeap(DHeap): >>> min_heap.extract().key 4 - >>> max_heap = BinaryHeap(heap_property='max') + >>> max_heap = TernaryHeap(heap_property='max') >>> max_heap.insert(1, 1) >>> max_heap.insert(5, 5) >>> max_heap.insert(7, 7) From 6ad68dc8c95145bd2af6ea829f6d6bd16b7ea882 Mon Sep 17 00:00:00 2001 From: prshnt19 Date: Sun, 8 Mar 2020 23:28:25 +0530 Subject: [PATCH 4/7] heaps and tests updated --- pydatastructs/trees/heaps.py | 8 +++++--- pydatastructs/trees/tests/test_heaps.py | 26 +++++++++++-------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/pydatastructs/trees/heaps.py b/pydatastructs/trees/heaps.py index 0a132e2c4..819f8603f 100644 --- a/pydatastructs/trees/heaps.py +++ b/pydatastructs/trees/heaps.py @@ -69,9 +69,9 @@ class DHeap(Heap): .. [1] https://en.wikipedia.org/wiki/D-ary_heap """ - __slots__ = ['_comp', 'heap', 'm', 'heap_property', '_last_pos_filled'] + __slots__ = ['_comp', 'heap', 'd', 'heap_property', '_last_pos_filled'] - def __new__(cls, elements=None, heap_property="min", d=3): + def __new__(cls, elements=None, heap_property="min", d=4): obj = Heap.__new__(cls) obj.heap_property = heap_property obj.d = d @@ -281,16 +281,18 @@ class TernaryHeap(DHeap): >>> min_heap.insert(1, 1) >>> min_heap.insert(5, 5) >>> min_heap.insert(7, 7) + >>> min_heap.insert(3, 3) >>> min_heap.extract().key 1 >>> min_heap.insert(4, 4) >>> min_heap.extract().key - 4 + 3 >>> max_heap = TernaryHeap(heap_property='max') >>> max_heap.insert(1, 1) >>> max_heap.insert(5, 5) >>> max_heap.insert(7, 7) + >>> min_heap.insert(3, 3) >>> max_heap.extract().key 7 >>> max_heap.insert(6, 6) diff --git a/pydatastructs/trees/tests/test_heaps.py b/pydatastructs/trees/tests/test_heaps.py index 5fcd46258..49eaa291e 100644 --- a/pydatastructs/trees/tests/test_heaps.py +++ b/pydatastructs/trees/tests/test_heaps.py @@ -40,8 +40,7 @@ def test_BinaryHeap(): 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 + 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)] @@ -65,8 +64,7 @@ def test_TernaryHeap(): '(3, 3, []), (19, 19, []), (1, 1, []), ' '(2, 2, []), (7, 7, [])]') - expected_extracted_element = max_heap.heap[0].key - assert max_heap.extract().key == expected_extracted_element + assert max_heap.extract().key == 100 expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] sorted_elements = [] @@ -79,7 +77,7 @@ def test_TernaryHeap(): 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") + min_heap = TernaryHeap(elements=elements, heap_property="min") expected_extracted_element = min_heap.heap[0].key assert min_heap.extract().key == expected_extracted_element @@ -88,8 +86,8 @@ def test_TernaryHeap(): assert expected_sorted_elements == sorted_elements def test_DHeap(): - assert raises(ValueError, lambda: DHeap(heap_property="none", d=3)) - max_heap = DHeap(heap_property="max", d=4) + 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) @@ -98,14 +96,13 @@ def test_DHeap(): 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=3) + 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]), (25, 25, [4, 5, 6]), ' - '(36, 36, [7, 8]), (17, 17, []), ' - '(3, 3, []), (19, 19, []), (1, 1, []), ' - '(2, 2, []), (7, 7, [])]') + ('[(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, [])]') expected_extracted_element = max_heap.heap[0].key assert max_heap.extract().key == expected_extracted_element @@ -121,9 +118,8 @@ def test_DHeap(): 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 + min_heap = DHeap(elements=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)] From f92735de98fa8bc82111225f5117e98d32ffb4ae Mon Sep 17 00:00:00 2001 From: prshnt19 Date: Tue, 10 Mar 2020 03:41:07 +0530 Subject: [PATCH 5/7] Heaps uses DynamicOneDimensionalArray --- .../linear_data_structures/arrays.py | 1 + pydatastructs/trees/heaps.py | 23 +++++++++---------- pydatastructs/trees/tests/test_heaps.py | 15 ++++++------ 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 980aab92b..322361c43 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -255,6 +255,7 @@ def delete(self, idx): def size(self): return self._size + class ArrayForTrees(DynamicOneDimensionalArray): """ Utility dynamic array for storing nodes of a tree. diff --git a/pydatastructs/trees/heaps.py b/pydatastructs/trees/heaps.py index 819f8603f..3fef1a642 100644 --- a/pydatastructs/trees/heaps.py +++ b/pydatastructs/trees/heaps.py @@ -82,15 +82,15 @@ def __new__(cls, elements=None, heap_property="min", d=4): else: raise ValueError("%s is invalid heap property"%(heap_property)) if elements is None: - elements = [] + elements = DynamicOneDimensionalArray(TreeNode, 0) obj.heap = elements - obj._last_pos_filled = len(elements) - 1 + obj._last_pos_filled = obj.heap._last_pos_filled obj._build() return obj def _build(self): for i in range(self._last_pos_filled + 1): - self.heap[i].left, self.heap[i].right = \ + self.heap[i]._leftmost, self.heap[i]._rightmost = \ self.d*i + 1, self.d*i + self.d for i in range((self._last_pos_filled + 1)//self.d, -1, -1): self._heapify(i) @@ -143,7 +143,7 @@ def insert(self, key, data): self.heap.append(new_node) self._last_pos_filled += 1 i = self._last_pos_filled - self.heap[i].left, self.heap[i].right = self.d*i + 1, self.d*i + self.d + self.heap[i]._leftmost, self.heap[i]._rightmost = self.d*i + 1, self.d*i + self.d while True: parent = (i - 1)//self.d @@ -171,22 +171,20 @@ def extract(self): 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.heap.delete(self._last_pos_filled) self._last_pos_filled -= 1 + self._heapify(0) return element_to_be_extracted def __str__(self): to_be_printed = ['' for i in range(self._last_pos_filled + 1)] for i in range(self._last_pos_filled + 1): node = self.heap[i] - if node.left <= self._last_pos_filled: - if node.right <= self._last_pos_filled: - children = [x for x in range(node.left, node.right + 1)] + if node._leftmost <= self._last_pos_filled: + if node._rightmost <= self._last_pos_filled: + children = [x for x in range(node._leftmost, node._rightmost + 1)] else: - children = [x for x in range(node.left, self._last_pos_filled + 1)] + children = [x for x in range(node._leftmost, self._last_pos_filled + 1)] else: children = [] to_be_printed[i] = (node.key, node.data, children) @@ -303,6 +301,7 @@ class TernaryHeap(DHeap): ========== .. [1] https://en.wikipedia.org/wiki/D-ary_heap + .. [2] https://ece.uwaterloo.ca/~dwharder/aads/Algorithms/d-ary_heaps/Ternary_heaps/ """ def __new__(cls, elements=None, heap_property="min"): obj = DHeap.__new__(cls, elements, heap_property, 3) diff --git a/pydatastructs/trees/tests/test_heaps.py b/pydatastructs/trees/tests/test_heaps.py index 49eaa291e..bb2f384bd 100644 --- a/pydatastructs/trees/tests/test_heaps.py +++ b/pydatastructs/trees/tests/test_heaps.py @@ -1,4 +1,5 @@ from pydatastructs.trees.heaps import BinaryHeap, TernaryHeap, BinomialHeap, DHeap +from pydatastructs.linear_data_structures.arrays import DynamicOneDimensionalArray from pydatastructs.miscellaneous_data_structures.binomial_trees import BinomialTree from pydatastructs.utils.misc_util import TreeNode, BinomialTreeNode from pydatastructs.utils.raises_util import raises @@ -25,10 +26,11 @@ def test_BinaryHeap(): "(3, 3, []), (25, 25, []), (1, 1, []), " "(2, 2, []), (7, 7, [])]") - expected_extracted_element = max_heap.heap[0].key - assert max_heap.extract().key == expected_extracted_element + 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) @@ -39,7 +41,7 @@ def test_BinaryHeap(): 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") + 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] @@ -77,7 +79,7 @@ def test_TernaryHeap(): TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] - min_heap = TernaryHeap(elements=elements, heap_property="min") + 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 @@ -104,8 +106,7 @@ def test_DHeap(): '(36, 36, []), (17, 17, []), (3, 3, []), (19, 19, []), ' '(1, 1, []), (2, 2, []), (7, 7, [])]') - expected_extracted_element = max_heap.heap[0].key - assert max_heap.extract().key == expected_extracted_element + assert max_heap.extract().key == 100 expected_sorted_elements = [36, 25, 19, 17, 7, 3, 2, 1] sorted_elements = [] @@ -118,7 +119,7 @@ def test_DHeap(): TreeNode(1, 1), TreeNode(2, 2), TreeNode(3, 3), TreeNode(17, 17), TreeNode(19, 19), TreeNode(36, 36) ] - min_heap = DHeap(elements=elements, heap_property="min") + 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] From bf6cc996f8ec942a4f716cf6f16b61c0e2b9b0d0 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Wed, 11 Mar 2020 15:47:38 +0530 Subject: [PATCH 6/7] Update pydatastructs/linear_data_structures/arrays.py --- pydatastructs/linear_data_structures/arrays.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 322361c43..980aab92b 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -255,7 +255,6 @@ def delete(self, idx): def size(self): return self._size - class ArrayForTrees(DynamicOneDimensionalArray): """ Utility dynamic array for storing nodes of a tree. From ecf4171dc6a5e5a3c835508e37ef3b77144c2635 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Wed, 11 Mar 2020 15:49:40 +0530 Subject: [PATCH 7/7] Update pydatastructs/trees/tests/test_heaps.py --- pydatastructs/trees/tests/test_heaps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydatastructs/trees/tests/test_heaps.py b/pydatastructs/trees/tests/test_heaps.py index bb2f384bd..940620522 100644 --- a/pydatastructs/trees/tests/test_heaps.py +++ b/pydatastructs/trees/tests/test_heaps.py @@ -29,8 +29,8 @@ def test_BinaryHeap(): 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 + 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)