Skip to content

Commit e811970

Browse files
authored
DHeap added (#118)
1 parent bd4e402 commit e811970

File tree

3 files changed

+243
-40
lines changed

3 files changed

+243
-40
lines changed

pydatastructs/trees/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
from .heaps import (
2424
BinaryHeap,
25+
TernaryHeap,
26+
DHeap,
2527
BinomialHeap
2628
)
2729
__all__.extend(heaps.__all__)

pydatastructs/trees/heaps.py

Lines changed: 154 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
__all__ = [
77
'BinaryHeap',
8+
'TernaryHeap',
9+
'DHeap',
810
'BinomialHeap'
911
]
1012

@@ -14,9 +16,10 @@ class Heap(object):
1416
"""
1517
pass
1618

17-
class BinaryHeap(Heap):
19+
20+
class DHeap(Heap):
1821
"""
19-
Represents Binary Heap.
22+
Represents D-ary Heap.
2023
2124
Parameters
2225
==========
@@ -26,7 +29,6 @@ class BinaryHeap(Heap):
2629
List/tuple of initial elements in Heap.
2730
2831
heap_property : str
29-
The property of binary heap.
3032
If the key stored in each node is
3133
either greater than or equal to
3234
the keys in the node's children
@@ -41,8 +43,8 @@ class BinaryHeap(Heap):
4143
Examples
4244
========
4345
44-
>>> from pydatastructs.trees.heaps import BinaryHeap
45-
>>> min_heap = BinaryHeap(heap_property="min")
46+
>>> from pydatastructs.trees.heaps import DHeap
47+
>>> min_heap = DHeap(heap_property="min", d=3)
4648
>>> min_heap.insert(1, 1)
4749
>>> min_heap.insert(5, 5)
4850
>>> min_heap.insert(7, 7)
@@ -52,7 +54,7 @@ class BinaryHeap(Heap):
5254
>>> min_heap.extract().key
5355
4
5456
55-
>>> max_heap = BinaryHeap(heap_property='max')
57+
>>> max_heap = DHeap(heap_property='max', d=2)
5658
>>> max_heap.insert(1, 1)
5759
>>> max_heap.insert(5, 5)
5860
>>> max_heap.insert(7, 7)
@@ -65,31 +67,32 @@ class BinaryHeap(Heap):
6567
References
6668
==========
6769
68-
.. [1] https://en.m.wikipedia.org/wiki/Binary_heap
70+
.. [1] https://en.wikipedia.org/wiki/D-ary_heap
6971
"""
70-
__slots__ = ['_comp', 'heap', 'heap_property', '_last_pos_filled']
72+
__slots__ = ['_comp', 'heap', 'd', 'heap_property', '_last_pos_filled']
7173

72-
def __new__(cls, elements=None, heap_property="min"):
74+
def __new__(cls, elements=None, heap_property="min", d=4):
7375
obj = Heap.__new__(cls)
7476
obj.heap_property = heap_property
77+
obj.d = d
7578
if heap_property == "min":
7679
obj._comp = lambda key_parent, key_child: key_parent <= key_child
7780
elif heap_property == "max":
7881
obj._comp = lambda key_parent, key_child: key_parent >= key_child
7982
else:
8083
raise ValueError("%s is invalid heap property"%(heap_property))
8184
if elements is None:
82-
elements = []
85+
elements = DynamicOneDimensionalArray(TreeNode, 0)
8386
obj.heap = elements
84-
obj._last_pos_filled = len(elements) - 1
87+
obj._last_pos_filled = obj.heap._last_pos_filled
8588
obj._build()
8689
return obj
8790

8891
def _build(self):
8992
for i in range(self._last_pos_filled + 1):
90-
self.heap[i].left, self.heap[i].right = \
91-
2*i + 1, 2*i + 2
92-
for i in range((self._last_pos_filled + 1)//2, -1, -1):
93+
self.heap[i]._leftmost, self.heap[i]._rightmost = \
94+
self.d*i + 1, self.d*i + self.d
95+
for i in range((self._last_pos_filled + 1)//self.d, -1, -1):
9396
self._heapify(i)
9497

9598
def _swap(self, idx1, idx2):
@@ -103,23 +106,22 @@ def _swap(self, idx1, idx2):
103106
def _heapify(self, i):
104107
while True:
105108
target = i
106-
l = 2*i + 1
107-
r = 2*i + 2
109+
l = self.d*i + 1
110+
r = self.d*i + self.d
108111

109-
if l <= self._last_pos_filled:
110-
target = l if self._comp(self.heap[l].key, self.heap[target].key) \
111-
else i
112-
if r <= self._last_pos_filled:
113-
target = r if self._comp(self.heap[r].key, self.heap[target].key) \
114-
else target
112+
for j in range(l, r+1):
113+
if j <= self._last_pos_filled:
114+
target = j if self._comp(self.heap[j].key, self.heap[target].key) \
115+
else target
116+
else:
117+
break
115118

116119
if target != i:
117120
self._swap(target, i)
118121
i = target
119122
else:
120123
break
121124

122-
123125
def insert(self, key, data):
124126
"""
125127
Insert a new element to the heap according to heap property.
@@ -141,10 +143,10 @@ def insert(self, key, data):
141143
self.heap.append(new_node)
142144
self._last_pos_filled += 1
143145
i = self._last_pos_filled
144-
self.heap[i].left, self.heap[i].right = 2*i + 1, 2*i + 2
146+
self.heap[i]._leftmost, self.heap[i]._rightmost = self.d*i + 1, self.d*i + self.d
145147

146148
while True:
147-
parent = (i - 1)//2
149+
parent = (i - 1)//self.d
148150
if i == 0 or self._comp(self.heap[parent].key, self.heap[i].key):
149151
break
150152
else:
@@ -169,23 +171,143 @@ def extract(self):
169171
else:
170172
element_to_be_extracted = TreeNode(self.heap[0].key, self.heap[0].data)
171173
self._swap(0, self._last_pos_filled)
172-
self.heap[self._last_pos_filled] = TreeNode(float('inf') if self.heap_property == 'min'
173-
else float('-inf'), None)
174-
self._heapify(0)
175-
self.heap.pop()
174+
self.heap.delete(self._last_pos_filled)
176175
self._last_pos_filled -= 1
176+
self._heapify(0)
177177
return element_to_be_extracted
178178

179179
def __str__(self):
180180
to_be_printed = ['' for i in range(self._last_pos_filled + 1)]
181181
for i in range(self._last_pos_filled + 1):
182182
node = self.heap[i]
183-
to_be_printed[i] = (node.left if node.left <= self._last_pos_filled else None,
184-
node.key, node.data,
185-
node.right if node.right <= self._last_pos_filled else None)
183+
if node._leftmost <= self._last_pos_filled:
184+
if node._rightmost <= self._last_pos_filled:
185+
children = [x for x in range(node._leftmost, node._rightmost + 1)]
186+
else:
187+
children = [x for x in range(node._leftmost, self._last_pos_filled + 1)]
188+
else:
189+
children = []
190+
to_be_printed[i] = (node.key, node.data, children)
186191
return str(to_be_printed)
187192

188193

194+
class BinaryHeap(DHeap):
195+
"""
196+
Represents Binary Heap.
197+
198+
Parameters
199+
==========
200+
201+
elements : list, tuple
202+
Optional, by default 'None'.
203+
List/tuple of initial elements in Heap.
204+
205+
heap_property : str
206+
If the key stored in each node is
207+
either greater than or equal to
208+
the keys in the node's children
209+
then pass 'max'.
210+
If the key stored in each node is
211+
either less than or equal to
212+
the keys in the node's children
213+
then pass 'min'.
214+
By default, the heap property is
215+
set to 'min'.
216+
217+
Examples
218+
========
219+
220+
>>> from pydatastructs.trees.heaps import BinaryHeap
221+
>>> min_heap = BinaryHeap(heap_property="min")
222+
>>> min_heap.insert(1, 1)
223+
>>> min_heap.insert(5, 5)
224+
>>> min_heap.insert(7, 7)
225+
>>> min_heap.extract().key
226+
1
227+
>>> min_heap.insert(4, 4)
228+
>>> min_heap.extract().key
229+
4
230+
231+
>>> max_heap = BinaryHeap(heap_property='max')
232+
>>> max_heap.insert(1, 1)
233+
>>> max_heap.insert(5, 5)
234+
>>> max_heap.insert(7, 7)
235+
>>> max_heap.extract().key
236+
7
237+
>>> max_heap.insert(6, 6)
238+
>>> max_heap.extract().key
239+
6
240+
241+
References
242+
==========
243+
244+
.. [1] https://en.m.wikipedia.org/wiki/Binary_heap
245+
"""
246+
def __new__(cls, elements=None, heap_property="min"):
247+
obj = DHeap.__new__(cls, elements, heap_property, 2)
248+
return obj
249+
250+
251+
class TernaryHeap(DHeap):
252+
"""
253+
Represents Ternary Heap.
254+
255+
Parameters
256+
==========
257+
258+
elements : list, tuple
259+
Optional, by default 'None'.
260+
List/tuple of initial elements in Heap.
261+
262+
heap_property : str
263+
If the key stored in each node is
264+
either greater than or equal to
265+
the keys in the node's children
266+
then pass 'max'.
267+
If the key stored in each node is
268+
either less than or equal to
269+
the keys in the node's children
270+
then pass 'min'.
271+
By default, the heap property is
272+
set to 'min'.
273+
274+
Examples
275+
========
276+
277+
>>> from pydatastructs.trees.heaps import TernaryHeap
278+
>>> min_heap = TernaryHeap(heap_property="min")
279+
>>> min_heap.insert(1, 1)
280+
>>> min_heap.insert(5, 5)
281+
>>> min_heap.insert(7, 7)
282+
>>> min_heap.insert(3, 3)
283+
>>> min_heap.extract().key
284+
1
285+
>>> min_heap.insert(4, 4)
286+
>>> min_heap.extract().key
287+
3
288+
289+
>>> max_heap = TernaryHeap(heap_property='max')
290+
>>> max_heap.insert(1, 1)
291+
>>> max_heap.insert(5, 5)
292+
>>> max_heap.insert(7, 7)
293+
>>> min_heap.insert(3, 3)
294+
>>> max_heap.extract().key
295+
7
296+
>>> max_heap.insert(6, 6)
297+
>>> max_heap.extract().key
298+
6
299+
300+
References
301+
==========
302+
303+
.. [1] https://en.wikipedia.org/wiki/D-ary_heap
304+
.. [2] https://ece.uwaterloo.ca/~dwharder/aads/Algorithms/d-ary_heaps/Ternary_heaps/
305+
"""
306+
def __new__(cls, elements=None, heap_property="min"):
307+
obj = DHeap.__new__(cls, elements, heap_property, 3)
308+
return obj
309+
310+
189311
class BinomialHeap(Heap):
190312
"""
191313
Represents binomial heap.

0 commit comments

Comments
 (0)