From d77922a6caf49d9df233d1e4a2af4d08539b45c2 Mon Sep 17 00:00:00 2001 From: vibhu Date: Thu, 12 Mar 2020 11:26:59 +0530 Subject: [PATCH 1/6] Added implementation for M-ary tree Added M_aryTreeNode for use in M_ary tree and an implementation for M_ary Tree. The work is in reference with issue #101. --- pydatastructs/trees/m_ary_trees.py | 168 +++++++++++++++++++++++++++++ pydatastructs/utils/__init__.py | 1 + pydatastructs/utils/misc_util.py | 49 +++++++++ 3 files changed, 218 insertions(+) create mode 100644 pydatastructs/trees/m_ary_trees.py diff --git a/pydatastructs/trees/m_ary_trees.py b/pydatastructs/trees/m_ary_trees.py new file mode 100644 index 000000000..074c2909e --- /dev/null +++ b/pydatastructs/trees/m_ary_trees.py @@ -0,0 +1,168 @@ +from pydatastructs.utils import M_AryTreeNode, BinomialTreeNode +from pydatastructs.linear_data_structures.arrays import ArrayForTrees + +__all__ = [ + 'M_AryTree' +] + +class M_AryTree(object): + """ + Abstract m-ary tree. + + Parameters + ========== + + max_children + Optional, specifies the maximum number of children + a node can have. Defaults to 2 in case nothing is + specified. + root_data + Optional, the root node of the binary tree. + If not of type M_AryTreeNode, it will consider + root as data and a new root node will + be created. + key + Required if tree is to be instantiated with + root otherwise not needed. + comp: lambda + Optional, A lambda function which will be used + for comparison of keys. Should return a + bool value. By default it implements less + than operator. + is_order_statistic: bool + Set it to True, if you want to use the + order statistic features of the tree. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/M-ary_tree + """ + + __slots__ = ['root_idx', 'max_children', 'comparator', 'tree', 'size', + 'is_order_statistic'] + + + def __new__(cls, max_children=2, key=None, root_data=None, comp=None, + is_order_statistic=False): + obj = object.__new__(cls) + if key is None and root_data is not None: + raise ValueError('Key required.') + key = None if root_data is None else key + root = M_AryTreeNode(key, root_data) + root.is_root = True + obj.root_idx = 0 + obj.max_children = max_children + obj.tree, obj.size = ArrayForTrees(M_AryTreeNode, [root]), 1 + obj.comparator = lambda key1, key2: key1 < key2 \ + if comp is None else comp + obj.is_order_statistic = is_order_statistic + return obj + + def insert(self, key, data): + """ + Inserts data by the passed key using iterative + algorithm. + + Parameters + ========== + + key + The key for comparison. + data + The data to be inserted. + + Returns + ======= + + None + """ + raise NotImplementedError("This is an abstract method.") + + def delete(self, key, **kwargs): + """ + Deletes the data with the passed key + using iterative algorithm. + + Parameters + ========== + + key + The key of the node which is + to be deleted. + balancing_info: bool + Optional, by default, False + The information needed for updating + the tree is returned if this parameter + is set to True. It is not meant for + user facing APIs. + + Returns + ======= + + True + If the node is deleted successfully. + None + If the node to be deleted doesn't exists. + + Note + ==== + + The node is deleted means that the connection to that + node are removed but the it is still in tree. + """ + raise NotImplementedError("This is an abstract method.") + + def search(self, key, **kwargs): + """ + Searches for the data in the binary search tree + using iterative algorithm. + + Parameters + ========== + + key + The key for searching. + parent: bool + If true then returns index of the + parent of the node with the passed + key. + By default, False + + Returns + ======= + + int + If the node with the passed key is + in the tree. + tuple + The index of the searched node and + the index of the parent of that node. + None + In all other cases. + """ + raise NotImplementedError("This is an abstract method.") + + def to_binary_tree(self): + """ + Converts an m-ary tree to a binary tree. + + Returns + ======= + + TreeNode + The root of the newly created binary tree. + """ + raise NotImplementedError("This is an abstract method.") + + + def __str__(self): + to_be_printed = ['' for i in range(self.tree._last_pos_filled + 1)] + for i in range(self.tree._last_pos_filled + 1): + if self.tree[i] is not None: + node = self.tree[i] + to_be_printed[i] = (node.key, node.data) + for j in node.children: + if j is not None: + to_be_printed[i].append(j) + return str(to_be_printed) diff --git a/pydatastructs/utils/__init__.py b/pydatastructs/utils/__init__.py index bb63db83e..524fe4c01 100644 --- a/pydatastructs/utils/__init__.py +++ b/pydatastructs/utils/__init__.py @@ -3,6 +3,7 @@ from . import misc_util from .misc_util import ( TreeNode, + M_AryTreeNode, LinkedListNode, BinomialTreeNode, AdjacencyListGraphNode, diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py index 5db27a374..bec0af5c4 100644 --- a/pydatastructs/utils/misc_util.py +++ b/pydatastructs/utils/misc_util.py @@ -1,5 +1,6 @@ __all__ = [ 'TreeNode', + 'M_AryTreeNode', 'LinkedListNode', 'BinomialTreeNode', 'AdjacencyListGraphNode', @@ -104,6 +105,54 @@ def __str__(self): """ return str((self.key, self.data)) +class M_AryTreeNode(TreeNode): + """ + Represents node in an M-ary trees. + + Parameters + ========== + + data + Any valid data to be stored in the node. + key + Required for comparison operations. + + Note + ==== + + The following are the data members of the class: + + children: DynamicOneDimensionalArray + An array of indices which stores the children of + this node in the M-ary tree array + is_root: bool, by default, False + If the current node is a root of the tree then + set it to True otherwise False. + """ + __slots__ = ['key', 'children', 'data', 'is_root'] + + def __new__(cls, key, data): + from pydatastructs.linear_data_structures.arrays import DynamicOneDimensionalArray + obj = Node.__new__(cls) + obj.data = data + obj.key = key + obj.is_root = False + obj.children = DynamicOneDimensionalArray(int, 0) + return obj + + def add_children(self, *children): + """ + Adds children of current node. + """ + for child in children: + self.children.append(child) + + def __str__(self): + """ + For printing the key and data. + """ + return str((self.key, self.data)) + class LinkedListNode(Node): """ Represents node in linked lists. From 74dab8f990ad126dafc141771e10d32e19a260a3 Mon Sep 17 00:00:00 2001 From: vibhu Date: Thu, 12 Mar 2020 19:30:39 +0530 Subject: [PATCH 2/6] Removing trailing white spaces --- pydatastructs/trees/m_ary_trees.py | 8 ++++---- pydatastructs/utils/misc_util.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pydatastructs/trees/m_ary_trees.py b/pydatastructs/trees/m_ary_trees.py index 074c2909e..cfbc334d7 100644 --- a/pydatastructs/trees/m_ary_trees.py +++ b/pydatastructs/trees/m_ary_trees.py @@ -13,8 +13,8 @@ class M_AryTree(object): ========== max_children - Optional, specifies the maximum number of children - a node can have. Defaults to 2 in case nothing is + Optional, specifies the maximum number of children + a node can have. Defaults to 2 in case nothing is specified. root_data Optional, the root node of the binary tree. @@ -145,13 +145,13 @@ def search(self, key, **kwargs): def to_binary_tree(self): """ - Converts an m-ary tree to a binary tree. + Converts an m-ary tree to a binary tree. Returns ======= TreeNode - The root of the newly created binary tree. + The root of the newly created binary tree. """ raise NotImplementedError("This is an abstract method.") diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py index bec0af5c4..de903fd21 100644 --- a/pydatastructs/utils/misc_util.py +++ b/pydatastructs/utils/misc_util.py @@ -123,7 +123,7 @@ class M_AryTreeNode(TreeNode): The following are the data members of the class: children: DynamicOneDimensionalArray - An array of indices which stores the children of + An array of indices which stores the children of this node in the M-ary tree array is_root: bool, by default, False If the current node is a root of the tree then From 13bbd9840cfdd807c9c4f5eaf49bd63b31ecfcb1 Mon Sep 17 00:00:00 2001 From: vibhu Date: Fri, 13 Mar 2020 10:58:49 +0530 Subject: [PATCH 3/6] Fixed _ in names and MAryTree to global namespace --- pydatastructs/trees/__init__.py | 7 +++++++ pydatastructs/trees/m_ary_trees.py | 12 ++++++------ pydatastructs/utils/__init__.py | 2 +- pydatastructs/utils/misc_util.py | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pydatastructs/trees/__init__.py b/pydatastructs/trees/__init__.py index 5f110bf0c..e9beb55df 100644 --- a/pydatastructs/trees/__init__.py +++ b/pydatastructs/trees/__init__.py @@ -2,6 +2,7 @@ from . import ( binary_trees, + m_ary_trees, space_partitioning_trees ) @@ -10,6 +11,12 @@ ) __all__.extend(binary_trees.__all__) +from .m_ary_trees import ( + MAryTreeNode, MAryTree +) + +__all__.extend(m_ary_trees.__all__) + from .space_partitioning_trees import ( OneDimensionalSegmentTree ) diff --git a/pydatastructs/trees/m_ary_trees.py b/pydatastructs/trees/m_ary_trees.py index cfbc334d7..1968988b5 100644 --- a/pydatastructs/trees/m_ary_trees.py +++ b/pydatastructs/trees/m_ary_trees.py @@ -1,11 +1,11 @@ -from pydatastructs.utils import M_AryTreeNode, BinomialTreeNode +from pydatastructs.utils import MAryTreeNode from pydatastructs.linear_data_structures.arrays import ArrayForTrees __all__ = [ - 'M_AryTree' + 'MAryTree' ] -class M_AryTree(object): +class MAryTree(object): """ Abstract m-ary tree. @@ -18,7 +18,7 @@ class M_AryTree(object): specified. root_data Optional, the root node of the binary tree. - If not of type M_AryTreeNode, it will consider + If not of type MAryTreeNode, it will consider root as data and a new root node will be created. key @@ -49,11 +49,11 @@ def __new__(cls, max_children=2, key=None, root_data=None, comp=None, if key is None and root_data is not None: raise ValueError('Key required.') key = None if root_data is None else key - root = M_AryTreeNode(key, root_data) + root = MAryTreeNode(key, root_data) root.is_root = True obj.root_idx = 0 obj.max_children = max_children - obj.tree, obj.size = ArrayForTrees(M_AryTreeNode, [root]), 1 + obj.tree, obj.size = ArrayForTrees(MAryTreeNode, [root]), 1 obj.comparator = lambda key1, key2: key1 < key2 \ if comp is None else comp obj.is_order_statistic = is_order_statistic diff --git a/pydatastructs/utils/__init__.py b/pydatastructs/utils/__init__.py index 524fe4c01..a59e4a3dc 100644 --- a/pydatastructs/utils/__init__.py +++ b/pydatastructs/utils/__init__.py @@ -3,7 +3,7 @@ from . import misc_util from .misc_util import ( TreeNode, - M_AryTreeNode, + MAryTreeNode, LinkedListNode, BinomialTreeNode, AdjacencyListGraphNode, diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py index de903fd21..bf93efe01 100644 --- a/pydatastructs/utils/misc_util.py +++ b/pydatastructs/utils/misc_util.py @@ -1,6 +1,6 @@ __all__ = [ 'TreeNode', - 'M_AryTreeNode', + 'MAryTreeNode', 'LinkedListNode', 'BinomialTreeNode', 'AdjacencyListGraphNode', @@ -105,7 +105,7 @@ def __str__(self): """ return str((self.key, self.data)) -class M_AryTreeNode(TreeNode): +class MAryTreeNode(TreeNode): """ Represents node in an M-ary trees. From d9bcef79837f83bec3ef9ef373da15e66d0816a7 Mon Sep 17 00:00:00 2001 From: vibhu Date: Sun, 15 Mar 2020 23:57:36 +0530 Subject: [PATCH 4/6] Updated the ordering of parameters. --- pydatastructs/trees/m_ary_trees.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/pydatastructs/trees/m_ary_trees.py b/pydatastructs/trees/m_ary_trees.py index 1968988b5..f0a4d389a 100644 --- a/pydatastructs/trees/m_ary_trees.py +++ b/pydatastructs/trees/m_ary_trees.py @@ -12,10 +12,6 @@ class MAryTree(object): Parameters ========== - max_children - Optional, specifies the maximum number of children - a node can have. Defaults to 2 in case nothing is - specified. root_data Optional, the root node of the binary tree. If not of type MAryTreeNode, it will consider @@ -32,6 +28,10 @@ class MAryTree(object): is_order_statistic: bool Set it to True, if you want to use the order statistic features of the tree. + max_children + Optional, specifies the maximum number of children + a node can have. Defaults to 2 in case nothing is + specified. References ========== @@ -43,8 +43,8 @@ class MAryTree(object): 'is_order_statistic'] - def __new__(cls, max_children=2, key=None, root_data=None, comp=None, - is_order_statistic=False): + def __new__(cls, key=None, root_data=None, comp=None, + is_order_statistic=False, max_children=2): obj = object.__new__(cls) if key is None and root_data is not None: raise ValueError('Key required.') @@ -90,12 +90,6 @@ def delete(self, key, **kwargs): key The key of the node which is to be deleted. - balancing_info: bool - Optional, by default, False - The information needed for updating - the tree is returned if this parameter - is set to True. It is not meant for - user facing APIs. Returns ======= From ac26f9a36b58dc622043b60e15c22f027adbaea3 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Wed, 18 Mar 2020 01:19:11 +0530 Subject: [PATCH 5/6] Removed tab --- pydatastructs/trees/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydatastructs/trees/__init__.py b/pydatastructs/trees/__init__.py index 97ec76287..42f919c35 100644 --- a/pydatastructs/trees/__init__.py +++ b/pydatastructs/trees/__init__.py @@ -17,7 +17,7 @@ __all__.extend(binary_trees.__all__) from .m_ary_trees import ( - MAryTreeNode, MAryTree + MAryTreeNode, MAryTree ) __all__.extend(m_ary_trees.__all__) From ebe7541ae9316472f9258137cddc2e061d76e630 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Thu, 19 Mar 2020 01:06:24 +0530 Subject: [PATCH 6/6] Update pydatastructs/utils/misc_util.py --- pydatastructs/utils/misc_util.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py index a3f47671a..a573a86f5 100644 --- a/pydatastructs/utils/misc_util.py +++ b/pydatastructs/utils/misc_util.py @@ -147,11 +147,6 @@ def add_children(self, *children): for child in children: self.children.append(child) - def __str__(self): - """ - For printing the key and data. - """ - return str((self.key, self.data)) class LinkedListNode(Node): """