Terms
Path - Path refers to the sequence of nodes along the edges of a tree
Root - The node at the top of the tree is called root.
. There is ONLY one root per tree
. There is Only one path from root node to any node.
Parent - Any node ( except the root node) has one edge upward to a node called parent.
Child - The node below a given node connected by its edge downward is called its child node.
Leaf - The node which does not have any child node is called the leaf node.
Subtree - Subtree represents the descendants of a node.
Visiting - Visiting refers to checking the value of a node when control is on the node.
Traversing - Traversing means passing through nodes in a specific order.
Levels - Level of a node represents the generation of a node. If the root node is at level 0, then its next child is at level1,
its grandchild is at level 2, and so on.
this is height of a three, from 0.
Keys - Key represents a value of a node based on which a search operation is to be carried out for a node.
Binary Search Tree Representation
A node's left child must have a value less than its parent's value and the node's right child must have a value greater than its parent value.
golang code
Basic Operations
Insert - Insert an element in a tree/create a tree
Search - Searches an element in a tree
Preorder Traversal - Traverses a tree in a pre-order manner.
Inorder Traversal - Traverses a tree in an in-order manner.
Postorder Traversal - Traverses a tree in a post-order manner.
Insert Operation
The very first insertion creates the tree. Afterwards, whenever an element is to be inserted, first locate its proper location.
Start searching from the root node, the if the data is less than the key value, search for the empty location in the left subtree and insert the data.
Otherwise, search for the empty location in the right subtree and insert the data.
golang code
Search Operation
Whenever an element is to be searched, start searching fromo the root node, then if the data is less than the key value, search for the element in the left
subtree. Otherwise, search for the element in the right subtree. Follow the same algorighm for each node.
golang code
Traverse Operation
Traversal is a process to visit all the nodes of a tree.Because, all nodes are connected via edges we always start from the root node.
That is, we cannot randomly access a node in a tree. There are three ways which we use to traverse a tree:
.In-order Traversal
.Pre-order Traversal
.Post-order Traversal
In-order Traversal
In this traversal method, the left subtree is visited first, then the root and later the right subtree.
* We should always remember that every node may represent a subtree itself.
If a binary tree is traversed in-order, the output will produce sorted key values in an ascending order.
We start from A, and following in-order traversal, we move to its left subtree B. B is also traversed in-order.
The process goes on until all the nodes are visited. The output of inorder traversal of this tree will be:
D -> B -> E -> A -> F -> C -> G
Pre-order Traversal
In this traversal method, the root node is visited first, then the left subtree and finally the right subtree.
We start from A, and following pre-order traversal, we first visit A itself and then move to its left subtree B.
B is also traversed pre-order. The process goes on until all the nodes are visited.
The output of pre-order traversal of this tree will be:
A -> B -> D -> E -> C -> F -> G
Post-order Traversal
In this traversal method, the root node is visited last, hense the name.
First we traverse the left subtree, then the right subtree and finally the root node.
We start from A, and following Post-order traversal, we first visit the left subtree B.
B is also traversed post-order. The process goes on until all the nodes are visited.
The output of post-order traversal of this tree will be:
D -> E -> B -> F -> G -> C -> A
Golang:
1 package binary_search_tree 2 3 import ( 4 "fmt" 5 ) 6 7 type Node struct { 8 Data int 9 LeftChild *Node 10 RightChild *Node 11 } 12 13 type BinarySearchTree struct { 14 Root *Node 15 } 16 17 func (bst *BinarySearchTree) Insert(data int) { 18 tmpNode := &Node{data, nil, nil} 19 20 if bst.Root == nil { 21 bst.Root = tmpNode // create root node 22 return 23 } 24 25 var parent *Node 26 current := bst.Root 27 28 for true { 29 parent = current 30 if data < parent.Data { 31 current = parent.LeftChild 32 if current == nil { 33 parent.LeftChild = tmpNode 34 return 35 } 36 } else { 37 current = parent.RightChild 38 if current == nil { 39 parent.RightChild = tmpNode 40 return 41 } 42 } 43 } 44 } 45 46 func (bst *BinarySearchTree) Search(data int) *Node { 47 if bst.Root == nil { 48 fmt.Println("binary search tree is empty.") 49 return nil 50 } 51 52 fmt.Printf("Visiting elements %d, path:", data) 53 current := bst.Root 54 55 for current.Data != data { 56 if current != nil { 57 fmt.Printf(" -> %d", current.Data) 58 } 59 60 if data < current.Data { 61 current = current.LeftChild 62 } else { 63 current = current.RightChild 64 } 65 66 if current == nil { 67 fmt.Printf(" >> %d not found\n", data) 68 return nil 69 } 70 } 71 72 fmt.Printf(" -> %d found\n", data) 73 return current 74 } 75 76 func traverseInOrder(root *Node) { 77 if root == nil { 78 return 79 } 80 81 // visit left child 82 if root.LeftChild != nil { 83 traverseInOrder(root.LeftChild) 84 } 85 86 // visit root 87 fmt.Printf(" %d", root.Data) 88 89 // visit right child 90 if root.RightChild != nil { 91 traverseInOrder(root.RightChild) 92 } 93 } 94 95 func traversePreOrder(root *Node) { 96 if root == nil { 97 return 98 } 99 100 // visit root 101 fmt.Printf(" %d", root.Data) 102 103 // visit left child 104 if root.LeftChild != nil { 105 traversePreOrder(root.LeftChild) 106 } 107 108 // visit right child 109 if root.RightChild != nil { 110 traversePreOrder(root.RightChild) 111 } 112 } 113 114 func traversePostOrder(root *Node) { 115 if root == nil { 116 return 117 } 118 119 // visit left child 120 if root.LeftChild != nil { 121 traversePostOrder(root.LeftChild) 122 } 123 124 // visit right child 125 if root.RightChild != nil { 126 traversePostOrder(root.RightChild) 127 } 128 129 // visit root 130 fmt.Printf(" %d", root.Data) 131 } 132 133 func (bst *BinarySearchTree) TraverseInOrder() { 134 if bst.Root == nil { 135 fmt.Println("tree is empty.") 136 } 137 fmt.Print("inorder traversal: ") 138 traverseInOrder(bst.Root) 139 fmt.Println("") 140 } 141 142 func (bst *BinarySearchTree) TraversePreOrder() { 143 if bst.Root == nil { 144 fmt.Println("tree is empty.") 145 } 146 fmt.Print("preorder traversal: ") 147 traversePreOrder(bst.Root) 148 fmt.Println("") 149 } 150 151 func (bst *BinarySearchTree) TraversePostOrder() { 152 if bst.Root == nil { 153 fmt.Println("tree is empty.") 154 } 155 fmt.Print("postorder traversal: ") 156 traversePostOrder(bst.Root) 157 fmt.Println(" ") 158 }
Test:
package main import ( bst "binary_search_tree" ) func createTree(bst *bst.BinarySearchTree) { bst.Insert(27) bst.Insert(35) bst.Insert(14) bst.Insert(19) bst.Insert(42) bst.Insert(31) bst.Insert(10) bst.Insert(8) bst.Insert(74) bst.Insert(40) bst.Insert(23) bst.Insert(18) } func search(bst *bst.BinarySearchTree) { bst.Search(31) bst.Search(19) bst.Search(42) bst.Search(10) bst.Search(16) bst.Search(8) bst.Search(74) bst.Search(23) bst.Search(71) } func traverse(bst *bst.BinarySearchTree) { bst.TraverseInOrder() bst.TraversePreOrder() bst.TraversePostOrder() }
func main() { bst := &bst.BinarySearchTree{} // 27 // / \ // 14 35 // / \ / \ // 10 19 31 42 // / / \ / \ // 8 18 23 40 74 createTree(bst) search(bst) traverse(bst) }
output:
Visiting elements 31, path: -> 27 -> 35 -> 31 found Visiting elements 19, path: -> 27 -> 14 -> 19 found Visiting elements 42, path: -> 27 -> 35 -> 42 found Visiting elements 10, path: -> 27 -> 14 -> 10 found Visiting elements 16, path: -> 27 -> 14 -> 19 -> 18 >> 16 not found Visiting elements 8, path: -> 27 -> 14 -> 10 -> 8 found Visiting elements 74, path: -> 27 -> 35 -> 42 -> 74 found Visiting elements 23, path: -> 27 -> 14 -> 19 -> 23 found Visiting elements 71, path: -> 27 -> 35 -> 42 -> 74 >> 71 not found inorder traversal: 8 10 14 18 19 23 27 31 35 40 42 74 preorder traversal: 27 14 10 8 19 18 23 35 31 42 40 74 postorder traversal: 8 10 18 23 19 14 31 40 74 42 35 27