Data Structures, Algorithms, Memory Layouts, and Heap Analysis
Graph Data Structures and Representations
Fundamental Definitions:
A graph is mathematically defined as an ordered pair , where is the set of vertices (also called nodes or points) and is the set of edges (also called lines or connections).
An edge connects two vertices and . The vertices and of an edge are called the endpoints of the edge.
Graphs can contain loops, which are defined as edges that connect a vertex to itself (an edge having the same node twice as its endpoints).
A vertex may belong to no edge, existing as an isolated node in .
If is empty, then the graph is empty.
The order of a graph is denoted by , which represents the total number of its vertices.
The quantity represents the total number of edges in .
The overall size of a graph is defined as the sum .
Two vertices and are adjacent if is an edge in .
Directed vs. Undirected Graphs:
Undirected Graphs: Edges have no orientation. An edge connects and symmetrically.
Directed Graphs: Edges possess direction. If an edge connects and , vertex is called the tail of the edge and vertex is called the head of the edge. The edge is said to join and , or be incident on and incident on y$.\n\n* **Adjacency-List Representation**:\n * Consists of an array Adj|V|u \in V.\n * For each vertex u \in VAdj[u]vEuv.\n * Adj[u]uG.\n * **Memory Usage**: Requires |V| + |E|G.\n * **Search Performance**: Determining whether a given edge (u, v)GvAdj[u], which is slower than matrix lookup.\n * **Weighted Graphs**: For graphs where each edge has an associated weight given by a weight function w: E \rightarrow \mathbb{R}w(u, v)(u, v) \in Evu's adjacency list.\n\n* **Adjacency-Matrix Representation**:\n * Consists of an n \times nA = (A_{ij})n = |V|.\n * The matrix element A_{ij}ij.\n * For an undirected graph GA_{ij} = A_{ji}.\n * **Memory Usage**: Requires |V| \times |V||V|^2) memory space.\n * **Search Performance**: Checking for edge existence takes O(1)A_{uv}, but at the cost of higher memory consumption.\n\n* **Concrete Representation Examples**:\n * **Undirected Graph Example**: An undirected graph G57 edges.\n * Vertices: {1, 2, 3, 4, 5}.\n * Adjacency-List Representation:\n * 1 \rightarrow 2 \rightarrow 5\n * 2 \rightarrow 1 \rightarrow 5 \rightarrow 3 \rightarrow 4\n * 3 \rightarrow 2 \rightarrow 4\n * 4 \rightarrow 2 \rightarrow 5 \rightarrow 3\n * 5 \rightarrow 4 \rightarrow 1 \rightarrow 2\n * Adjacency-Matrix Representation:\n * Row 1[0, 1, 0, 0, 1]\n * Row 2[1, 0, 1, 1, 1]\n * Row 3[0, 1, 0, 1, 0]\n * Row 4[0, 1, 1, 0, 1]\n * Row 5[1, 1, 0, 1, 0]\n * **Directed Graph Example**: A directed graph G68 edges.\n * Vertices: {1, 2, 3, 4, 5, 6}.\n * Adjacency-List Representation:\n * 1 \rightarrow 2 \rightarrow 4\n * 2 \rightarrow 5\n * 3 \rightarrow 6 \rightarrow 5\n * 4 \rightarrow 2\n * 5 \rightarrow 4\n * 6 \rightarrow 6\n * Adjacency-Matrix Representation:\n * Row 1[0, 1, 0, 1, 0, 0]\n * Row 2[0, 0, 0, 0, 1, 0]\n * Row 3[0, 0, 0, 0, 1, 1]\n * Row 4[0, 1, 0, 0, 0, 0]\n * Row 5[0, 0, 0, 1, 0, 0]\n * Row 6[0, 0, 0, 0, 0, 1]\n\n# Binary Operations and Bit Masking\n\n* **Bitwise Operations and Truth Tables**:\n * **Bitwise OR (|11.\n * Rules: A | 1 \implies 1A | 0 \implies A\n * **Bitwise AND ($\&$)**: Evaluates to 11.\n * Rules: A \& 1 \implies AA \& 0 \implies 0\n * **Bitwise XOR (\hat{\ }1 if operands are different.\n * Rules: A \hat{\ } 1 \implies \sim AAA \hat{\ } 0 \implies A\n * **Complete Truth Table**:\n * Input (A=1, B=0)A|B = 1A\&B = 0A \hat{\ } B = 1\n * Input (A=0, B=0)A|B = 0A\&B = 0A \hat{\ } B = 0\n * Input (A=1, B=1)A|B = 1A\&B = 1A \hat{\ } B = 0\n * Input (A=0, B=1)A|B = 1A\&B = 0A \hat{\ } B = 1\n\n* **Bit Masking and Integer Representation**:\n * Decimal 1500001111_2 (base-2).\n * Decimal 15\text{0x0F} in hexadecimal format (base-16).\n * **Nibble**: A 4\text{-bit} aggregation or half an octet. It is also termed a half-byte or semi-octet.\n * A single hexadecimal digit (0\text{--}\text{F}, called a hex digit) represents exactly one nibble.\n * **High Nibble**: Contains the more significant bits of a byte. For decimal 1500001111_20000_2\text{0x0} is the high nibble.\n * **Low Nibble**: Contains the less significant bits of a byte. For decimal 1500001111_21111_2\text{0xF} is the low nibble.\n\n# Abstract Data Types: Stacks and Queues\n\n* **The Stack Abstract Data Type**:\n * **LIFO Model**: Last-In, First-Out dynamic set where the element deleted from the set is the one most recently inserted.\n * Attributes: Has a top pointer (`S.top`), a base pointer, a length, and a maximum value for length n.\n * **Stack API**:\n * `PUSH(S, x)`: Takes stack SxxS, and `S.top` is incremented.\n * `POP(S)`: Takes stack S. Returns the value stored at `S.top`, and `S.top` is decremented.\n * `STACK-EMPTY(S)`: Returns `True` if S is empty (`S.top == 0`), otherwise returns `False`.\n * **Array Implementation**:\n * Implemented using an array A[1..n]n elements.\n * Attribute `S.top` indexes the most recently inserted element.\n * Stack consists of elements S[1..S.\text{top}].\n * S[1]S[S.\text{top}] is the element at the top.\n * When `S.top == 0`, the stack contains no elements and is empty.\n * **Underflow**: Occurs when attempting to pop an empty stack (`S.top == 0`).\n * **Overflow**: Occurs when attempting to push onto a full stack (`S.top == n`).\n * **Execution Walkthrough Example**:\n * (a) Stack S4[15, 6, 2, 9]9, `S.top = 4`.\n * (b) Stack S[15, 6, 2, 9, 17, 3], `S.top = 6`.\n * (c) Stack S33617, `S.top = 5`.\n * **Time Complexity**: All stack operations (`PUSH`, `POP`, `STACK-EMPTY`) run in O(1) constant time.\n\n* **The Queue Abstract Data Type**:\n * **FIFO Model**: First-In, First-Out dynamic set where the element deleted is the one that has been in the set the longest.\n * Attributes: Has a tail pointer (`Q.tail`), a head pointer (`Q.head`), and a length (`Q.length`).\n * **Queue API**:\n * `ENQUEUE(Q, x)`: Takes queue QxxQ1 (wrapping around if necessary).\n * `DEQUEUE(Q)`: Takes queue Q1 (wrapping around if necessary).\n * **Array Implementation Algorithms**:\n * Implemented using array Q[1..n]Q[1..12]).\n * `ENQUEUE(Q, x)` algorithm:\n 1. `Q[Q.tail] = x`\n 2. `if Q.tail == Q.length`\n 3. ` Q.tail = 1`\n 4. `else Q.tail = Q.tail + 1`\n * `DEQUEUE(Q)` algorithm:\n 1. `x = Q[Q.head]`\n 2. `if Q.head == Q.length`\n 3. ` Q.head = 1`\n 4. `else Q.head = Q.head + 1`\n 5. `return x`\n * **Time Complexity**: All queue operations (`ENQUEUE`, `DEQUEUE`) run in O(1) constant time.\n\n# Array Memory Layouts, Multi-Dimensional Arrays, and Sparse Matrices\n\n* **Multi-Dimensional Array Access Patterns**:\n * **Row-Major Order**:\n * Mapping function maps base address and indices to memory address.\n * Elements of row 012, etc.\n * If the array is a matrix, it is stored by rows.\n * **Column-Major Order**:\n * Mapping function obtains offset by evaluating j \times r + irij is column index).\n * If the array is a matrix, it is stored by columns.\n * **General Element Locating Formula**:\n * \text{Address}(\text{Array}[i, j]) = \text{Base Address} + ((\text{Rows above}) \times \text{Row size} + \text{Elements to left}) \times \text{Element size}\n * Formal layout: \text{Address}([i, j]) = \text{Base}([0, 0]) + (((i - \text{low}_1) \times \text{size}_2) + (j - \text{low}_2)) \times \text{element_size}\n * **Three-Dimensional Array Indexing Example**:\n * Matrix size Z[100, 100, 100].\n * First element of first column in first matrix: Z[1, 1, 1].\n * The first 100h1Z[:, 1, 1].\n * First matrix accessed with 3rd index: Z[:, :, 1]Z[:, :, 100].\n\n* **Arrays of Arrays Implementation**:\n * **C Language Code Structure**:\n * Array declarations:\n * `int a[6] = {20, 6, 6, 20, 14, 7};`\n * `int b[6] = {11, 22, 120, 1, 8};` (last element uninitialized, defaults to 0)\n * `int c[6] = {0};` (all elements initialized to 0)\n * Pointer-array declaration: `int* TwoD1[3] = {a, b, c};`\n * Fixed 2D array declaration: `int TwoD2[3][6];`\n * Iterative copy assignment: `TwoD2[i][j] = TwoD1[i][j]`\n * Data sizes: `sizeof(int*)` evaluates to pointer size (e.g., 8\,\text{bytes}4\,\text{bytes}.\n * **Java Language Code Structure**:\n * Array declarations:\n * `int[] a = {20, 6, 6, 20, 14, 7};`\n * `int[] b = {11, 22, 120, 1, 8, 0};` (padded to match size)\n * `int[] c = {0, 0, 0, 0, 0, 0};`\n * Pointer-array equivalent: `int[][] TwoD1 = {a, b, c};` (array of references to 1D arrays)\n * Fixed size allocation: `int[][] TwoD2 = new int[3][6];`\n * Memory estimation: Primitive `int` is 4\,\text{bytes}; array references estimated using `Integer.BYTES * 6`.\n\n* **Rectangular vs. Irregular (Jagged) Arrays**:\n * **Rectangular Array**: A multi-dimensional array in which all rows have identical numbers of elements, and all columns have identical numbers of elements.\n * **Jagged (Irregular) Array**: An array in which two or more rows have different numbers of elements, represented physically via an array of arrays.\n * **Language Support**:\n * C, C++, and Java support jagged arrays.\n * C# supports both rectangular arrays and jagged arrays.\n\n* **Array Slices**:\n * A slice is a substructure of an array; it acts strictly as a referencing mechanism.\n * Slices are useful in languages that provide native built-in array operations.\n * **Python Examples**:\n * `vector = [2, 4, 6, 8, 10, 12, 14, 16]`\n * `vector[3:6]` creates a three-element array `[8, 10, 12]`.\n * `mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]`\n * `mat[0][0:2]` selects the first and second elements of the first row of `mat` (`[1, 2]`).\n\n* **Sparse Matrices**:\n * Sparse matrices store non-zero elements only, skipping zero entries to conserve memory.\n * **Representation Method 1 (Coordinate Format)**:\n * Uses a struct containing row, column, and value:\n * `struct Element { int row; int col; int val; };`\n * `struct Element sparse[10];`\n * Assignment: `e1.row = 0; e1.col = 0; e1.val = 1; sparse[0] = e1;`\n * **Representation Method 2 (Column-Value Format)**:\n * Uses a struct containing column and value:\n * `struct Element { int col; int val; };`\n * `struct Element sparse[5];`\n\n# Heap Data Structure, Heapsort, and Priority Queues\n\n* **The Binary Heap Data Structure**:\n * A binary heap is an array object A that can be viewed as a nearly complete binary tree.\n * Each node of the tree corresponds to an element of array A\n * The tree is completely filled on all levels except possibly the lowest, which is filled from the left up to a point.\n * Heap Object Attributes:\n * `A.length`: Gives the total number of elements in array A\n * `A.heap-size`: Represents how many valid elements of the heap are stored within array A\n * A[1..A.\text{length}]A[1..A.\text{heap-size}]0 \le A.\text{heap-size} \le A.\text{length}).\n * Element Requirements: Element types must allow a total ordering comparison, and elements must be at least ordinal 1$.
Root of the tree is stored at index .
Bitwise Arithmetic for Heap Index Navigation:
PARENT(i): Computes by shifting binary representation of right by bit position (divides by and takes floor).LEFT(i): Computes by shifting binary representation of left by bit position.RIGHT(i): Computes by shifting binary representation of left by bit position and setting low-order bit to 1$.\n\n* **Max-Heaps vs. Min-Heaps**:\n * **Max-Heap Property**: For every node i other than the root:\n * A[\text{PARENT}(i)] \ge A[i]\n * Value of a node is at most the value of its parent.\n * Largest element in a max-heap is stored at the root (A[1]).\n * Subtree rooted at a node has values no larger than that contained at the node itself.\n * **Min-Heap Property**: For every node i other than the root:\n * A[\text{PARENT}(i)] \le A[i]\n * Smallest element in a min-heap is stored at the root (A[1]).\n * **Height Definitions**:\n * Height of a node in a heap: The number of edges on the longest simple downward path from the node to a leaf.\n * Height of a heap: Height of its root, equal to \lfloor \log_2(n) \rfloorn\text{-element} heap.\n * Basic operations on heaps run in time at most proportional to height of heap: O(\log_2(n)).\n\n* **Maintaining the Max-Heap Property (`MAX-HEAPIFY`)**:\n * Key procedure to maintain max-heap property, running in O(\log_2(n)) time (proportional to heap height).\n * Inputs: Array Ai\n * Precondition: Assumes binary trees rooted at `LEFT(i)` and `RIGHT(i)` are max-heaps, but A[i] might be smaller than its children, violating the max-heap property.\n * Logic: Lets value at A[i]i satisfies max-heap property.\n * Step-by-step Execution:\n 1. Determine largest of A[i]A[\text{LEFT}(i)]A[\text{RIGHT}(i)], storing its index in `largest`.\n 2. If A[i]i is already a max-heap; procedure terminates.\n 3. Otherwise, one child contains `largest`; exchange A[i]A[\text{largest}].\n 4. Call `MAX-HEAPIFY(A, largest)` recursively on affected subtree.\n * **Pseudo-code**:\n ```\n MAX-HEAPIFY(A, i)\n 1 l = LEFT(i)\n 2 r = RIGHT(i)\n 3 if l <= A.heap-size and A[l] > A[i]\n 4 largest = l\n 5 else largest = i\n 6 if r <= A.heap-size and A[r] > A[largest]\n 7 largest = r\n 8 if largest != i\n 9 exchange A[i] with A[largest]\n 10 MAX-HEAPIFY(A, largest)\n ```\n * Trace Example: `MAX-HEAPIFY(A, 2)` with `A.heap-size = 10`. Node 2A[2] = 4A[4] = 14A[4]A[9] = 8, restoring heap property.\n\n* **Building a Heap (`BUILD-MAX-HEAP`)**:\n * Produces a max-heap from an unordered input array A\n * Subarray elements A[\lfloor n/2 \rfloor + 1 \dots n] are all leaves of the tree (each is a 1-element heap to begin with).\n * Procedure iterates through remaining nodes from \lfloor A.\text{length}/2 \rfloor1, executing `MAX-HEAPIFY(A, i)` on each node.\n * **Pseudo-code**:\n ```\n BUILD-MAX-HEAP(A)\n 1 A.heap-size = A.length\n 2 for i = floor(A.length / 2) downto 1\n 3 MAX-HEAPIFY(A, i)\n ```\n * Trace Example: Input array A = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]A.\text{length} = 10i = 5i = 4, 3, 2, 1A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1].\n * **Time Complexity**: Runs in linear time O(n).\n\n* **The Heapsort Algorithm**:\n * `HEAPSORT(A)` sorts array A in place.\n * Worst-case running time is proportional to n \log_2(n)O(n \log_2(n))).\n * Sorts in place: Only a constant number of array elements are stored outside input array at any time.\n\n* **Max-Priority Queues**:\n * Abstract Data Type for maintaining a set S of elements, each with an associated value called a key.\n * **Supported API Operations**:\n * `INSERT(S, x)`: Inserts element xSS = S \cup {x}).\n * `MAXIMUM(S)`: Returns element of S with largest key.\n * `EXTRACT-MAX(S)`: Removes and returns element of S with largest key.\n * `INCREASE-KEY(S, x, k)`: Increases value of element xkk \ge \text{current key}).\n * **Real-World Application**: Scheduling jobs on a shared computer.\n * When job finishes or interrupts, scheduler selects highest-priority job using `EXTRACT-MAX`.\n * Scheduler adds new job to queue at any time using `INSERT`.\n * **`HEAP-INCREASE-KEY` Algorithm**:\n * Inputs: Array Ai, new key value `key`.\n * Updates key A[i] = \text{key}.\n * Traverses path toward root, comparing element to parent and exchanging keys if element key is larger.\n * **Pseudo-code**:\n ```\n HEAP-INCREASE-KEY(A, i, key)\n 1 if key < A[i]\n 2 error "new key is smaller than current key"\n 3 A[i] = key\n 4 while i > 1 and A[PARENT(i)] < A[i]\n 5 exchange A[i] with A[PARENT(i)]\n 6 i = PARENT(i)\n ```\n * Time Complexity: Runs in O(\log_2(n)) time.\n * **`MAX-HEAP-INSERT` Algorithm**:\n * Input: Array A, key of new element.\n * Expands max-heap by adding new leaf with key -\infty (incrementing `A.heap-size`).\n * Calls `HEAP-INCREASE-KEY(A, A.heap-size, key)` to set correct value and maintain max-heap property.\n * Time Complexity: Runs in O(\log_2(n)) time.\n\n# Comprehensive Summary of Data Structures and Operations\n\n* **Abstract Data Types (ADTs)**:\n * Static Set\n * Dynamic Set\n * Stack (LIFO)\n * Queue (FIFO)\n * Priority Queue (Max-Priority Queue)\n* **Concrete Data Structures**:\n * Arrays and Circular Arrays\n * Lists, Circular Lists, and Doubly Linked Lists\n * Trees and Binary Search Trees (BST)\n * Hash Tables (Hash Maps)\n * Heaps (Max-Heap and Min-Heap)\n* **Searching and Sorting Algorithms**:\n * Simple Linear Search\n * Searching a BST\n * Insertion Sort\n * MergeSort\n * Heapsort (O(n \log_2(n))$$ in-place)
Memory Layouts and Specialized Representations:
Sparse Matrices (Coordinate format and Column-value format)
Arrays of Arrays and 2-Dimensional Arrays
Pointers and Records