enh(Python): binary tree (#665)
parent
98bac46911
commit
fd9f7b4806
|
@ -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)
|
||||
|
||||
|
|
|
@ -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(B<A AND C>A), Value(D<B AND E>B), Value(F<D AND G>D), 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 B<E THEN element would be at Right of the sub-tree
|
||||
#
|
||||
# Significance of BST:
|
||||
# With every iteration, search space is reduced by 1/2 (half)
|
||||
# Let no of nodes in a tree (n) be 8 then:
|
||||
# n = 8 [8->4->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(B<A AND C>A), Value(D<B AND E>B), Value(F<D AND G>D), 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 B<E THEN element would be at Right of the sub-tree
|
||||
|
||||
Significance of BST:
|
||||
With every iteration, search space is reduced by 1/2 (half)
|
||||
Let no of nodes in a tree (n) be 8 then:
|
||||
n = 8 [8->4->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
|
|
@ -1,65 +1,68 @@
|
|||
# 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
|
||||
|
||||
# for setting left node
|
||||
def setLeft(self, node):
|
||||
def set_left(self, node):
|
||||
""" for setting left node """
|
||||
self.left = node
|
||||
|
||||
# for setting right node
|
||||
def setRight(self, node):
|
||||
def set_right(self, node):
|
||||
""" for setting right node """
|
||||
self.right = node
|
||||
|
||||
# for getting the left node
|
||||
def getLeft(self):
|
||||
def get_left(self):
|
||||
""" for getting the left node """
|
||||
return self.left
|
||||
|
||||
# for getting right node
|
||||
def getRight(self):
|
||||
def get_right(self):
|
||||
""" for getting right node """
|
||||
return self.right
|
||||
|
||||
# for setting data of a node
|
||||
def setData(self, data):
|
||||
def set_data(self, data):
|
||||
""" for setting data of a node """
|
||||
self.data = data
|
||||
|
||||
# for getting data of a node
|
||||
def getData(self):
|
||||
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())
|
||||
|
||||
# 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
|
||||
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())
|
||||
|
||||
# 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
|
||||
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.setLeft(Node(2))
|
||||
root.setRight(Node(3))
|
||||
root.left.setLeft(Node(4))
|
||||
root.set_left(Node(2))
|
||||
root.set_right(Node(3))
|
||||
root.left.set_left(Node(4))
|
||||
|
||||
print('Inorder Traversal:')
|
||||
inorder(root)
|
||||
|
|
Loading…
Reference in New Issue