diff --git a/algorithms/Python/README.md b/algorithms/Python/README.md index a307dd3a..959198b4 100644 --- a/algorithms/Python/README.md +++ b/algorithms/Python/README.md @@ -66,5 +66,5 @@ ## Trees - [Binary Tree](trees/binary_tree.py) -- [Binary Search Tree](trees/binary-search-tree.py) +- [Binary Search Tree](trees/binary_search_tree.py) diff --git a/algorithms/Python/trees/binary-search-tree.py b/algorithms/Python/trees/binary_search_tree.py similarity index 61% rename from algorithms/Python/trees/binary-search-tree.py rename to algorithms/Python/trees/binary_search_tree.py index 6b6d4c93..41232ab6 100644 --- a/algorithms/Python/trees/binary-search-tree.py +++ b/algorithms/Python/trees/binary_search_tree.py @@ -1,8 +1,5 @@ # author: @hashfx -# Binary Tree Data Structure -# Data is stored in hierarchical form where a parent node can have at most 2 child nodes -# # A # ___|___ # B C @@ -10,49 +7,56 @@ # D E # / \ \ # F G H -# -# Here, A is "ROOT NODE" and B, C are "CHILD NODE" -# (B-D-F-G), (B-E-H) is a sub-tree -# B is 'ROOT NODE' for D, E & D is 'ROOT NODE' for F, G & E is root node for H -# Those nodes [C, F, G, H] who do not have any child node are "LEAF NODE" -# -# Rules for Binary Search Tree: -# > All nodes are unique -# > Right sub-tree > Left sub-tree ===== Left sub-tree < Right sub-tree -# [Value(BA), Value(DB), Value(FD), Value(H>E)] -# > One parent node can not have more than 2 child nodes -# > Elements are not duplicated -# Searching in Binary Tree: -# Suppose we want to search E in the Tree: -# > At Root Node(A) :: IF A>E THEN element would be at Left sub-Tree -# > At Left sub-Tree(B) :: IF B4->2->1] {Search completed in 3 iterations} -# 3 compared to 8 is log(2)8 = 2 -# Search Complexity : O(log n) -# Insertion Complexity : O(log n) -# -# -# Types of BST: -# Breadth First Search -# -# -# Depth First Search -# order here means base node -# > In Order Traversal : first visit left sub-tree >> root node >> right sub-tree [F-D-G-B-H-E-A-C] -# {Root node in between left and right tree} -# > Pre Order Traversal : root node >> left sub-tree >> right sub-tree [A-B-D-F-G-E-H-C] -# {Root node before left and right tree} -# > Post Order Traversal : left sub-tree >> right sub-tree >> root node [F-G-D-H-E-B-C-A] -# {Root node after left and right tree} + +""" Binary Tree Data Structure +Data is stored in hierarchical form where a parent node can have at most 2 child nodes + + Here, A is "ROOT NODE" and B, C are "CHILD NODE" + (B-D-F-G), (B-E-H) is a sub-tree + B is 'ROOT NODE' for D, E & D is 'ROOT NODE' for F, G & E is root node for H + Those nodes [C, F, G, H] who do not have any child node are "LEAF NODE" + + Rules for Binary Search Tree: + > All nodes are unique + > Right sub-tree > Left sub-tree ===== Left sub-tree < Right sub-tree + [Value(BA), Value(DB), Value(FD), Value(H>E)] + > One parent node can not have more than 2 child nodes + > Elements are not duplicated + Searching in Binary Tree: + Suppose we want to search E in the Tree: + > At Root Node(A) :: IF A>E THEN element would be at Left sub-Tree + > At Left sub-Tree(B) :: IF B4->2->1] {Search completed in 3 iterations} + 3 compared to 8 is log(2)8 = 2 + Search Complexity : O(log n) + Insertion Complexity : O(log n) + + +Types of BST: + Breadth First Search + + + Depth First Search + order here means base node + > In Order Traversal : + first visit left sub-tree >> root node >> right sub-tree [F-D-G-B-H-E-A-C] + {Root node in between left and right tree} + > Pre Order Traversal : + root node >> left sub-tree >> right sub-tree [A-B-D-F-G-E-H-C] + {Root node before left and right tree} + > Post Order Traversal : + left sub-tree >> right sub-tree >> root node [F-G-D-H-E-B-C-A] + {Root node after left and right tree}""" class Node: - # constructor + """ constructor """ def __init__(self, data): + """ constructor """ self.data = data self.left = None self.right = None @@ -63,11 +67,12 @@ class Node: # checking if entered data is already present if data == self.data: - return + return None - # if tree is empty means no node(root) at tree else incoming data will be treated as node(root(tree)) + # if tree is empty means no node(root) at tree + # else incoming data will be treated as node(root(tree)) if self.data: - ''' check if data(right) > data(left) & node(parent)''' + # check if data(right) > data(left) & node(parent) if data < self.data: # data is smaller than data of node(parent) if self.left is None: # and if no element is present at left of node self.left = Node(data) # insert data at left @@ -82,23 +87,27 @@ class Node: else: self.data = data # if tree is empty; treat incoming data as root of the tree + return None - def InOrderTraversal(self): + + def in_order_traversal(self): + """ constructor """ elements = [] # list to be filled with all elements of BST in specific order # In-order-Traversal : left sub-tree >> root node >> right sub-tree if self.left: # put elements of left sub-tree in list[elements] - elements += self.left.InOrderTraversal() + elements += self.left.in_order_traversal() elements.append(self.data) # put root node data in list[elements] if self.right: # put elements of right sub-tree in list[elements] - elements += self.right.InOrderTraversal() + elements += self.right.in_order_traversal() return elements # return list[elements] - def PreOrderTraversal(self): + def pre_order_traversal(self): + """ constructor """ elements = [] # Pre-Order-Traversal : root node >> left sub-tree >> right sub-tree @@ -106,23 +115,24 @@ class Node: elements.append(self.data) # put root node data in list[elements] if self.left: # put elements of left sub-tree in list[elements] - elements += self.left.InOrderTraversal() + elements += self.left.in_order_traversal() if self.right: # put elements of right sub-tree in list[elements] - elements += self.right.InOrderTraversal() + elements += self.right.in_order_traversal() return elements # return list[elements] - def PostOrderTraversal(self): + def post_order_traversal(self): + """ constructor """ elements = [] # Pre-Order-Traversal : left sub-tree >> right sub-tree >> root node if self.left: # put elements of left sub-tree in list[elements] - elements += self.left.InOrderTraversal() + elements += self.left.in_order_traversal() if self.right: # put elements of right sub-tree in list[elements] - elements += self.right.InOrderTraversal() + elements += self.right.in_order_traversal() elements.append(self.data) # put root node data in list[elements] @@ -137,22 +147,21 @@ class Node: # search for val in left sub-tree if self.left: return self.left.search(val) - else: - return False + return False if val > self.data: # search for val in right sub-tree if self.right: return self.right.search(val) - else: - return False + return False + + return None def max(self): - '''Maximum element of tree: keep searching on right sub-tree to find maximum element ''' - if self.right is None: # leaf node - return self.data - return self.right.max() - + '''Maximum element of tree: keep searching on right sub-tree to find maximum element ''' + if self.right is None: # leaf node + return self.data + return self.right.max() def min(self): ''' Minimum element of tree: keep searching on left sub-tree to find minimum element ''' @@ -162,6 +171,7 @@ class Node: def delete(self, val): + """ constructor """ if val < self.data: # search for element in left sub-tree if self.left: # check if there is any left sub-tree self.left = self.left.delete(val) # delete recursion @@ -193,13 +203,13 @@ class Node: def build_tree(elements): + """ constructor """ root = Node(elements[0]) for i in range(1, len(elements)): root.add_child(elements[i]) return root - # If build_tree() is not used # root = Node(4) # root.add_child(6) @@ -208,29 +218,25 @@ def build_tree(elements): # root.add_child(3) # root.add_child(8) # root.add_child(5) - -''' smaller elements will be displayed at left/top of root node <--> greater elements will be displayed at - right/bottom of root node ''' # root.display() - # main method if __name__ == '__main__': # Numeric BST num_list = [20, 18, 37, 15, 7, 5, 9, 18, 24, 0] # repeated elements are removed list_tree = build_tree(num_list) - print(list_tree.InOrderTraversal()) # return list in sorted order - print(list_tree.PreOrderTraversal()) # return list in sorted order - print(list_tree.PostOrderTraversal()) # return list in sorted order + print(list_tree.in_order_traversal()) # return list in sorted order + print(list_tree.pre_order_traversal()) # return list in sorted order + print(list_tree.post_order_traversal()) # return list in sorted order # list_tree.display() # display tree using display function print(list_tree.search(20)) # True print(list_tree.search(4)) # False list_tree.delete(20) - print("Deleted element: ", list_tree.InOrderTraversal()) + print("Deleted element: ", list_tree.in_order_traversal()) # String BST country = ["India", "Australia", "France", "Japan", "Sweden"] country_tree = build_tree(country) - print(country_tree.InOrderTraversal()) # return list in sorted order + print(country_tree.in_order_traversal()) # return list in sorted order print(country_tree.search("UK")) # False print(country_tree.search("Japan")) # True diff --git a/algorithms/Python/trees/binary_tree.py b/algorithms/Python/trees/binary_tree.py index 4fc4d46f..b966230b 100644 --- a/algorithms/Python/trees/binary_tree.py +++ b/algorithms/Python/trees/binary_tree.py @@ -1,77 +1,80 @@ -# Author: github.com/Mo-Shakib - -class Node: - def __init__(self, data = None): - self.left = None - self.right = None - self.data = data - - # for setting left node - def setLeft(self, node): - self.left = node - - # for setting right node - def setRight(self, node): - self.right = node - - # for getting the left node - def getLeft(self): - return self.left - - # for getting right node - def getRight(self): - return self.right - - # for setting data of a node - def setData(self, data): - self.data = data - - # for getting data of a node - def getData(self): - return self.data - - -# in this we traverse first to the leftmost node, then print its data and then traverse for rightmost node -def inorder(Tree): - if Tree: - inorder(Tree.getLeft()) - print(Tree.getData(), end = ' ') - inorder(Tree.getRight()) - return - -# in this we first print the root node and then traverse towards leftmost node and then to the rightmost node -def preorder(Tree): - if Tree: - print(Tree.getData(), end = ' ') - preorder(Tree.getLeft()) - preorder(Tree.getRight()) - return - -# in this we first traverse to the leftmost node and then to the rightmost node and then print the data -def postorder(Tree): - if Tree: - postorder(Tree.getLeft()) - postorder(Tree.getRight()) - print(Tree.getData(), end = ' ') - return - -if __name__ == '__main__': - root = Node(1) - root.setLeft(Node(2)) - root.setRight(Node(3)) - root.left.setLeft(Node(4)) - - print('Inorder Traversal:') - inorder(root) - print('\nPreorder Traversal:') - preorder(root) - print('\nPostorder Traversal:') - postorder(root) - - # OUTPUT: - # Inorder Traversal: - # 4 2 1 3 - # Preorder Traversal: - # 1 2 4 3 - # Postorder Traversal: - # 4 2 3 1 +# Author: github.com/Mo-Shakib + +""" The binary tree data structure implementation """ + +class Node: + """ node class """ + def __init__(self, data = None): + """ initializing function """ + self.left = None + self.right = None + self.data = data + + def set_left(self, node): + """ for setting left node """ + self.left = node + + def set_right(self, node): + """ for setting right node """ + self.right = node + + def get_left(self): + """ for getting the left node """ + return self.left + + def get_right(self): + """ for getting right node """ + return self.right + + def set_data(self, data): + """ for setting data of a node """ + self.data = data + + def get_data(self): + """ for getting data of a node """ + return self.data + +def inorder(tree): + """ in this we traverse first to the leftmost node, + then print its data and then traverse for rightmost node """ + if tree: + inorder(tree.get_left()) + print(tree.get_data(), end = ' ') + inorder(tree.get_right()) + +def preorder(tree): + """ in this we first print the root node + and then traverse towards leftmost node and then to the rightmost node """ + if tree: + print(tree.get_data(), end = ' ') + preorder(tree.get_left()) + preorder(tree.get_right()) + +def postorder(tree): + """ in this we first traverse to the leftmost node + and then to the rightmost node and then print the data """ + if tree: + postorder(tree.get_left()) + postorder(tree.get_right()) + print(tree.get_data(), end = ' ') + +if __name__ == '__main__': + root = Node(1) + root.set_left(Node(2)) + root.set_right(Node(3)) + root.left.set_left(Node(4)) + + print('Inorder Traversal:') + inorder(root) + print('\nPreorder Traversal:') + preorder(root) + print('\nPostorder Traversal:') + postorder(root) + + # OUTPUT: + # Inorder Traversal: + # 4 2 1 3 + # Preorder Traversal: + # 1 2 4 3 + # Postorder Traversal: + # 4 2 3 1