Skip to content

Commit eadae21

Browse files
authored
Added implementation for M-ary tree (#140)
1 parent 5aeeff9 commit eadae21

File tree

4 files changed

+214
-0
lines changed

4 files changed

+214
-0
lines changed

pydatastructs/trees/__init__.py

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

33
from . import (
44
binary_trees,
5+
m_ary_trees,
56
space_partitioning_trees,
67
heaps
78
)
@@ -15,6 +16,12 @@
1516
)
1617
__all__.extend(binary_trees.__all__)
1718

19+
from .m_ary_trees import (
20+
MAryTreeNode, MAryTree
21+
)
22+
23+
__all__.extend(m_ary_trees.__all__)
24+
1825
from .space_partitioning_trees import (
1926
OneDimensionalSegmentTree
2027
)

pydatastructs/trees/m_ary_trees.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
from pydatastructs.utils import MAryTreeNode
2+
from pydatastructs.linear_data_structures.arrays import ArrayForTrees
3+
4+
__all__ = [
5+
'MAryTree'
6+
]
7+
8+
class MAryTree(object):
9+
"""
10+
Abstract m-ary tree.
11+
12+
Parameters
13+
==========
14+
15+
root_data
16+
Optional, the root node of the binary tree.
17+
If not of type MAryTreeNode, it will consider
18+
root as data and a new root node will
19+
be created.
20+
key
21+
Required if tree is to be instantiated with
22+
root otherwise not needed.
23+
comp: lambda
24+
Optional, A lambda function which will be used
25+
for comparison of keys. Should return a
26+
bool value. By default it implements less
27+
than operator.
28+
is_order_statistic: bool
29+
Set it to True, if you want to use the
30+
order statistic features of the tree.
31+
max_children
32+
Optional, specifies the maximum number of children
33+
a node can have. Defaults to 2 in case nothing is
34+
specified.
35+
36+
References
37+
==========
38+
39+
.. [1] https://en.wikipedia.org/wiki/M-ary_tree
40+
"""
41+
42+
__slots__ = ['root_idx', 'max_children', 'comparator', 'tree', 'size',
43+
'is_order_statistic']
44+
45+
46+
def __new__(cls, key=None, root_data=None, comp=None,
47+
is_order_statistic=False, max_children=2):
48+
obj = object.__new__(cls)
49+
if key is None and root_data is not None:
50+
raise ValueError('Key required.')
51+
key = None if root_data is None else key
52+
root = MAryTreeNode(key, root_data)
53+
root.is_root = True
54+
obj.root_idx = 0
55+
obj.max_children = max_children
56+
obj.tree, obj.size = ArrayForTrees(MAryTreeNode, [root]), 1
57+
obj.comparator = lambda key1, key2: key1 < key2 \
58+
if comp is None else comp
59+
obj.is_order_statistic = is_order_statistic
60+
return obj
61+
62+
def insert(self, key, data):
63+
"""
64+
Inserts data by the passed key using iterative
65+
algorithm.
66+
67+
Parameters
68+
==========
69+
70+
key
71+
The key for comparison.
72+
data
73+
The data to be inserted.
74+
75+
Returns
76+
=======
77+
78+
None
79+
"""
80+
raise NotImplementedError("This is an abstract method.")
81+
82+
def delete(self, key, **kwargs):
83+
"""
84+
Deletes the data with the passed key
85+
using iterative algorithm.
86+
87+
Parameters
88+
==========
89+
90+
key
91+
The key of the node which is
92+
to be deleted.
93+
94+
Returns
95+
=======
96+
97+
True
98+
If the node is deleted successfully.
99+
None
100+
If the node to be deleted doesn't exists.
101+
102+
Note
103+
====
104+
105+
The node is deleted means that the connection to that
106+
node are removed but the it is still in tree.
107+
"""
108+
raise NotImplementedError("This is an abstract method.")
109+
110+
def search(self, key, **kwargs):
111+
"""
112+
Searches for the data in the binary search tree
113+
using iterative algorithm.
114+
115+
Parameters
116+
==========
117+
118+
key
119+
The key for searching.
120+
parent: bool
121+
If true then returns index of the
122+
parent of the node with the passed
123+
key.
124+
By default, False
125+
126+
Returns
127+
=======
128+
129+
int
130+
If the node with the passed key is
131+
in the tree.
132+
tuple
133+
The index of the searched node and
134+
the index of the parent of that node.
135+
None
136+
In all other cases.
137+
"""
138+
raise NotImplementedError("This is an abstract method.")
139+
140+
def to_binary_tree(self):
141+
"""
142+
Converts an m-ary tree to a binary tree.
143+
144+
Returns
145+
=======
146+
147+
TreeNode
148+
The root of the newly created binary tree.
149+
"""
150+
raise NotImplementedError("This is an abstract method.")
151+
152+
153+
def __str__(self):
154+
to_be_printed = ['' for i in range(self.tree._last_pos_filled + 1)]
155+
for i in range(self.tree._last_pos_filled + 1):
156+
if self.tree[i] is not None:
157+
node = self.tree[i]
158+
to_be_printed[i] = (node.key, node.data)
159+
for j in node.children:
160+
if j is not None:
161+
to_be_printed[i].append(j)
162+
return str(to_be_printed)

pydatastructs/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from . import misc_util
44
from .misc_util import (
55
TreeNode,
6+
MAryTreeNode,
67
LinkedListNode,
78
BinomialTreeNode,
89
AdjacencyListGraphNode,

pydatastructs/utils/misc_util.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
__all__ = [
22
'TreeNode',
3+
'MAryTreeNode',
34
'LinkedListNode',
45
'BinomialTreeNode',
56
'AdjacencyListGraphNode',
@@ -105,6 +106,49 @@ def __str__(self):
105106
"""
106107
return str((self.key, self.data))
107108

109+
class MAryTreeNode(TreeNode):
110+
"""
111+
Represents node in an M-ary trees.
112+
113+
Parameters
114+
==========
115+
116+
data
117+
Any valid data to be stored in the node.
118+
key
119+
Required for comparison operations.
120+
121+
Note
122+
====
123+
124+
The following are the data members of the class:
125+
126+
children: DynamicOneDimensionalArray
127+
An array of indices which stores the children of
128+
this node in the M-ary tree array
129+
is_root: bool, by default, False
130+
If the current node is a root of the tree then
131+
set it to True otherwise False.
132+
"""
133+
__slots__ = ['key', 'children', 'data', 'is_root']
134+
135+
def __new__(cls, key, data):
136+
from pydatastructs.linear_data_structures.arrays import DynamicOneDimensionalArray
137+
obj = Node.__new__(cls)
138+
obj.data = data
139+
obj.key = key
140+
obj.is_root = False
141+
obj.children = DynamicOneDimensionalArray(int, 0)
142+
return obj
143+
144+
def add_children(self, *children):
145+
"""
146+
Adds children of current node.
147+
"""
148+
for child in children:
149+
self.children.append(child)
150+
151+
108152
class LinkedListNode(Node):
109153
"""
110154
Represents node in linked lists.

0 commit comments

Comments
 (0)