Lecture Notes on 04 Nov 2020 * Exercise: Create a binary search tree with the following keys: 58, 37, 83, 23, 47, 79, 97, 11, 31, 59, 81, 87, 19, 62 * Operations and Algorithms on Binary Search Trees * Define a Node: - data - lchild - rchild * Create an Empty Tree - root = None * Insert elements in the Tree - create Node - find unique location in Tree and add - new addition always a leaf node * Find a node containing some data value in Tree - always start at the root - go left if data value is less than node value - go right if data value is greater than node value * Find minimum value in a Tree - go left until you hit a node that does not have a left child * Find maximum value in a Tree - go right until you hit a node that does not have a right child * Traverse a Tree - traverse a Tree means to visit every node just once - the following algorithms looks upon the Tree as a recursive data structure * Inorder Traversal - start at the root - recursively go to the left subtree - visit root and print - recursively go to the right subtree * Preorder Traversal - visit root and print - recursively go to the left subtree - recursively go to the right subtree * Postorder Traversal - recursively go to the left subtree - recursively go to the right subtree - visit root and print * Expression Tree: operands are the leaf nodes and the non-leaf nodes are the operators. Preorder traversal gives prefix notation. Postorder traversal gives postfix notation. Code for Binary Search Tree class Node (object): def __init__ (self, data): self.data = data self.lchild = None self.rchild = None # self.parent = None # self.visited = False class Tree (object): def __init__ (self): self.root = None # insert data into the tree def insert (self, data): new_node = Node (data) if (self.root == None): self.root = new_node return else: current = self.root parent = self.root while (current != None): parent = current if (data < current.data): current = current.lchild else: current = current.rchild # found location now insert node if (data < parent.data): parent.lchild = new_node else: parent.rchild = new_node # search for a node with given data def find (self, data): current = self.root while (current != None) and (current.data != data): if (data < current.data): current = current.lchild else: current = current.rchild return current # find the node with the minimum key def find_min (self): current = self.root parent = self.root while (current != None): parent = current current = current.lchild return parent # find the node with the maximum key def find_max (self): current = self.root parent = self.root while (current != None): parent = current current = current.rchild return parent # in order traversal - left, center, right def in_order (self, aNode): if (aNode != None): self.in_order (aNode.lchild) print (aNode.data) self.in_order (aNode.rchild) # pre order traversal - center, left, right def pre_order (self, aNode): if (aNode != None): print (aNode.data) self.pre_order (aNode.lchild) self.pre_order (aNode.rchild) # post order traversal - left, right, center def post_order (self, aNode): if (aNode != None): self.post_order (aNode.lchild) self.post_order (aNode.rchild) print (aNode.data)