Skip to content

Commit 9563a44

Browse files
committed
Added basic skeleton for parent pointer tree
1 parent 6f688cd commit 9563a44

File tree

2 files changed

+154
-2
lines changed

2 files changed

+154
-2
lines changed

pydatastructs/trees/m_ary_trees.py

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from pydatastructs.utils import MAryTreeNode
1+
from pydatastructs.utils import MAryTreeNode, ParentPointerTreeNode
22
from pydatastructs.linear_data_structures.arrays import ArrayForTrees
33
from pydatastructs.utils.misc_util import (
44
Backend, raise_if_backend_is_not_python)
@@ -170,3 +170,155 @@ def __str__(self):
170170
if j is not None:
171171
to_be_printed[i].append(j)
172172
return str(to_be_printed)
173+
174+
class ParentPointerTree(object):
175+
"""
176+
Implements a tree with parent pointers.
177+
178+
Parameters
179+
==========
180+
181+
key
182+
Required if tree is to be instantiated with
183+
root otherwise not needed.
184+
root_data
185+
Optional, the root node of the tree.
186+
If not of type TreeNode, it will consider
187+
root as data and a new root node will
188+
be created.
189+
comp: lambda
190+
Optional, A lambda function which will be used
191+
for comparison of keys. Should return a
192+
bool value. By default it implements less
193+
than operator.
194+
195+
References
196+
==========
197+
198+
.. [1] https://en.wikipedia.org/wiki/Tree_(data_structure)#Parent_pointer_tree
199+
"""
200+
201+
__slots__ = ['root_idx', 'comparator', 'tree', 'size']
202+
203+
def __new__(cls, key=None, root_data=None, comp=None, **kwargs):
204+
raise_if_backend_is_not_python(
205+
cls, kwargs.get('backend', Backend.PYTHON))
206+
obj = object.__new__(cls)
207+
if key is None and root_data is not None:
208+
raise ValueError('Key required.')
209+
key = None if root_data is None else key
210+
root = ParentPointerTreeNode(key, root_data)
211+
root.is_root = True
212+
obj.root_idx = 0
213+
obj.tree, obj.size = ArrayForTrees(ParentPointerTreeNode, [root]), 1
214+
obj.comparator = lambda key1, key2: key1 < key2 \
215+
if comp is None else comp
216+
217+
return obj
218+
219+
@classmethod
220+
def methods(cls):
221+
return ['__new__', '__str__']
222+
223+
def insert(self, parent_key, key, data=None):
224+
"""
225+
Inserts data by the passed key using iterative
226+
algorithm.
227+
228+
Parameters
229+
==========
230+
231+
key
232+
The key for comparison.
233+
data
234+
The data to be inserted.
235+
236+
Returns
237+
=======
238+
239+
None
240+
"""
241+
if parent_key is None:
242+
raise ValueError("Parent key is required.")
243+
if key is None:
244+
raise ValueError("Key is required.")
245+
if self.search(key) is not None:
246+
raise ValueError("Key already exists.")
247+
248+
parent_node = self.search(parent_key, parent=True)
249+
new_node = ParentPointerTreeNode(key, data, parent_node)
250+
251+
self.tree.append(new_node)
252+
self.size += 1
253+
254+
def delete(self, key):
255+
"""
256+
Deletes the data with the passed key
257+
using iterative algorithm.
258+
259+
Parameters
260+
==========
261+
262+
key
263+
The key of the node which is
264+
to be deleted.
265+
266+
Returns
267+
=======
268+
269+
True
270+
If the node is deleted successfully.
271+
272+
None
273+
If the node to be deleted doesn't exists.
274+
275+
Note
276+
====
277+
278+
The node is deleted means that the connection to that
279+
node are removed but the it is still in tree.
280+
"""
281+
for idx in range(self.size):
282+
if self.tree[idx].key == key:
283+
self.tree.delete(idx)
284+
return True
285+
286+
return None
287+
288+
def search(self, key, **kwargs):
289+
"""
290+
Searches for the data in the tree
291+
using iterative algorithm.
292+
293+
Parameters
294+
==========
295+
296+
key
297+
The key for searching.
298+
parent: bool
299+
If true then returns index of the
300+
parent of the node with the passed
301+
key.
302+
By default, False
303+
304+
Returns
305+
=======
306+
307+
int
308+
If the node with the passed key is
309+
in the tree.
310+
tuple
311+
The index of the searched node and
312+
the index of the parent of that node.
313+
None
314+
In all other cases.
315+
"""
316+
317+
318+
def __str__(self):
319+
to_be_printed = ['' for i in range(self.tree._last_pos_filled + 1)]
320+
for i in range(self.tree._last_pos_filled + 1):
321+
if self.tree[i] is not None:
322+
node = self.tree[i]
323+
to_be_printed[i] = (node.key, node.data, node.parent)
324+
return str(to_be_printed)

pydatastructs/utils/misc_util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ class ParentPointerTreeNode(TreeNode):
300300
def methods(cls):
301301
return ['__new__', '__str__']
302302

303-
def __new__(cls, key, data=None, parent=None, **kwargs):
303+
def __new__(cls, key, data=None, parent: 'ParentPointerTreeNode' = None, **kwargs):
304304
raise_if_backend_is_not_python(
305305
cls, kwargs.get('backend', Backend.PYTHON))
306306
obj = Node.__new__(cls)

0 commit comments

Comments
 (0)