• Depth: length of the unique path from root to node
• Height: length of the longest path from the node to a leaf
• Keep children in a linked list
• Preorder traversal: work at the node is done before its children are processed
• Postorder traversal: work at a node is performed after its children are evaluated
• Binary tree: no node can have more than two children o Average depth is O(rootN), O(logN) for binary search tree o Can maintain references to children cuz there’s only 2
• Example of a binary tree: expression tree o Leaves are operands, other nodes contain operators o Inorder traversal: recursively print left child, then parent, then right
• O(N) o Postorder traversal: recursively print left subtree, right subtree, then operator → O(N) o Preorder traversal: print operator, then recursively print the left and right subtrees o Constructing an expression tree from a postfix expression: read one symbol at a time; if operand, create a one-node tree and push it onto a stack. If operator, pop two trees T1, T2 from stack, and form a new tree whose root is the operator, and whose left and right children are T2 and T1; push new tree onto stack
• Binary search tree: binary tree with the property that for every node X, the value of all items in its left subtree are < X and the value of all items in the right subtree are > X o Contains: Uses O(logN) stack space o findMin, findMax: traverse all the way left or right from the root o insert: traverse down tree as would with contains, stick it at the end o remove: easy if leaf or has one child; if two children; replace data in node with smallest data of right subtree, and recursively delete that node o Lazy deletion: if expected number of deletions is small, just mark the node as deleted but don’t actually do anything; small time penalty as depth doesn’t really increase o Running time of all operations on a node is O(depth), and the average depth is O(logN) o If input is presorted,