If you need to maintain a list of objects that are sorted and unique
& if you need to be able to quickly insert and retrieve objects to and from this list
-- the ideal data structure will be a tree set (or a tree map, if you consider each object a key and associate another object called a value to it).
Implementation in Java : TreeSet<T>, TreeMap<K, V>
A binary tree is a BST iff, for every node n, in the tree:
- All keys in n's left subtree are less than the key in n, and
- all keys in n's right subtree are greater than the key in n.
Insertion - O(log n)
From root all the way to leaf, compare and decide which side to go.
The new node will always a leaf node.
Deletion - O(1)-O(log n)
If n has no children, we only have to remove n from the tree.
If n has a single child, we remove n and connect its parent to its child.
If n has two children, we need to :
Find the smallest node that is larger than n, call it m.
Remove m from the tree, Replace the value of n with m.
(think : m will always have no left child)
Retrieval - O(log n)
For BST (binary search trees),
although the average-case times for the lookup, insert, and delete methods are all O(log N), where N is the number of nodes in the tree,
the worst-case time is O(N).
We can guarantee O(log N) time for all three methods by using a Balanced Tree -- a tree that always has height O(log N)-- instead of a binary search tree.
Balanced Tree — AVL tree, 2-4 tree, red-black tree and B trees
"fully populated" means that every internal node has exactly two children, and all terminal nodes are at the same depth.
1 class BST { 2 private class Node { 3 int val; 4 Node left; 5 Node right; 6 7 public Node() {} 8 9 public Node(int val) { 10 this.val = val; 11 } 12 13 public void copy(Node n) { 14 this.val = n.val; 15 this.left = n.left; 16 this.right = n.right; 17 } 18 } 19 20 public static Node root; 21 22 // Insert, O(lg n) 23 public void insert(int val) { 24 root = insert(root, val); 25 } 26 27 private Node insert(Node node, int val) { 28 if (node == null) { 29 node = new Node(val); 30 return node; 31 } 32 33 if (node.val > val) node.left = insert(node.left, val); 34 if (node.val < val) node.right = insert(node.right, val); 35 36 return node; 37 } 38 39 //Search, O(lg n) 40 public Node search(int val) { 41 return search(root, val); 42 } 43 44 private Node search(Node node, int val) { 45 if (node == null) return null; 46 47 if (node.val == val) return node; 48 else if (node.val > val) return search(node.left, val); 49 else return search(node.right, val); 50 } 51 52 //Delete, O(1) - O(lg n) 53 public Node delete(int val) { 54 root = delete(root, val); 55 return root; 56 } 57 58 private Node delete(Node node, int val) { 59 if (node == null) return null; 60 if (node.val > val) node.left = delete(node.left, val); 61 else if (node.val < val) node.right = delete(node.right, val); 62 63 else { 64 Node del = new Node(); 65 del.copy(node); 66 67 if (node.left == null) {node.copy(node.right); node.right = null; return node;} 68 if (node.right == null) {node.copy(node.left); node.left = null; return node;} 69 70 node.copy(min(del.right)); 71 node.right = deleteMin(del.right); 72 node.left = del.left; 73 } 74 return node; 75 } 76 77 private Node min (Node node) { 78 if (node == null || node.left == null) return node; 79 return min(node.left); 80 } 81 82 // remove the smallest node and return new root; 83 private Node deleteMin(Node node) { 84 if (node == null) return null; 85 if (node.left == null) { 86 return node.right; // node is deleted 87 } 88 node.left = deleteMin(node.left); 89 return node; 90 } 91 }