LATEX 2ε Cheat Sheet Right Left y is the right child of z and x is the left child of y Rotate right at y, then left at z to balance. Algorithmic Analysis O(1) O(log n) O(n) O(n log n) O(n^2) O(n^3) O(2^n) O(n)! O(n^n) If the balance factor is greather than 1, it is either left left or left right. To check if it is left left, compare newly inserted node with the node in the left subtree root. If it is less than the left subtree root, it is left left. If it is greater than the left subtree root, it is left right. If the balance factor is less than -1, it is either right right or right left. To check if it is right right, compare newly inserted node with the node in the right subtree root. If it is greater than the right subtree root, it is right right. If it is less than the right subtree root, it is right left. Constant Logarithmic Linear Linearithmic Quadratic Cubic Exponential Factorial Polynomial Linear Structures - Average Case Structure Array Stack Queue Lists Trees Access O(1) O(n) O(n) O(n) O(log n) Search O(n) O(n) O(n) O(n) O(log n) Insert O(n) O(1) O(1) O(1) O(log n) Left & Right Rotation Pseudocode Delete O(n) O(1) O(1) O(1) O(log n) Trees & Traversals Inorder traversal visits the left subtree, then the root, then the right subtree. Preorder traversal visits the root, then the left subtree, then the right subtree. Postorder traversal visits the left subtree, then the right subtree, then the root. Levelorder traversal visits the nodes of each level from left to right. If there are n nodes in a tree, then the maximum height of the tree is n − 1. The minimum is f loor(log2 n). A binary tree is full if every node has either zero or two children. A binary tree is complete if every level is completely filled except possibly the last level, which is filled from left to right. A binary tree is perfect if it is both full and complete. AVL Trees AVL Trees are self balancing. The difference between heights of left and right subtrees cannot be more than one for all nodes. The height of an AVL Tree is always O(logn), where n is the number of nodes in the tree. To insert and balance: Assume n is the new node. Insert it as standard. Start at n, travel up to first unbalanced node. Let z be first unbalanced node, y be the child of z that comes on the path from w to z, and x be the grandchild of z that comes on the path from w to z. Perform appropriate rotations on subtree with root z. 4 possible cases: Left Left y is the left child of z and x is the left child of y. Rotate right at z to balance. Left Right y is the left child of z and x is the right child of y. Rotate left at y, then right at z to balance. Right Right y is the right child of z and x is the right child of y Rotate left at z to balance. Root is Node x. LeftRotate(Node* x) Node *y = x->right; Node *T2 = y->left; // Perform rotation y->left = x; x->right = T2; // Update heights x->height = max(height(x->left), height(x->right))+1; y->height = max(height(y->left), height(y->right))+1; // Return new root return y; RightRotate(Node* x) Node *y = x->left; Node *T2 = y->right; // Perform rotation y->right = x; x->left = T2; // Update heights x->height = max(height(x->left), height(x->right))+1; y->height = max(height(y->left), height(y->right))+1; // Return new root return y; B/B+ Trees In a B Tree, all leaves are at the same level. A B-Tree is defined by the term minimum degree t. Every node except the root must contain at least t − 1 keys. The root may contain at least 1 key. All nodes (including root) may contain at most 2t − 1 keys. The number of children of a node is equal to the number of keys in it plus 1. All keys of a node are sorted in increasing order. The child between two keys k1 and k2 contains all keys in the range from k1 and k2. A B-Tree grows and shrinks from the root, unlike a BST. Insertion of a node in a B-Tree happens only at a leaf. B+ Trees are a special case of B-Trees where the keys are stored in the leaves. The non-leaf nodes are used to index the leaves. Zig-Zig = Left Left and Zag-Zag = Right Right. However, Zag-Zig = Left Right and Zig-Zag = Right Left. Splay Trees A Splay Tree is a self-adjusting binary search tree with the additional property that recently accessed elements are quick to access again. It performs basic operations such as search, insertion, and deletion in O(logn) amortized time. Splay operation brings the recently accessed item to the root. It is performed after every operation. If the next element searched for is the same, it is returned immediately. Splay trees are good for when you may have many elements but only a select few are accessed most commonly. Red Black Trees A Red Black Tree is a self-balancing binary search tree. Each node of the binary tree has an extra bit, and that bit is often interpreted as the color (red or black) of the node. These color bits are used to ensure the tree remains approximately balanced during insertions and deletions. Every Red Black Tree follows these rules: 1. Every node is either red or black. 2. The root is black. 3. Every leaf (NULL) is black. 4. If a node is red, then both its children are black. 5. There are no two adjacent red nodes (A red node cannot have a red parent or red child). 6. For each node, all simple paths from the node to descendant leaves contain the same number of black nodes. The black height of a red-black tree is the number of black nodes from the root to a leaf. Leaf nodes are counted as black nodes. A red black tree of height h has black height >= h/2 Height of a red black tree with n nodes is h <= 2log2 (n + 1) For a newly inserted node x, x’s parent is its parent node. x’s sibling is its parent’s other child. x’s grandparent is the parent of its parent. x’s uncle is the other child of the grandparent. Heaps A heap is a tree-based data structure in which the tree is complete. A max-heap is a complete binary tree in which the value in each internal node is greater than or equal to the values in the children of that node (i.e. the root is the largest element). A min-heap is a complete binary tree in which the value in each internal node is less than or equal to the values in the children of that node (i.e. the root is the smallest element). For any node at position p, the left child is at position 2p + 1 and the right child is at position 2p + 2. A node at position c can find its parent at position ⌊(c − 1)/2⌋. Insertion & Deletion Insertion: 1. Insert the new element at the end of the heap. 2. Compare the new element with its parent; if they are in the correct order, stop. 3. If not, swap the element with its parent and return to the previous step. 4. Repeat until the element is in the correct position. temp->right = newNode; break; } else q.push(temp->right); } } // Heapify the new node HeapifyUp(newNode); Insert(Node* root, int key) Deletion: // Create a new node Node* newNode = new Node(key); 1. Replace the root of the heap with the last element on // If the tree is empty, make the new node the root the last level. if (root == NULL) 2. Compare the new root with its children; if they are in root = newNode; the correct order, stop. else 3. If not, swap the element with its largest (or smallest { // Do level order traversal until we find an empty depending on min/max) child and return to the previous step. // place and add the new node as a child of the // last node in level order. 4. Repeat until the element is in the correct position. queue<Node*> q; 5. Remove the old root. q.push(root); while (!q.empty()) Delete(Node* root, int key) { // Find the node to be deleted Node* temp = q.front(); Node* temp = root; q.pop(); Node* keyNode = NULL; if (temp->left == NULL) while (temp != NULL) { { temp->left = newNode; if (temp->data == key) break; { } keyNode = temp; else } q.push(temp->left); if (temp->right == NULL) if (keyNode == NULL) q.push(temp->left); { if (keyNode == NULL) q.push(temp->right); } // If the node is not found, return if (keyNode == NULL) return; // Replace the node to be deleted with the last node // in the heap int x = temp->data; DeleteDeepest(root, temp); keyNode->data = x; // Heapify the root node HeapifyDown(root); Sorting Heap sort inserts n elements into a heap and then removes them one by one to place in a now ordered array. HeapSort(int arr[], int n) // Build a heap from the input data. for (int i = 1; i < n; i++) HeapifyUp(arr, i); // One by one extract an element from heap for (int i = n - 1; i > 0; i--) { // Move current root to end swap(arr[0], arr[i]); // call max heapify on the reduced heap HeapifyDown(arr, i, 0); } Complexity: O(nlog2 (n))