overview tree traversals data structures and algorithms binary search 2020 10 01 lecture 10 binary search trees overview recap definitions binary tree: every node has at most 2 successors (empty tree is also a binary tree) tree traversals depth of a node x : length (number of edges) of a path from the root to x binary search height of a node x : length of a maximal path from x to a leaf height of a tree: binary search trees height of its root number of levels is height plus one
binary tree: linked implementation binary tree: alternative implementation linked data structure with nodes containing • x . key from a totally ordered set remember the heap • x . left points to left child of node x • x . right points to right child of node x binary trees can be represented as arrays using the level numbering • x . p points to parent of node x if x . p = nil then x is the root T . root points to the root of the tree (nil if empty tree) tree traversals preorder traversal: pseudo-code visit first the node and next its successors input: node v in a binary tree how can we visit all nodes in a tree exactly once? Algorithm preOrder( v ): visit( v ) we will focus on binary trees if v . left � = nil then preOrder( v . left ) if v . right � = nil then preOrder( v . right ) preOrder is in O ( n ) with n number of nodes
postorder traversal: pseudo-code inorder traversal: pseudo-code visit all successors and next the node itself input: node v in binary tree visit left sub-tree, then node itself, then right sub-tree Algorithm postOrder( v ): Algorithm inOrder( v ): if v . left � = nil then if not v = nil then postOrder( v . left ) inOrder( v . left ) if v . right � = nil then visit( v ) postOrder( v . right ) inOrder( v . right ) visit( v ) postOrder is in O ( n ) with n number of nodes Euler traversal: idea Euler traversal: pseudo-code instantiate visitLeft, visitBelow, visitRight as desired generic description of traversals Algorithm eulerTour( v ): + vistLeft( v ) if v . left � = nil then × / L R eulerTour( v . left ) B − 3 8 4 visitBelow( v ) if v . right � = nil then 5 2 eulerTour( v . right ) visitRight( v )
overview look-up table tree traversals ordered array so with A [1] , . . . , A [ n ] increasing, for storing items from a ordered dictionary binary search operations for searching, adding, deleting binary search trees searching by binary search binary search binary search: time complexity search for key k in a sorted array A [ l . . . r ] recurrence equation: if l > r then return that k is not present � d if n = 1 T ( n ) = T ( n 2 ) + c if n > 1 if l ≤ r then let i := ⌊ ( l + r ) / 2 ⌋ and compare m := A [ i ] with k • if k < m then binary search k in A [ l . . . i − 1] binary search is in O (log n ) • if k = m then return that k is at i • if k > m then binary search k in A [ i + 1 . . . r ] for instance searching in array of size 25000 takes 15 steps this describes a recursive procedure; alternative is an interative procedure
look-up table overview tree traversals searching is in O (log n ) binary search adding and deleting are in O ( n ) (why?) use in case of few updates binary search trees otherwise: tree structure binary search tree binary search tree: example we assume the keys or labels come from a totally ordered set 6 binary tree with the 2 9 binary search tree property: for every node x with key k we have: 1 4 8 its left sub-tree contains only keys less than (equal to) k its right sub-tree contains only keys greater than (equal to) k
questions searching in a binary search tree: example look for key 4 what are the binary search trees with keys 1 , 2 , 3 < 6 give a min-heap that is not a binary search tree 2 > 9 give a binary search tree that is not a min-heap 1 4 8 searching in a binary search tree alternative: iterative version input: node v in binary search tree, and key k Algorithm treeSearchIt( v , k ): Algorithm treeSearch( v , k ): while v � = nil and k � = v . key do if v = nil or k = v . key then if k < v . key then return v v := v . left if k < v . key then else return treeSearch( v . left , k ) v := v . right else return v return treeSearch( v . right , k ) what is the worst-case running time of treeSearch? in O ( h )
binary search tree: search smallest key binary search tree: search largest key as far as possible to the left as far as possible to the right 6 6 2 9 2 9 1 4 8 1 4 8 minimum and maximum: pseudo-code question input: node x not nil in binary search tree output: node with the smallest or largest key in the subtree rooted at input Algorithm treeMimimum( x ): given a node while x . left � = nil do x := x . left how to compute the node that is visited next in inorder traversal? return x Algorithm treeMaximum( x ): while x . right � = nil do x := x . right return x
successor: pseudo-code time complexity: height is crucial input: node x Algorithm treeSuccessor( x ): if x . right � = nil then search, minimum, maximum, successor, predecessor return treeMimimum( x . right ) y := x . p can all be implemented in O ( h ) with h the height of the BST while y � = nil and x = y . right do x := y y := y . p return y what happens if x contains the largest key? what is the worst-case running time of treeSuccessor? adding: example adding a node to a binary search tree Algorithm insert( T , z ): y := nil add node with key 5 x := T . root while not x = nil do 6 6 < y = x 2 9 2 9 if z . key < x . key then > x := x . left 1 4 8 1 4 8 else > x := x . right 5 z . p := y if y = nil then T . root := z else if z . key < y . key then y . left := z else y . right := z
example removal easy case example removal difficult case 6 6 6 7 remove remove 2 9 2 8 2 9 2 9 1 4 8 1 4 8 1 4 8 1 4 7 7 7 removal removing a node from a binary search tree Algorithm treeDelete( T , z ): if z . left = nil then transplant( T , z , z . right ) remove node z from binary search tree T else if z . right = nil then transplant( T , z , z . left ) if z has at most 1 child then transplant else if z has 2 children then take treeMinimum of right subtree y := treeMinimum( z . right ) transplant that one on the place of z if y . p � = z then transplant( T , y , y . right ) y . right := z . right y . right . p := y transplant( T , z , y ) y . left := z . left y . left . p := y
and pseudo-code for transplant worst-case time complexity Algorithm transplant( T , u , v ): the height of the tree is crucial: if u . p = nil then T . root := v worst-case time complexity for searching, adding, deleting all in O ( height ) else if u = u . p . left then u . p . left := v so worst-case in O ( n ) else u . p . right := v if v � = nil then v . p := u . p binary search tree: worst-case time complexity binary search trees: further improvements because the height is crucial for the time complexity of the operations operations for searching, adding, deleting all in O ( height ) there are many subclasses of balanced binary search tree best case: height is in O (log n ) AVL trees, red-black trees, splay trees worst case: height is in O ( n ) compromise between the optimal and arbitrary binary search tree expected case: height is in O (log n ) (no proof)
Recommend
More recommend