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