|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: 3.4 Binary search trees |
| 4 | +--- |
| 5 | + |
| 6 | +* doubly-linked lists supported insertion and deletion in O(1) but linear query time |
| 7 | +* sorted lists support logarithmic query time but linear time update |
| 8 | +* binary search tree: **fast search and flexible update** |
| 9 | +* two pointer for each element: the median elements above and below the given node |
| 10 | +* a rooted **binary tree** is recursively defined as either |
| 11 | + * (1) being empty, or |
| 12 | + * (2) consisting of a node called the root, together with two rooted binary trees called the left and right subtrees |
| 13 | +* a **binary search tree** labels each node in a binary tree such that for any node labeled x: |
| 14 | + * all nodes in the left subtree of x have keys < x |
| 15 | + * all nodes in the right subtree of x have keys > x |
| 16 | +* nodes have a left and right pointer field (optional parent pointer) and a data field |
| 17 | + |
| 18 | +### searching |
| 19 | + |
| 20 | +* start at the root |
| 21 | +* unless root is what we're looking for proceed either left or right depending upon whether x occurs before or after the root key |
| 22 | +* runs in O(h) time where h is the height of the tree |
| 23 | + |
| 24 | +### minimum and maximum |
| 25 | + |
| 26 | +* the minimum element must be the leftmost descendent of the root |
| 27 | +* the maximum element must be the rightmost descendent of the root |
| 28 | +* runs in O(h) time where h is the height of the tree |
| 29 | + |
| 30 | +### tree traversal |
| 31 | + |
| 32 | +* listing the labels of the tree nodes |
| 33 | +* in-order: recursively |
| 34 | + * process left subtree first |
| 35 | + * then process actual item |
| 36 | + * process right subtree last |
| 37 | +* pre/post order by moving actual item before/after processing subtrees |
| 38 | + |
| 39 | +### insertion |
| 40 | + |
| 41 | +* there is only one place to insert an item x into a binary search tree T where we know we can find it again |
| 42 | +* we must replace the NULL pointer found in T after an unsuccessful query for the key k |
| 43 | +* take care to assign the correct left/right pointer |
| 44 | +* runs in O(h) time where h is the height of the tree |
| 45 | + |
| 46 | +### deletion |
| 47 | + |
| 48 | +* three cases |
| 49 | +* leaf node: zero children, simply remove it |
| 50 | +* node with one child: replace node with child |
| 51 | +* node with two children: relabel this node with the key of its immediate successor (leftmost descendant in the right subtree) |
| 52 | +* TODO: add actual delete algorithm |
| 53 | +* takes at most two searches and some contant time: O(h) |
| 54 | + |
| 55 | +### performance |
| 56 | + |
| 57 | +* best case if the tree is perfectly balanced: h = log(n) |
| 58 | +* worst case: inserting elements in sorted order: h = n |
| 59 | +* based on all n! orderings there's a high probablity to get a log(n) tree |
| 60 | +* randomization can be helpful |
| 61 | + |
| 62 | +### balanced search trees |
| 63 | + |
| 64 | +* worst case out of our hands as it depends on **user input** |
| 65 | +* insert/delete can be implemented in a way that adjusts after each operation |
| 66 | +* keeps the tree close enough to be balanced so the max height is logarithmic |
| 67 | +* all dictionary operations (search, insert, delete) take O(log n) time |
| 68 | +* concrete implementations: red-black trees, avl trees, splay trees |
0 commit comments