├── Book Chapter ├── Appendix_A_Recursion.pdf ├── Authors.pdf ├── Chapter_0.pdf ├── Chapter_1.pdf ├── Chapter_2.pdf ├── Chapter_3.pdf ├── Chapter_4.pdf ├── Chapter_5.pdf ├── Chapter_6.pdf ├── Chapter_7.pdf └── Preface.pdf ├── Java ├── Chapter 1 │ ├── ArrayUtils.java │ └── MatrixUtils.java ├── Chapter 2 │ ├── .gitkeep │ ├── DoublyCircularLinkedList.java │ ├── Main.java │ ├── Node.java │ └── SinglyLinkedList.java ├── Chapter 3 │ ├── LinkedListQueue.java │ ├── LinkedListStack.java │ ├── MainQueue.java │ ├── MainStack.java │ ├── Node.java │ ├── QueueOperations.java │ └── StackOperations.java ├── Chapter 4 │ ├── .gitkeep │ ├── HashTable.java │ ├── Main.java │ └── Node.java ├── Chapter 5 │ ├── BinaryTree.java │ └── TreeNode.java └── Chapter 6 │ ├── BinarySearchTree.java │ ├── Main.java │ ├── MaxHeap.java │ └── Node.java ├── Python ├── Chapter 1 │ ├── ArrayUtils.py │ └── MatrixUtils.py ├── Chapter 2 │ ├── .gitkeep │ ├── DoublyLinkedList.py │ └── SinglyLinkedList.py ├── Chapter 3 │ ├── queuee.py │ └── stack.py ├── Chapter 4 │ └── hash_table.py ├── Chapter 5 │ └── binary_tree.py └── Chapter 6 │ ├── bst.py │ └── max_heap.py └── README.md /Book Chapter/Appendix_A_Recursion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Appendix_A_Recursion.pdf -------------------------------------------------------------------------------- /Book Chapter/Authors.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Authors.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_0.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_1.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_2.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_3.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_4.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_5.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_6.pdf -------------------------------------------------------------------------------- /Book Chapter/Chapter_7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Chapter_7.pdf -------------------------------------------------------------------------------- /Book Chapter/Preface.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zabermd/Data-Structures-and-their-Use-in-Elementary-Algorithms/bcf43851d555452e059239359cce86f555f7a1c8/Book Chapter/Preface.pdf -------------------------------------------------------------------------------- /Java/Chapter 1/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | public class ArrayUtils { 2 | 3 | // Iteration over an array 4 | public static void iterate(int[] arr) { 5 | for (int element : arr) { 6 | System.out.print(element + " "); 7 | } 8 | System.out.println(); 9 | } 10 | 11 | // Resize an array 12 | public static int[] resize(int[] arr, int newSize) { 13 | int[] resized = new int[newSize]; 14 | for (int i = 0; i < Math.min(arr.length, newSize); i++) { 15 | resized[i] = arr[i]; 16 | } 17 | return resized; 18 | } 19 | 20 | // Copy an array (pass by value) 21 | public static int[] copyArray(int[] arr) { 22 | int[] copy = new int[arr.length]; 23 | for (int i = 0; i < arr.length; i++) { 24 | copy[i] = arr[i]; 25 | } 26 | return copy; 27 | } 28 | 29 | // Shift left (in-place) 30 | public static void shiftLeft(int[] arr) { 31 | if (arr.length == 0) return; 32 | for (int i = 0; i < arr.length - 1; i++) { 33 | arr[i] = arr[i + 1]; 34 | } 35 | arr[arr.length - 1] = 0; // Fill the last position with 0 36 | } 37 | 38 | // Shift right (in-place) 39 | public static void shiftRight(int[] arr) { 40 | if (arr.length == 0) return; 41 | for (int i = arr.length - 1; i > 0; i--) { 42 | arr[i] = arr[i - 1]; 43 | } 44 | arr[0] = 0; // Fill the first position with 0 45 | } 46 | 47 | // Rotate left (in-place) 48 | public static void rotateLeft(int[] arr) { 49 | if (arr.length == 0) return; 50 | int first = arr[0]; 51 | for (int i = 0; i < arr.length - 1; i++) { 52 | arr[i] = arr[i + 1]; 53 | } 54 | arr[arr.length - 1] = first; 55 | } 56 | 57 | // Rotate right (in-place) 58 | public static void rotateRight(int[] arr) { 59 | if (arr.length == 0) return; 60 | int last = arr[arr.length - 1]; 61 | for (int i = arr.length - 1; i > 0; i--) { 62 | arr[i] = arr[i - 1]; 63 | } 64 | arr[0] = last; 65 | } 66 | 67 | // Reverse array (Out-of-place) 68 | public static int[] reverseOutOfPlace(int[] arr) { 69 | int[] reversed = new int[arr.length]; 70 | for (int i = 0; i < arr.length; i++) { 71 | reversed[i] = arr[arr.length - 1 - i]; 72 | } 73 | return reversed; 74 | } 75 | 76 | // Reverse array (In-place) 77 | public static void reverseInPlace(int[] arr) { 78 | int left = 0, right = arr.length - 1; 79 | while (left < right) { 80 | int temp = arr[left]; 81 | arr[left] = arr[right]; 82 | arr[right] = temp; 83 | left++; 84 | right--; 85 | } 86 | } 87 | 88 | // Insert an element at the end or anywhere else 89 | public static int[] insert(int[] arr, int index, int value, int currentSize) { 90 | if (index < 0 || index > currentSize) { 91 | throw new IndexOutOfBoundsException("Invalid index"); 92 | } 93 | if (currentSize == arr.length) { 94 | arr = resize(arr, arr.length * 2); 95 | } 96 | for (int i = currentSize; i > index; i--) { 97 | arr[i] = arr[i - 1]; 98 | } 99 | arr[index] = value; 100 | return arr; 101 | } 102 | 103 | // Delete the last element or any other element (in-place) 104 | public static void delete(int[] arr, int index, int currentSize) { 105 | if (index < 0 || index >= currentSize) { 106 | throw new IndexOutOfBoundsException("Invalid index"); 107 | } 108 | for (int i = index; i < currentSize - 1; i++) { 109 | arr[i] = arr[i + 1]; 110 | } 111 | arr[currentSize - 1] = 0; // Set the last element to 0 after deletion 112 | } 113 | 114 | // Main method to test the utility class 115 | public static void main(String[] args) { 116 | int[] array = {1, 2, 3, 4, 5, 0, 0}; 117 | int currentSize = 5; 118 | 119 | System.out.print("Original array: "); 120 | iterate(array); 121 | 122 | System.out.print("Resized array: "); 123 | iterate(resize(array, 7)); 124 | 125 | System.out.print("Copied array: "); 126 | iterate(copyArray(array)); 127 | 128 | System.out.print("Shift left: "); 129 | shiftLeft(array); 130 | iterate(array); 131 | 132 | System.out.print("Shift right: "); 133 | shiftRight(array); 134 | iterate(array); 135 | 136 | System.out.print("Rotate left: "); 137 | rotateLeft(array); 138 | iterate(array); 139 | 140 | System.out.print("Rotate right: "); 141 | rotateRight(array); 142 | iterate(array); 143 | 144 | System.out.print("Reversed out-of-place: "); 145 | iterate(reverseOutOfPlace(array)); 146 | 147 | reverseInPlace(array); 148 | System.out.print("Reversed in-place: "); 149 | iterate(array); 150 | 151 | System.out.print("After insertion: "); 152 | array = insert(array, 2, 10, currentSize); 153 | currentSize++; 154 | iterate(array); 155 | 156 | System.out.print("After deletion: "); 157 | delete(array, 2, currentSize); 158 | currentSize--; 159 | iterate(array); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /Java/Chapter 1/MatrixUtils.java: -------------------------------------------------------------------------------- 1 | public class MatrixUtils { 2 | 3 | // 1. Creating a 2D array 4 | public static int[][] create2DArray(int rows, int cols, int initialValue) { 5 | int[][] matrix = new int[rows][cols]; 6 | for (int i = 0; i < rows; i++) { 7 | for (int j = 0; j < cols; j++) { 8 | matrix[i][j] = initialValue; 9 | } 10 | } 11 | return matrix; 12 | } 13 | 14 | // 2. Row-wise iteration 15 | public static void iterateRows(int[][] matrix) { 16 | for (int[] row : matrix) { 17 | for (int value : row) { 18 | System.out.print(value + " "); 19 | } 20 | System.out.println(); 21 | } 22 | } 23 | 24 | // 3. Column-wise iteration 25 | public static void iterateColumns(int[][] matrix) { 26 | int rows = matrix.length; 27 | int cols = matrix[0].length; 28 | for (int j = 0; j < cols; j++) { 29 | for (int i = 0; i < rows; i++) { 30 | System.out.print(matrix[i][j] + " "); 31 | } 32 | System.out.println(); 33 | } 34 | } 35 | 36 | // 4. Sum of all values 37 | public static int sumAllValues(int[][] matrix) { 38 | int sum = 0; 39 | for (int[] row : matrix) { 40 | for (int value : row) { 41 | sum += value; 42 | } 43 | } 44 | return sum; 45 | } 46 | 47 | // 5. Sum of every row 48 | public static int[] sumRows(int[][] matrix) { 49 | int[] rowSums = new int[matrix.length]; 50 | for (int i = 0; i < matrix.length; i++) { 51 | int sum = 0; 52 | for (int value : matrix[i]) { 53 | sum += value; 54 | } 55 | rowSums[i] = sum; 56 | } 57 | return rowSums; 58 | } 59 | 60 | // 6. Sum of all columns 61 | public static int[] sumColumns(int[][] matrix) { 62 | int rows = matrix.length; 63 | int cols = matrix[0].length; 64 | int[] colSums = new int[cols]; 65 | for (int j = 0; j < cols; j++) { 66 | int sum = 0; 67 | for (int i = 0; i < rows; i++) { 68 | sum += matrix[i][j]; 69 | } 70 | colSums[j] = sum; 71 | } 72 | return colSums; 73 | } 74 | 75 | // 7. Swapping columns based on pattern in a matrix 76 | public static int[][] swapColumns(int[][] matrix) { 77 | int rows = matrix.length; 78 | int cols = matrix[0].length; 79 | int mid = cols / 2; 80 | for (int j = 0; j < mid; j++) { 81 | int col1 = j; 82 | int col2 = cols - 1 - j; 83 | for (int i = 0; i < rows; i++) { 84 | int temp = matrix[i][col1]; 85 | matrix[i][col1] = matrix[i][col2]; 86 | matrix[i][col2] = temp; 87 | } 88 | } 89 | return matrix; 90 | } 91 | 92 | 93 | // 8. Adding primary diagonal items in a square matrix 94 | public static int sumPrimaryDiagonal(int[][] matrix) { 95 | int sum = 0; 96 | for (int i = 0; i < matrix.length; i++) { 97 | sum += matrix[i][i]; 98 | } 99 | return sum; 100 | } 101 | 102 | // 9. Adding secondary diagonal items in a square matrix 103 | public static int sumSecondaryDiagonal(int[][] matrix) { 104 | int sum = 0; 105 | int n = matrix.length; 106 | for (int i = 0; i < n; i++) { 107 | sum += matrix[i][n - 1 - i]; 108 | } 109 | return sum; 110 | } 111 | 112 | // 10. Adding two matrices of the same dimension 113 | public static int[][] addMatrices(int[][] matrix1, int[][] matrix2) { 114 | int rows = matrix1.length; 115 | int cols = matrix1[0].length; 116 | int[][] result = new int[rows][cols]; 117 | for (int i = 0; i < rows; i++) { 118 | for (int j = 0; j < cols; j++) { 119 | result[i][j] = matrix1[i][j] + matrix2[i][j]; 120 | } 121 | } 122 | return result; 123 | } 124 | 125 | // 11. Matrix multiplication 126 | public static int[][] multiplyMatrices(int[][] matrix1, int[][] matrix2) { 127 | int rows1 = matrix1.length; 128 | int cols1 = matrix1[0].length; 129 | int cols2 = matrix2[0].length; 130 | int[][] result = new int[rows1][cols2]; 131 | for (int i = 0; i < rows1; i++) { 132 | for (int j = 0; j < cols2; j++) { 133 | for (int k = 0; k < cols1; k++) { 134 | result[i][j] += matrix1[i][k] * matrix2[k][j]; 135 | } 136 | } 137 | } 138 | return result; 139 | } 140 | 141 | // Main method to test the MatrixUtils class 142 | public static void main(String[] args) { 143 | int[][] matrix1 = create2DArray(3, 3, 1); 144 | int[][] matrix2 = create2DArray(3, 3, 2); 145 | 146 | System.out.println("Matrix 1:"); 147 | iterateRows(matrix1); 148 | 149 | System.out.println("Matrix 2:"); 150 | iterateRows(matrix2); 151 | 152 | System.out.println("Sum of all values in Matrix 1: " + sumAllValues(matrix1)); 153 | 154 | System.out.println("Row-wise sums of Matrix 1:"); 155 | int[] rowSums = sumRows(matrix1); 156 | for (int sum : rowSums) { 157 | System.out.print(sum + " "); 158 | } 159 | System.out.println(); 160 | 161 | System.out.println("Column-wise sums of Matrix 1:"); 162 | int[] colSums = sumColumns(matrix1); 163 | for (int sum : colSums) { 164 | System.out.print(sum + " "); 165 | } 166 | System.out.println(); 167 | 168 | 169 | iterateRows(matrix1); 170 | 171 | System.out.println("Sum of primary diagonal of Matrix 2: " + sumPrimaryDiagonal(matrix2)); 172 | System.out.println("Sum of secondary diagonal of Matrix 2: " + sumSecondaryDiagonal(matrix2)); 173 | 174 | System.out.println("Addition of Matrix 1 and Matrix 2:"); 175 | int[][] addedMatrix = addMatrices(matrix1, matrix2); 176 | iterateRows(addedMatrix); 177 | 178 | System.out.println("Multiplication of Matrix 1 and Matrix 2:"); 179 | int[][] multipliedMatrix = multiplyMatrices(matrix1, matrix2); 180 | iterateRows(multipliedMatrix); 181 | 182 | int[][] matrix = { 183 | {1, 2, 3, 4}, 184 | {5, 6, 7, 8}, 185 | {9, 10, 11, 12}, 186 | {13, 14, 15, 16} 187 | }; 188 | System.out.println("Matrix before swapping columns:"); 189 | iterateRows(matrix); 190 | matrix = swapColumns(matrix); 191 | 192 | System.out.println("Matrix after swapping columns:"); 193 | iterateRows(matrix); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Java/Chapter 2/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java/Chapter 2/DoublyCircularLinkedList.java: -------------------------------------------------------------------------------- 1 | public class DoublyCircularLinkedList { 2 | private Node head; 3 | 4 | public DoublyCircularLinkedList() { 5 | head = new Node(-1); // Dummy node 6 | head.next = head; 7 | head.prev = head; 8 | } 9 | 10 | // 1. Creating a Linked List from an array 11 | public void createFromArray(int[] arr) { 12 | for (int elem : arr) { 13 | insertAtEnd(elem); 14 | } 15 | } 16 | 17 | // 2. Iteration of the linked list 18 | public void iterate() { 19 | Node current = head.next; 20 | while (current != head) { 21 | System.out.print(current.elem + " "); 22 | current = current.next; 23 | } 24 | System.out.println(); 25 | } 26 | 27 | // 3. Count the items in the linked list 28 | public int countItems() { 29 | int count = 0; 30 | Node current = head.next; 31 | while (current != head) { 32 | count++; 33 | current = current.next; 34 | } 35 | return count; 36 | } 37 | 38 | // 4. Retrieving a node from an index (Index starts from 0) 39 | public Node getNode(int index) { 40 | if (index < 0) return null; 41 | 42 | Node current = head.next; 43 | int currentIndex = 0; 44 | 45 | while (current != head) { 46 | if (currentIndex == index) return current; 47 | currentIndex++; 48 | current = current.next; 49 | } 50 | return null; // Index out of bounds 51 | } 52 | 53 | // 5. Inserting a node in the list (start, middle, end) 54 | public void insertAtStart(int elem) { 55 | Node newNode = new Node(elem); 56 | Node first = head.next; 57 | 58 | newNode.next = first; 59 | newNode.prev = head; 60 | head.next = newNode; 61 | first.prev = newNode; 62 | } 63 | 64 | public void insertAtEnd(int elem) { 65 | Node newNode = new Node(elem); 66 | Node last = head.prev; 67 | 68 | newNode.next = head; 69 | newNode.prev = last; 70 | last.next = newNode; 71 | head.prev = newNode; 72 | } 73 | 74 | public void insertAtIndex(int index, int elem) { 75 | if (index < 0) return; 76 | 77 | if (index == 0) { 78 | insertAtStart(elem); 79 | return; 80 | } 81 | 82 | Node current = head.next; 83 | int currentIndex = 0; 84 | 85 | while (current != head) { 86 | if (currentIndex == index) { 87 | Node newNode = new Node(elem); 88 | Node prevNode = current.prev; 89 | 90 | newNode.next = current; 91 | newNode.prev = prevNode; 92 | prevNode.next = newNode; 93 | current.prev = newNode; 94 | 95 | return; 96 | } 97 | currentIndex++; 98 | current = current.next; 99 | } 100 | 101 | if (currentIndex == index) { // Insert at the end 102 | insertAtEnd(elem); 103 | } 104 | } 105 | 106 | // 6. Removing a node from the list 107 | public void remove(int index) { 108 | if (index < 0) return; 109 | 110 | Node current = head.next; 111 | int currentIndex = 0; 112 | 113 | while (current != head) { 114 | if (currentIndex == index) { 115 | Node prevNode = current.prev; 116 | Node nextNode = current.next; 117 | 118 | prevNode.next = nextNode; 119 | nextNode.prev = prevNode; 120 | 121 | return; 122 | } 123 | currentIndex++; 124 | current = current.next; 125 | } 126 | System.out.println("Index out of bounds"); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Java/Chapter 2/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | public static void main(String[] args) { 3 | DoublyCircularLinkedList list = new DoublyCircularLinkedList(); 4 | 5 | // 1. Creating a Linked List from an array 6 | int[] arr = {10, 20, 30, 40, 50}; 7 | list.createFromArray(arr); 8 | 9 | // 2. Iteration of the linked list 10 | System.out.println("Iterating the list:"); 11 | list.iterate(); 12 | 13 | // 3. Count the items in the linked list 14 | System.out.println("Count of items: " + list.countItems()); 15 | 16 | // 4. Retrieving a node from an index 17 | int indexToRetrieve = 2; 18 | Node node = list.getNode(indexToRetrieve); 19 | if (node != null) { 20 | System.out.println("Element at index " + indexToRetrieve + ": " + node.elem); 21 | } else { 22 | System.out.println("Index " + indexToRetrieve + " is out of bounds."); 23 | } 24 | 25 | // 5. Inserting a node in the list (start, middle, end) 26 | System.out.println("Inserting 5 at the start:"); 27 | list.insertAtStart(5); 28 | list.iterate(); 29 | 30 | System.out.println("Inserting 60 at the end:"); 31 | list.insertAtEnd(60); 32 | list.iterate(); 33 | 34 | System.out.println("Inserting 25 at index 3:"); 35 | list.insertAtIndex(3, 25); 36 | list.iterate(); 37 | 38 | // 6. Removing a node from the list 39 | System.out.println("Removing the node at index 4:"); 40 | list.remove(4); 41 | list.iterate(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Java/Chapter 2/Node.java: -------------------------------------------------------------------------------- 1 | class Node { 2 | int elem; 3 | Node next; 4 | Node prev; 5 | 6 | public Node(int elem) { 7 | this.elem = elem; 8 | this.next = null; 9 | this.prev = null; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Java/Chapter 2/SinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class SinglyLinkedList { 2 | 3 | // Node class 4 | private static class Node { 5 | int elem; 6 | Node next; 7 | 8 | Node(int elem) { 9 | this.elem = elem; 10 | this.next = null; 11 | } 12 | } 13 | 14 | private Node head; 15 | 16 | // 1. Create a Linked List from an array 17 | public void createFromArray(int[] arr) { 18 | if (arr == null || arr.length == 0) return; 19 | head = new Node(arr[0]); 20 | Node current = head; 21 | for (int i = 1; i < arr.length; i++) { 22 | current.next = new Node(arr[i]); 23 | current = current.next; 24 | } 25 | } 26 | 27 | // 2. Iteration of the linked list 28 | public void iterate() { 29 | Node current = head; 30 | while (current != null) { 31 | System.out.print(current.elem + " -> "); 32 | current = current.next; 33 | } 34 | System.out.println(); 35 | } 36 | 37 | // 3. Count the items in the linked list 38 | public int count() { 39 | int count = 0; 40 | Node current = head; 41 | while (current != null) { 42 | count++; 43 | current = current.next; 44 | } 45 | return count; 46 | } 47 | 48 | // 4. Retrieve index of an element 49 | public int indexOf(int elem) { 50 | int index = 0; 51 | Node current = head; 52 | while (current != null) { 53 | if (current.elem == elem) { 54 | return index; 55 | } 56 | current = current.next; 57 | index++; 58 | } 59 | return -1; // Element not found 60 | } 61 | 62 | // 5. Retrieve a node from an index 63 | public Node getNode(int index) { 64 | int currentIndex = 0; 65 | Node current = head; 66 | while (current != null) { 67 | if (currentIndex == index) { 68 | return current; 69 | } 70 | current = current.next; 71 | currentIndex++; 72 | } 73 | return null; // Index out of bounds 74 | } 75 | 76 | // 6. Update value in a specific index 77 | public boolean update(int index, int newValue) { 78 | Node node = getNode(index); 79 | if (node != null) { 80 | node.elem = newValue; 81 | return true; 82 | } 83 | return false; // Index out of bounds 84 | } 85 | 86 | // 7. Search for an element in the list 87 | public boolean search(int elem) { 88 | Node current = head; 89 | while (current != null) { 90 | if (current.elem == elem) { 91 | return true; 92 | } 93 | current = current.next; 94 | } 95 | return false; 96 | } 97 | 98 | // 8. Insert a node in the list 99 | public void insert(int index, int elem) { 100 | Node newNode = new Node(elem); 101 | if (index == 0) { // Insert at the beginning 102 | newNode.next = head; 103 | head = newNode; 104 | return; 105 | } 106 | Node prev = getNode(index - 1); 107 | if (prev != null) { // Insert in the middle or at the end 108 | newNode.next = prev.next; 109 | prev.next = newNode; 110 | } 111 | } 112 | 113 | // 9. Remove a node from the list 114 | public void remove(int index) { 115 | if (index == 0 && head != null) { // Remove from the beginning 116 | head = head.next; 117 | return; 118 | } 119 | Node prev = getNode(index - 1); 120 | if (prev != null && prev.next != null) { // Remove from the middle or end 121 | prev.next = prev.next.next; 122 | } 123 | } 124 | 125 | // 10. Copying a linked list 126 | public SinglyLinkedList copy() { 127 | SinglyLinkedList newList = new SinglyLinkedList(); 128 | if (head == null) return newList; 129 | newList.head = new Node(head.elem); 130 | Node current = head.next; 131 | Node newCurrent = newList.head; 132 | while (current != null) { 133 | newCurrent.next = new Node(current.elem); 134 | current = current.next; 135 | newCurrent = newCurrent.next; 136 | } 137 | return newList; 138 | } 139 | 140 | // 11. Out-of-place reverse of a linked list 141 | public SinglyLinkedList reverseOutOfPlace() { 142 | SinglyLinkedList reversedList = new SinglyLinkedList(); 143 | Node current = head; 144 | while (current != null) { 145 | Node newNode = new Node(current.elem); 146 | newNode.next = reversedList.head; 147 | reversedList.head = newNode; 148 | current = current.next; 149 | } 150 | return reversedList; 151 | } 152 | 153 | // 12. In-place reverse of a linked list 154 | public void reverseInPlace() { 155 | Node prev = null, current = head, next; 156 | while (current != null) { 157 | next = current.next; 158 | current.next = prev; 159 | prev = current; 160 | current = next; 161 | } 162 | head = prev; 163 | } 164 | 165 | // 13. Rotating the list left 166 | public void rotateLeft(int k) { 167 | if (head == null || k <= 0) return; 168 | int size = count(); 169 | k = k % size; // Handle rotations greater than size 170 | if (k == 0) return; 171 | 172 | Node current = head; 173 | for (int i = 1; i < k; i++) { 174 | current = current.next; 175 | } 176 | 177 | Node newHead = current.next; 178 | current.next = null; 179 | 180 | Node tail = newHead; 181 | while (tail.next != null) { 182 | tail = tail.next; 183 | } 184 | tail.next = head; 185 | head = newHead; 186 | } 187 | 188 | // 14. Rotating the list right 189 | public void rotateRight(int k) { 190 | if (head == null || k <= 0) return; 191 | int size = count(); 192 | k = k % size; // Handle rotations greater than size 193 | if (k == 0) return; 194 | 195 | rotateLeft(size - k); 196 | } 197 | 198 | public static void main(String[] args) { 199 | 200 | SinglyLinkedList list = new SinglyLinkedList(); 201 | 202 | // 1. Create a linked list from an array 203 | int[] arr = {1, 2, 3, 4, 5}; 204 | list.createFromArray(arr); 205 | System.out.println("Original List:"); 206 | list.iterate(); 207 | 208 | // 2. Iterate through the linked list 209 | System.out.println("Iterating through the list:"); 210 | list.iterate(); 211 | 212 | // 3. Count the items in the linked list 213 | System.out.println("Count of items in the list: " + list.count()); 214 | 215 | // 4. Retrieve index of an element 216 | int elemToFind = 3; 217 | System.out.println("Index of element " + elemToFind + ": " + list.indexOf(elemToFind)); 218 | 219 | // 5. Retrieve a node from an index 220 | int indexToRetrieve = 2; 221 | Node node = list.getNode(indexToRetrieve); 222 | System.out.println("Element at index " + indexToRetrieve + ": " + (node != null ? node.elem : "Index out of bounds")); 223 | 224 | // 6. Update value at a specific index 225 | int indexToUpdate = 1; 226 | int newValue = 10; 227 | if (list.update(indexToUpdate, newValue)) { 228 | System.out.println("Updated value at index " + indexToUpdate + " to " + newValue); 229 | list.iterate(); 230 | } else { 231 | System.out.println("Failed to update index " + indexToUpdate); 232 | } 233 | 234 | // 7. Search for an element in the list 235 | int searchElement = 4; 236 | System.out.println("Element " + searchElement + " found: " + list.search(searchElement)); 237 | 238 | // 8. Insert a node in the list 239 | System.out.println("Inserting 99 at index 0:"); 240 | list.insert(0, 99); // Insert at the beginning 241 | list.iterate(); 242 | 243 | System.out.println("Inserting 77 at index 3:"); 244 | list.insert(3, 77); // Insert in the middle 245 | list.iterate(); 246 | 247 | System.out.println("Inserting 55 at the end:"); 248 | list.insert(list.count(), 55); // Insert at the end 249 | list.iterate(); 250 | 251 | // 9. Remove a node from the list 252 | System.out.println("Removing the node at index 2:"); 253 | list.remove(2); // Remove from the middle 254 | list.iterate(); 255 | 256 | // 10. Copying the linked list 257 | SinglyLinkedList copiedList = list.copy(); 258 | System.out.println("Copied list:"); 259 | copiedList.iterate(); 260 | 261 | // 11. Out-of-place reverse of a linked list 262 | SinglyLinkedList reversedList = list.reverseOutOfPlace(); 263 | System.out.println("Reversed list (out of place):"); 264 | reversedList.iterate(); 265 | 266 | // 12. In-place reverse of a linked list 267 | list.reverseInPlace(); 268 | System.out.println("Reversed list (in place):"); 269 | list.iterate(); 270 | 271 | // 13. Rotating the list left 272 | System.out.println("Rotating the list left by 2 positions:"); 273 | list.rotateLeft(2); 274 | list.iterate(); 275 | 276 | // 14. Rotating the list right 277 | System.out.println("Rotating the list right by 2 positions:"); 278 | list.rotateRight(2); 279 | list.iterate(); 280 | 281 | 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /Java/Chapter 3/LinkedListQueue.java: -------------------------------------------------------------------------------- 1 | public class LinkedListQueue { 2 | private Node front; 3 | private Node rear; 4 | 5 | public LinkedListQueue() { 6 | this.front = this.rear = null; 7 | } 8 | 9 | public void enqueue(int elem) { 10 | Node newNode = new Node(elem); 11 | if (rear == null) { 12 | front = rear = newNode; 13 | return; 14 | } 15 | rear.next = newNode; 16 | rear = newNode; 17 | } 18 | 19 | public int dequeue() { 20 | if (isEmpty()) { 21 | throw new RuntimeException("Queue is empty"); 22 | } 23 | int removedElem = front.elem; 24 | front = front.next; 25 | if (front == null) { 26 | rear = null; // Queue is now empty 27 | } 28 | return removedElem; 29 | } 30 | 31 | public int peek() { 32 | if (isEmpty()) { 33 | throw new RuntimeException("Queue is empty"); 34 | } 35 | return front.elem; 36 | } 37 | 38 | public boolean isEmpty() { 39 | return front == null; 40 | } 41 | 42 | public void displayQueue() { 43 | Node current = front; 44 | System.out.print("Queue (front to rear): "); 45 | while (current != null) { 46 | System.out.print(current.elem + " -> "); 47 | current = current.next; 48 | } 49 | System.out.println("NULL"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Java/Chapter 3/LinkedListStack.java: -------------------------------------------------------------------------------- 1 | 2 | // Stack class using a singly linked list 3 | class LinkedListStack { 4 | private Node top; // Points to the top element of the stack 5 | 6 | public LinkedListStack() { 7 | this.top = null; // Initialize stack as empty 8 | } 9 | 10 | // Push operation: Inserts an element at the top of the stack 11 | public void push(int value) { 12 | Node newNode = new Node(value); 13 | newNode.next = top; // New node points to the current top 14 | top = newNode; // Update top to the new node 15 | } 16 | 17 | // Pop operation: Removes and returns the top element of the stack 18 | public int pop() { 19 | if (isEmpty()) { 20 | throw new RuntimeException("Stack Underflow! Cannot pop from an empty stack."); 21 | } 22 | int poppedValue = top.elem; 23 | top = top.next; // Move top pointer to the next node 24 | return poppedValue; 25 | } 26 | 27 | // Peek operation: Returns the top element without removing it 28 | public int peek() { 29 | if (isEmpty()) { 30 | throw new RuntimeException("Stack is empty! Cannot peek."); 31 | } 32 | return top.elem; 33 | } 34 | 35 | // isEmpty operation: Checks if the stack is empty 36 | public boolean isEmpty() { 37 | return top == null; 38 | } 39 | 40 | // Display the stack contents (For debugging purposes) 41 | public void displayStack() { 42 | if (isEmpty()) { 43 | System.out.println("Stack is empty!"); 44 | return; 45 | } 46 | Node current = top; 47 | System.out.print("Stack (top to bottom): "); 48 | while (current != null) { 49 | System.out.print(current.elem + " -> "); 50 | current = current.next; 51 | } 52 | System.out.println("NULL"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Java/Chapter 3/MainQueue.java: -------------------------------------------------------------------------------- 1 | public class MainQueue { 2 | public static void main(String[] args) { 3 | LinkedListQueue queue = new LinkedListQueue(); 4 | queue.enqueue(10); 5 | queue.enqueue(20); 6 | queue.enqueue(30); 7 | System.out.println("Original Queue:"); 8 | queue.displayQueue(); 9 | 10 | // Reverse Queue 11 | queue = QueueOperations.reverseQueue(queue); 12 | System.out.println("Reversed Queue:"); 13 | queue.displayQueue(); 14 | 15 | // Generate Binary Numbers 16 | System.out.println("Binary Numbers up to 5:"); 17 | QueueOperations.generateBinaryNumbers(5); 18 | 19 | // Check Palindrome Queue 20 | LinkedListQueue palindromeQueue = new LinkedListQueue(); 21 | palindromeQueue.enqueue(1); 22 | palindromeQueue.enqueue(2); 23 | palindromeQueue.enqueue(3); 24 | palindromeQueue.enqueue(2); 25 | palindromeQueue.enqueue(1); 26 | 27 | System.out.println("Is the queue a palindrome? " + QueueOperations.isQueuePalindrome(palindromeQueue)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Java/Chapter 3/MainStack.java: -------------------------------------------------------------------------------- 1 | //Main class to test the stack implementation 2 | public class MainStack { 3 | public static void main(String[] args) { 4 | LinkedListStack stack = new LinkedListStack(); 5 | 6 | // Testing push operation 7 | stack.push(10); 8 | stack.push(20); 9 | stack.push(30); 10 | stack.displayStack(); // Output: Stack (top to bottom): 30 -> 20 -> 10 -> NULL 11 | 12 | // Testing peek operation 13 | System.out.println("Top element: " + stack.peek()); // Output: 30 14 | 15 | // Testing pop operation 16 | System.out.println("Popped: " + stack.pop()); // Output: 30 17 | stack.displayStack(); // Output: Stack (top to bottom): 20 -> 10 -> NULL 18 | 19 | // Checking if stack is empty 20 | System.out.println("Is stack empty? " + stack.isEmpty()); // Output: false 21 | 22 | // Popping remaining elements 23 | stack.pop(); 24 | stack.pop(); 25 | 26 | // Checking if stack is empty after all pops 27 | System.out.println("Is stack empty? " + stack.isEmpty()); // Output: true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Java/Chapter 3/Node.java: -------------------------------------------------------------------------------- 1 | public class Node { 2 | int elem; 3 | Node next; 4 | 5 | public Node(int elem) { 6 | this.elem = elem; 7 | this.next = null; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Java/Chapter 3/QueueOperations.java: -------------------------------------------------------------------------------- 1 | public class QueueOperations { 2 | 3 | // 1. Reverse a Queue 4 | public static LinkedListQueue reverseQueue(LinkedListQueue queue) { 5 | LinkedListStack stack = new LinkedListStack(); 6 | while (!queue.isEmpty()) { 7 | stack.push(queue.dequeue()); 8 | } 9 | while (!stack.isEmpty()) { 10 | queue.enqueue(stack.pop()); 11 | } 12 | return queue; 13 | } 14 | 15 | // 2. Generate Binary Numbers using Queue 16 | public static void generateBinaryNumbers(int n) { 17 | LinkedListQueue queue = new LinkedListQueue(); 18 | queue.enqueue(1); // Start with "1" 19 | 20 | for (int i = 0; i < n; i++) { 21 | int front = queue.dequeue(); 22 | System.out.print(front + " "); 23 | 24 | queue.enqueue(front * 10); // Append "0" to front 25 | queue.enqueue(front * 10 + 1); // Append "1" to front 26 | } 27 | System.out.println(); 28 | } 29 | 30 | // 3. Check if a given queue is a palindrome 31 | public static boolean isQueuePalindrome(LinkedListQueue queue) { 32 | LinkedListStack stack = new LinkedListStack(); 33 | LinkedListQueue tempQueue = new LinkedListQueue(); 34 | 35 | while (!queue.isEmpty()) { 36 | int elem = queue.dequeue(); 37 | stack.push(elem); 38 | tempQueue.enqueue(elem); 39 | } 40 | 41 | while (!tempQueue.isEmpty()) { 42 | int qElem = tempQueue.dequeue(); 43 | int sElem = stack.pop(); 44 | if (qElem != sElem) { 45 | return false; 46 | } 47 | } 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Java/Chapter 3/StackOperations.java: -------------------------------------------------------------------------------- 1 | package ChapterThree; 2 | 3 | public class StackOperations { 4 | 5 | // Method to reverse a stack 6 | public static LinkedListStack reverseStack(LinkedListStack stack) { 7 | LinkedListStack tempStack = new LinkedListStack(); 8 | while (!stack.isEmpty()) { 9 | tempStack.push(stack.pop()); 10 | } 11 | return tempStack; 12 | } 13 | 14 | // Method to evaluate a postfix expression 15 | public static int evaluatePostfix(String expression) { 16 | LinkedListStack stack = new LinkedListStack(); 17 | 18 | for (char ch : expression.toCharArray()) { 19 | if (Character.isDigit(ch)) { 20 | stack.push(ch - '0'); // Convert char to integer 21 | } else { 22 | int operand2 = stack.pop(); 23 | int operand1 = stack.pop(); 24 | switch (ch) { 25 | case '+': 26 | stack.push(operand1 + operand2); 27 | break; 28 | case '-': 29 | stack.push(operand1 - operand2); 30 | break; 31 | case '*': 32 | stack.push(operand1 * operand2); 33 | break; 34 | case '/': 35 | stack.push(operand1 / operand2); 36 | break; 37 | } 38 | } 39 | } 40 | return stack.pop(); 41 | } 42 | 43 | // Method to check if parentheses are balanced 44 | public static boolean isBalancedParentheses(String expression) { 45 | LinkedListStack stack = new LinkedListStack(); 46 | 47 | for (char ch : expression.toCharArray()) { 48 | if (ch == '(' || ch == '{' || ch == '[') { 49 | stack.push(ch); 50 | } else if (ch == ')' || ch == '}' || ch == ']') { 51 | if (stack.isEmpty()) return false; 52 | char top = (char) stack.pop(); 53 | if ((ch == ')' && top != '(') || 54 | (ch == '}' && top != '{') || 55 | (ch == ']' && top != '[')) { 56 | return false; 57 | } 58 | } 59 | } 60 | return stack.isEmpty(); 61 | } 62 | 63 | public static void main(String[] args) { 64 | // Testing Reverse Stack 65 | LinkedListStack stack = new LinkedListStack(); 66 | stack.push(10); 67 | stack.push(20); 68 | stack.push(30); 69 | System.out.println("Original Stack:"); 70 | stack.displayStack(); 71 | 72 | stack = reverseStack(stack); 73 | System.out.println("Reversed Stack:"); 74 | stack.displayStack(); 75 | 76 | // Testing Postfix Expression Evaluation 77 | String postfixExpression = "53+82-*"; // (5 + 3) * (8 - 2) = 48 78 | int result = evaluatePostfix(postfixExpression); 79 | System.out.println("Postfix Evaluation Result: " + result); 80 | 81 | // Testing Parentheses Matching 82 | String expr1 = "{[()]}"; // Balanced 83 | String expr2 = "{[(])}"; // Not Balanced 84 | System.out.println("Is Balanced: " + isBalancedParentheses(expr1)); // true 85 | System.out.println("Is Balanced: " + isBalancedParentheses(expr2)); // false 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /Java/Chapter 4/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Java/Chapter 4/HashTable.java: -------------------------------------------------------------------------------- 1 | // HashTable class with generic key-value support and duplicate key handling 2 | public class HashTable { 3 | private int size; 4 | private Node[] table; 5 | 6 | @SuppressWarnings("unchecked") 7 | public HashTable(int size) { 8 | this.size = size; 9 | table = new Node[size]; 10 | } 11 | 12 | // Hash function (modulus operation) 13 | private int hashFunction(K key) { 14 | return Math.abs(key.hashCode()) % size; 15 | } 16 | 17 | // Insert method (prevents duplicate keys and updates value if key exists) 18 | public void insert(K key, V value) { 19 | int index = hashFunction(key); 20 | Node current = table[index]; 21 | 22 | // Check if the key already exists and update its value 23 | while (current != null) { 24 | if (current.key.equals(key)) { 25 | current.value = value; // Update value for existing key 26 | return; 27 | } 28 | current = current.next; 29 | } 30 | 31 | // Insert at the beginning of the linked list (forward chaining) 32 | Node newNode = new Node<>(key, value); 33 | newNode.next = table[index]; 34 | table[index] = newNode; 35 | } 36 | 37 | // Search method 38 | public V search(K key) { 39 | int index = hashFunction(key); 40 | Node current = table[index]; 41 | 42 | while (current != null) { 43 | if (current.key.equals(key)) { 44 | return current.value; 45 | } 46 | current = current.next; 47 | } 48 | return null; // Key not found 49 | } 50 | 51 | // Display method 52 | public void display() { 53 | for (int i = 0; i < size; i++) { 54 | System.out.print("Index " + i + ": "); 55 | Node current = table[i]; 56 | while (current != null) { 57 | System.out.print("(" + current.key + ", " + current.value + ") -> "); 58 | current = current.next; 59 | } 60 | System.out.println("NULL"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Java/Chapter 4/Main.java: -------------------------------------------------------------------------------- 1 | package ChapterFour; 2 | 3 | // Main class for testing 4 | public class Main { 5 | public static void main(String[] args) { 6 | HashTable hashTable = new HashTable<>(5); 7 | 8 | // Insert key-value pairs 9 | hashTable.insert(12, "Apple"); 10 | hashTable.insert(5, "Orange"); 11 | hashTable.insert(17, "Banana"); 12 | hashTable.insert(10, "Grapes"); 13 | hashTable.insert(22, "Watermelon"); 14 | hashTable.insert(15, "Pineapple"); 15 | 16 | // Insert a duplicate key with a different value 17 | hashTable.insert(10, "Updated Grapes"); // Should update the value 18 | 19 | // Display the hash table 20 | hashTable.display(); 21 | 22 | // Search for a key 23 | System.out.println("Search for key 17: " + hashTable.search(17)); 24 | System.out.println("Search for key 10: " + hashTable.search(10)); // Should return "Updated Grapes" 25 | System.out.println("Search for key 8: " + hashTable.search(8)); // Should return null 26 | } 27 | } -------------------------------------------------------------------------------- /Java/Chapter 4/Node.java: -------------------------------------------------------------------------------- 1 | package ChapterFour; 2 | 3 | // Node class with generic key-value types 4 | public class Node { 5 | K key; 6 | V value; 7 | Node next; 8 | 9 | public Node(K key, V value) { 10 | this.key = key; 11 | this.value = value; 12 | this.next = null; 13 | } 14 | } -------------------------------------------------------------------------------- /Java/Chapter 5/BinaryTree.java: -------------------------------------------------------------------------------- 1 | public class BinaryTree { 2 | TreeNode root; 3 | 4 | // 1. Create a binary tree from array (ignoring index 0) 5 | public TreeNode createTreeFromArray(int[] arr, int i) { 6 | if (i >= arr.length) return null; 7 | TreeNode node = new TreeNode(arr[i]); 8 | node.left = createTreeFromArray(arr, 2 * i); 9 | node.right = createTreeFromArray(arr, 2 * i + 1); 10 | return node; 11 | } 12 | 13 | // 2. Depth of a node 14 | public int depth(TreeNode root, int key, int d) { 15 | if (root == null) return -1; 16 | if (root.elem == key) return d; 17 | 18 | int left = depth(root.left, key, d + 1); 19 | if (left != -1) return left; 20 | 21 | return depth(root.right, key, d + 1); 22 | } 23 | 24 | // 3. Height of a node 25 | public int height(TreeNode node) { 26 | if (node == null) return -1; 27 | int left = height(node.left); 28 | int right = height(node.right); 29 | return Math.max(left, right) + 1; 30 | } 31 | 32 | // 4. Number of nodes 33 | public int countNodes(TreeNode node) { 34 | if (node == null) return 0; 35 | return 1 + countNodes(node.left) + countNodes(node.right); 36 | } 37 | 38 | // 5. Full binary tree check 39 | public boolean isFull(TreeNode node) { 40 | if (node == null) return true; 41 | if ((node.left == null && node.right != null) || (node.left != null && node.right == null)) return false; 42 | return isFull(node.left) && isFull(node.right); 43 | } 44 | 45 | // 6. Complete binary tree check 46 | public boolean isComplete(TreeNode node, int index, int totalNodes) { 47 | if (node == null) return true; 48 | if (index > totalNodes) return false; 49 | return isComplete(node.left, 2 * index, totalNodes) && 50 | isComplete(node.right, 2 * index + 1, totalNodes); 51 | } 52 | 53 | // 7. Perfect binary tree check 54 | public boolean isPerfect(TreeNode node, int depth, int level) { 55 | if (node == null) return true; 56 | if (node.left == null && node.right == null) return depth == level; 57 | if (node.left == null || node.right == null) return false; 58 | return isPerfect(node.left, depth, level + 1) && 59 | isPerfect(node.right, depth, level + 1); 60 | } 61 | 62 | // 8. Balanced binary tree check 63 | public boolean isBalanced(TreeNode node) { 64 | return checkBalance(node) != -1; 65 | } 66 | 67 | private int checkBalance(TreeNode node) { 68 | if (node == null) return 0; 69 | int left = checkBalance(node.left); 70 | int right = checkBalance(node.right); 71 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) return -1; 72 | return Math.max(left, right) + 1; 73 | } 74 | 75 | // MAIN for testing 76 | public static void main(String[] args) { 77 | BinaryTree bt = new BinaryTree(); 78 | int[] arr = {0, 1, 2, 3, 4, 5, 6, 7}; // index 0 ignored 79 | bt.root = bt.createTreeFromArray(arr, 1); 80 | 81 | System.out.println("Depth of 6: " + bt.depth(bt.root, 6, 0)); 82 | System.out.println("Height of root: " + bt.height(bt.root)); 83 | System.out.println("Number of nodes: " + bt.countNodes(bt.root)); 84 | System.out.println("Is Full: " + bt.isFull(bt.root)); 85 | System.out.println("Is Complete: " + bt.isComplete(bt.root, 1, bt.countNodes(bt.root))); 86 | System.out.println("Is Perfect: " + bt.isPerfect(bt.root, bt.height(bt.root), 0)); 87 | System.out.println("Is Balanced: " + bt.isBalanced(bt.root)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Java/Chapter 5/TreeNode.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int elem; 3 | TreeNode left, right; 4 | 5 | public TreeNode(int elem) { 6 | this.elem = elem; 7 | this.left = null; 8 | this.right = null; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Java/Chapter 6/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | public class BinarySearchTree { 2 | Node root; 3 | 4 | // Insert an element 5 | public void insert(int elem) { 6 | root = insertRecursive(root, elem); 7 | } 8 | 9 | private Node insertRecursive(Node node, int elem) { 10 | if (node == null) return new Node(elem); 11 | if (elem < node.elem) node.left = insertRecursive(node.left, elem); 12 | else if (elem > node.elem) node.right = insertRecursive(node.right, elem); 13 | return node; 14 | } 15 | 16 | // Search for an element 17 | public boolean search(int elem) { 18 | return searchRecursive(root, elem); 19 | } 20 | 21 | private boolean searchRecursive(Node node, int elem) { 22 | if (node == null) return false; 23 | if (elem == node.elem) return true; 24 | if (elem < node.elem) return searchRecursive(node.left, elem); 25 | else return searchRecursive(node.right, elem); 26 | } 27 | 28 | // Delete using Inorder Successor 29 | public void deleteWithSuccessor(int elem) { 30 | root = deleteSuccessorRecursive(root, elem); 31 | } 32 | 33 | private Node deleteSuccessorRecursive(Node node, int elem) { 34 | if (node == null) return null; 35 | if (elem < node.elem) node.left = deleteSuccessorRecursive(node.left, elem); 36 | else if (elem > node.elem) node.right = deleteSuccessorRecursive(node.right, elem); 37 | else { 38 | if (node.left == null) return node.right; 39 | if (node.right == null) return node.left; 40 | Node successor = findMin(node.right); 41 | node.elem = successor.elem; 42 | node.right = deleteSuccessorRecursive(node.right, successor.elem); 43 | } 44 | return node; 45 | } 46 | 47 | // Delete using Inorder Predecessor 48 | public void deleteWithPredecessor(int elem) { 49 | root = deletePredecessorRecursive(root, elem); 50 | } 51 | 52 | private Node deletePredecessorRecursive(Node node, int elem) { 53 | if (node == null) return null; 54 | if (elem < node.elem) node.left = deletePredecessorRecursive(node.left, elem); 55 | else if (elem > node.elem) node.right = deletePredecessorRecursive(node.right, elem); 56 | else { 57 | if (node.left == null) return node.right; 58 | if (node.right == null) return node.left; 59 | Node predecessor = findMax(node.left); 60 | node.elem = predecessor.elem; 61 | node.left = deletePredecessorRecursive(node.left, predecessor.elem); 62 | } 63 | return node; 64 | } 65 | 66 | private Node findMin(Node node) { 67 | while (node.left != null) node = node.left; 68 | return node; 69 | } 70 | 71 | private Node findMax(Node node) { 72 | while (node.right != null) node = node.right; 73 | return node; 74 | } 75 | 76 | // Balance the BST 77 | public void balance() { 78 | int[] sorted = toSortedArray(); 79 | root = buildBalancedBST(sorted, 0, sorted.length - 1); 80 | } 81 | 82 | private Node buildBalancedBST(int[] arr, int start, int end) { 83 | if (start > end) return null; 84 | int mid = (start + end) / 2; 85 | Node node = new Node(arr[mid]); 86 | node.left = buildBalancedBST(arr, start, mid - 1); 87 | node.right = buildBalancedBST(arr, mid + 1, end); 88 | return node; 89 | } 90 | 91 | // Convert BST to sorted array using in-order traversal 92 | private int[] toSortedArray() { 93 | int size = countNodes(root); 94 | int[] result = new int[size]; 95 | fillArray(root, result, new int[]{0}); 96 | return result; 97 | } 98 | 99 | private void fillArray(Node node, int[] arr, int[] index) { 100 | if (node == null) return; 101 | fillArray(node.left, arr, index); 102 | arr[index[0]++] = node.elem; 103 | fillArray(node.right, arr, index); 104 | } 105 | 106 | private int countNodes(Node node) { 107 | if (node == null) return 0; 108 | return 1 + countNodes(node.left) + countNodes(node.right); 109 | } 110 | 111 | // Print in-order traversal 112 | public void printInOrder() { 113 | printInOrderRecursive(root); 114 | System.out.println(); 115 | } 116 | 117 | private void printInOrderRecursive(Node node) { 118 | if (node == null) return; 119 | printInOrderRecursive(node.left); 120 | System.out.print(node.elem + " "); 121 | printInOrderRecursive(node.right); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Java/Chapter 6/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | public static void main(String[] args) { 3 | BinarySearchTree bst = new BinarySearchTree(); 4 | int[] values = {30, 10, 50, 5, 20, 40, 60, 1}; 5 | 6 | for (int val : values) bst.insert(val); 7 | 8 | System.out.print("In-order before deletion: "); 9 | bst.printInOrder(); 10 | 11 | System.out.println("Searching 20: " + bst.search(20)); 12 | System.out.println("Searching 100: " + bst.search(100)); 13 | 14 | bst.deleteWithSuccessor(30); 15 | System.out.print("In-order after deleting 30 using successor: "); 16 | bst.printInOrder(); 17 | 18 | bst.insert(30); 19 | bst.deleteWithPredecessor(50); 20 | System.out.print("In-order after deleting 50 using predecessor: "); 21 | bst.printInOrder(); 22 | 23 | bst.balance(); 24 | System.out.print("In-order after balancing: "); 25 | bst.printInOrder(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/Chapter 6/MaxHeap.java: -------------------------------------------------------------------------------- 1 | public class MaxHeap { 2 | private int[] heap; 3 | private int size; 4 | private int capacity; 5 | 6 | public MaxHeap(int capacity) { 7 | this.capacity = capacity; 8 | heap = new int[capacity]; 9 | size = 0; 10 | } 11 | 12 | // Insert into Max Heap 13 | public void insert(int value) { 14 | if (size == capacity) { 15 | System.out.println("Heap is full"); 16 | return; 17 | } 18 | heap[size] = value; 19 | swim(size); 20 | size++; 21 | } 22 | 23 | // Swim up to maintain heap property 24 | private void swim(int index) { 25 | while (index > 0 && heap[index] > heap[parent(index)]) { 26 | swap(index, parent(index)); 27 | index = parent(index); 28 | } 29 | } 30 | 31 | private int parent(int index) { 32 | return (index - 1) / 2; 33 | } 34 | 35 | // Delete the max (root) element 36 | public int deleteMax() { 37 | if (size == 0) { 38 | throw new IllegalStateException("Heap is empty"); 39 | } 40 | int max = heap[0]; 41 | swap(0, size - 1); 42 | size--; 43 | heapify(0); 44 | return max; 45 | } 46 | 47 | // Heapify down to maintain heap property 48 | private void heapify(int index) { 49 | int largest = index; 50 | int left = 2 * index + 1; 51 | int right = 2 * index + 2; 52 | 53 | if (left < size && heap[left] > heap[largest]) 54 | largest = left; 55 | if (right < size && heap[right] > heap[largest]) 56 | largest = right; 57 | 58 | if (largest != index) { 59 | swap(index, largest); 60 | heapify(largest); 61 | } 62 | } 63 | 64 | // Swap helper 65 | private void swap(int i, int j) { 66 | int temp = heap[i]; 67 | heap[i] = heap[j]; 68 | heap[j] = temp; 69 | } 70 | 71 | // Heap sort (in-place) 72 | public void heapSort() { 73 | int originalSize = size; 74 | for (int i = size - 1; i > 0; i--) { 75 | swap(0, i); 76 | size--; 77 | heapify(0); 78 | } 79 | size = originalSize; 80 | } 81 | 82 | // Display heap 83 | public void printHeap() { 84 | for (int i = 0; i < size; i++) { 85 | System.out.print(heap[i] + " "); 86 | } 87 | System.out.println(); 88 | } 89 | 90 | // Display array after sorting 91 | public void printSorted() { 92 | heapSort(); 93 | for (int i = 0; i < size; i++) { 94 | System.out.print(heap[i] + " "); 95 | } 96 | System.out.println(); 97 | } 98 | 99 | // Main method for testing 100 | public static void main(String[] args) { 101 | MaxHeap maxHeap = new MaxHeap(10); 102 | maxHeap.insert(10); 103 | maxHeap.insert(20); 104 | maxHeap.insert(5); 105 | maxHeap.insert(7); 106 | maxHeap.insert(30); 107 | maxHeap.insert(15); 108 | 109 | System.out.println("Heap:"); 110 | maxHeap.printHeap(); 111 | 112 | System.out.println("Deleted Max: " + maxHeap.deleteMax()); 113 | 114 | System.out.println("Heap After Deletion:"); 115 | maxHeap.printHeap(); 116 | 117 | System.out.println("Heap Sort:"); 118 | maxHeap.printSorted(); 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /Java/Chapter 6/Node.java: -------------------------------------------------------------------------------- 1 | public class Node { 2 | int elem; 3 | Node left, right; 4 | 5 | public Node(int elem) { 6 | this.elem = elem; 7 | this.left = null; 8 | this.right = null; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Python/Chapter 1/ArrayUtils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class ArrayUtils: 4 | 5 | @staticmethod 6 | def iterate(arr): 7 | for element in arr: 8 | print(element, end=" ") 9 | print() 10 | 11 | @staticmethod 12 | def resize(arr, new_size): 13 | resized = np.zeros(new_size, dtype=arr.dtype) 14 | for i in range(min(len(arr), new_size)): 15 | resized[i] = arr[i] 16 | return resized 17 | 18 | @staticmethod 19 | def copy_array(arr): 20 | copy = np.zeros_like(arr) 21 | for i in range(len(arr)): 22 | copy[i] = arr[i] 23 | return copy 24 | 25 | @staticmethod 26 | def shift_left(arr): 27 | for i in range(len(arr) - 1): 28 | arr[i] = arr[i + 1] 29 | arr[-1] = 0 30 | 31 | @staticmethod 32 | def shift_right(arr): 33 | for i in range(len(arr) - 1, 0, -1): 34 | arr[i] = arr[i - 1] 35 | arr[0] = 0 36 | 37 | @staticmethod 38 | def rotate_left(arr): 39 | first = arr[0] 40 | for i in range(len(arr) - 1): 41 | arr[i] = arr[i + 1] 42 | arr[-1] = first 43 | 44 | @staticmethod 45 | def rotate_right(arr): 46 | last = arr[-1] 47 | for i in range(len(arr) - 1, 0, -1): 48 | arr[i] = arr[i - 1] 49 | arr[0] = last 50 | 51 | @staticmethod 52 | def reverse_out_of_place(arr): 53 | reversed_array = np.zeros_like(arr) 54 | for i in range(len(arr)): 55 | reversed_array[i] = arr[len(arr) - 1 - i] 56 | return reversed_array 57 | 58 | @staticmethod 59 | def reverse_in_place(arr): 60 | left, right = 0, len(arr) - 1 61 | while left < right: 62 | arr[left], arr[right] = arr[right], arr[left] 63 | left += 1 64 | right -= 1 65 | 66 | @staticmethod 67 | def insert(arr, index, value, current_size): 68 | if index < 0 or index > current_size: 69 | raise IndexError("Invalid index") 70 | if current_size == len(arr): 71 | arr = ArrayUtils.resize(arr, len(arr) * 2) 72 | for i in range(current_size, index, -1): 73 | arr[i] = arr[i - 1] 74 | arr[index] = value 75 | return arr 76 | 77 | @staticmethod 78 | def delete(arr, index, current_size): 79 | if index < 0 or index >= current_size: 80 | raise IndexError("Invalid index") 81 | for i in range(index, current_size - 1): 82 | arr[i] = arr[i + 1] 83 | arr[current_size - 1] = 0 84 | 85 | 86 | # Example usage 87 | if __name__ == "__main__": 88 | array = np.array([1, 2, 3, 4, 5, 0, 0], dtype=int) 89 | current_size = 5 90 | 91 | print("Original array: ", end="") 92 | ArrayUtils.iterate(array) 93 | 94 | print("Resized array: ", end="") 95 | resized = ArrayUtils.resize(array, 10) 96 | ArrayUtils.iterate(resized) 97 | 98 | print("Copied array: ", end="") 99 | copied = ArrayUtils.copy_array(array) 100 | ArrayUtils.iterate(copied) 101 | 102 | print("Shift left: ", end="") 103 | ArrayUtils.shift_left(array) 104 | ArrayUtils.iterate(array) 105 | 106 | print("Shift right: ", end="") 107 | ArrayUtils.shift_right(array) 108 | ArrayUtils.iterate(array) 109 | 110 | print("Rotate left: ", end="") 111 | ArrayUtils.rotate_left(array) 112 | ArrayUtils.iterate(array) 113 | 114 | print("Rotate right: ", end="") 115 | ArrayUtils.rotate_right(array) 116 | ArrayUtils.iterate(array) 117 | 118 | print("Reversed out-of-place: ", end="") 119 | reversed_out = ArrayUtils.reverse_out_of_place(array) 120 | ArrayUtils.iterate(reversed_out) 121 | 122 | print("Reversed in-place: ", end="") 123 | ArrayUtils.reverse_in_place(array) 124 | ArrayUtils.iterate(array) 125 | 126 | print("After insertion: ", end="") 127 | array = ArrayUtils.insert(array, 2, 10, current_size) 128 | current_size += 1 129 | ArrayUtils.iterate(array) 130 | 131 | print("After deletion: ", end="") 132 | ArrayUtils.delete(array, 2, current_size) 133 | current_size -= 1 134 | ArrayUtils.iterate(array) 135 | -------------------------------------------------------------------------------- /Python/Chapter 1/MatrixUtils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class MatrixUtils: 4 | @staticmethod 5 | def create_2d_array(rows, cols, initial_value=0): 6 | # Create a 2D array with zeros using np.zeros 7 | matrix = np.zeros((rows, cols), dtype=int) 8 | 9 | # If initial_value is not zero, update all elements 10 | if initial_value != 0: 11 | for i in range(rows): 12 | for j in range(cols): 13 | matrix[i][j] = initial_value 14 | 15 | return matrix.tolist() 16 | 17 | @staticmethod 18 | def iterate_rows(matrix): 19 | for row in matrix: 20 | print(row) 21 | 22 | @staticmethod 23 | def iterate_columns(matrix): 24 | rows = len(matrix) 25 | cols = len(matrix[0]) 26 | for j in range(cols): 27 | for i in range(rows): 28 | print(matrix[i][j], end=" ") 29 | print() 30 | 31 | @staticmethod 32 | def sum_all_values(matrix): 33 | total = 0 34 | for row in matrix: 35 | for value in row: 36 | total += value 37 | return total 38 | 39 | @staticmethod 40 | def sum_rows(matrix): 41 | row_sums = [] 42 | for row in matrix: 43 | row_sums.append(sum(row)) 44 | return row_sums 45 | 46 | @staticmethod 47 | def sum_columns(matrix): 48 | rows = len(matrix) 49 | cols = len(matrix[0]) 50 | col_sums = [0] * cols 51 | for j in range(cols): 52 | for i in range(rows): 53 | col_sums[j] += matrix[i][j] 54 | return col_sums 55 | 56 | @staticmethod 57 | def swap_columns(matrix): 58 | rows = len(matrix) 59 | cols = len(matrix[0]) 60 | for i in range(rows): 61 | for j in range(cols // 2): 62 | # Swap columns (0 ⇌ n-1, 1 ⇌ n-2, etc.) 63 | temp = matrix[i][j] 64 | matrix[i][j] = matrix[i][cols - 1 - j] 65 | matrix[i][cols - 1 - j] = temp 66 | return matrix 67 | 68 | @staticmethod 69 | def sum_primary_diagonal(matrix): 70 | total = 0 71 | for i in range(len(matrix)): 72 | total += matrix[i][i] 73 | return total 74 | 75 | @staticmethod 76 | def sum_secondary_diagonal(matrix): 77 | total = 0 78 | n = len(matrix) 79 | for i in range(n): 80 | total += matrix[i][n - 1 - i] 81 | return total 82 | 83 | @staticmethod 84 | def add_matrices(matrix1, matrix2): 85 | rows = len(matrix1) 86 | cols = len(matrix1[0]) 87 | result = np.zeros((rows, cols), dtype=int) 88 | for i in range(rows): 89 | for j in range(cols): 90 | result[i][j] = matrix1[i][j] + matrix2[i][j] 91 | return result.tolist() 92 | 93 | @staticmethod 94 | def multiply_matrices(matrix1, matrix2): 95 | rows1 = len(matrix1) 96 | cols1 = len(matrix1[0]) 97 | cols2 = len(matrix2[0]) 98 | result = np.zeros((rows1, cols2), dtype=int) 99 | for i in range(rows1): 100 | for j in range(cols2): 101 | for k in range(cols1): 102 | result[i][j] += matrix1[i][k] * matrix2[k][j] 103 | return result.tolist() 104 | 105 | 106 | # Example Usage 107 | if __name__ == "__main__": 108 | matrix1 = MatrixUtils.create_2d_array(3, 3, 1) 109 | matrix2 = MatrixUtils.create_2d_array(3, 3, 2) 110 | 111 | print("Matrix 1:") 112 | MatrixUtils.iterate_rows(matrix1) 113 | 114 | print("\nMatrix 2:") 115 | MatrixUtils.iterate_rows(matrix2) 116 | 117 | print("\nSum of all values in Matrix 1:", MatrixUtils.sum_all_values(matrix1)) 118 | 119 | print("\nRow-wise sums of Matrix 1:") 120 | row_sums = MatrixUtils.sum_rows(matrix1) 121 | print(row_sums) 122 | 123 | print("\nColumn-wise sums of Matrix 1:") 124 | col_sums = MatrixUtils.sum_columns(matrix1) 125 | print(col_sums) 126 | 127 | print("\nSum of primary diagonal of Matrix 2:", MatrixUtils.sum_primary_diagonal(matrix2)) 128 | print("Sum of secondary diagonal of Matrix 2:", MatrixUtils.sum_secondary_diagonal(matrix2)) 129 | 130 | print("\nAddition of Matrix 1 and Matrix 2:") 131 | added_matrix = MatrixUtils.add_matrices(matrix1, matrix2) 132 | MatrixUtils.iterate_rows(added_matrix) 133 | 134 | print("\nMultiplication of Matrix 1 and Matrix 2:") 135 | multiplied_matrix = MatrixUtils.multiply_matrices(matrix1, matrix2) 136 | MatrixUtils.iterate_rows(multiplied_matrix) 137 | 138 | print("\nMatrix before swapping columns:") 139 | test_matrix = [ 140 | [1, 2, 3, 4], 141 | [5, 6, 7, 8], 142 | [9, 10, 11, 12], 143 | [13, 14, 15, 16] 144 | ] 145 | MatrixUtils.iterate_rows(test_matrix) 146 | 147 | print("\nMatrix after swapping columns:") 148 | swapped_matrix = MatrixUtils.swap_columns(test_matrix) 149 | MatrixUtils.iterate_rows(swapped_matrix) 150 | -------------------------------------------------------------------------------- /Python/Chapter 2/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Python/Chapter 2/DoublyLinkedList.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, elem): 3 | self.elem = elem 4 | self.next = None 5 | self.prev = None 6 | 7 | 8 | class DoublyCircularLinkedList: 9 | def __init__(self): 10 | # Initialize the dummy head node 11 | self.head = Node(-1) 12 | self.head.next = self.head 13 | self.head.prev = self.head 14 | 15 | # 1. Create a Linked List from an array 16 | def create_from_array(self, arr): 17 | for elem in arr: 18 | self.insert_at_end(elem) 19 | 20 | # 2. Iterate the Linked List 21 | def iterate(self): 22 | current = self.head.next 23 | while current != self.head: 24 | print(current.elem, end=" -> ") 25 | current = current.next 26 | print("HEAD") 27 | 28 | # 3. Count the items in the Linked List 29 | def count_items(self): 30 | count = 0 31 | current = self.head.next 32 | while current != self.head: 33 | count += 1 34 | current = current.next 35 | return count 36 | 37 | # 4. Retrieve a node from an index 38 | def get_node(self, index): 39 | if index < 0: 40 | return None 41 | current = self.head.next 42 | current_index = 0 43 | while current != self.head: 44 | if current_index == index: 45 | return current 46 | current_index += 1 47 | current = current.next 48 | return None # Index out of bounds 49 | 50 | # 5a. Insert a node at the start 51 | def insert_at_start(self, elem): 52 | new_node = Node(elem) 53 | first = self.head.next 54 | new_node.next = first 55 | new_node.prev = self.head 56 | self.head.next = new_node 57 | first.prev = new_node 58 | 59 | # 5b. Insert a node at the end 60 | def insert_at_end(self, elem): 61 | new_node = Node(elem) 62 | last = self.head.prev 63 | new_node.next = self.head 64 | new_node.prev = last 65 | last.next = new_node 66 | self.head.prev = new_node 67 | 68 | # 5c. Insert a node at a specific index 69 | def insert_at_index(self, index, elem): 70 | if index < 0: 71 | return 72 | if index == 0: 73 | self.insert_at_start(elem) 74 | return 75 | 76 | current = self.head.next 77 | current_index = 0 78 | while current != self.head: 79 | if current_index == index: 80 | new_node = Node(elem) 81 | prev_node = current.prev 82 | new_node.next = current 83 | new_node.prev = prev_node 84 | prev_node.next = new_node 85 | current.prev = new_node 86 | return 87 | current_index += 1 88 | current = current.next 89 | 90 | if current_index == index: # Insert at the end 91 | self.insert_at_end(elem) 92 | 93 | # 6. Remove a node from the list 94 | def remove(self, index): 95 | if index < 0: 96 | return 97 | 98 | current = self.head.next 99 | current_index = 0 100 | while current != self.head: 101 | if current_index == index: 102 | prev_node = current.prev 103 | next_node = current.next 104 | prev_node.next = next_node 105 | next_node.prev = prev_node 106 | return 107 | current_index += 1 108 | current = current.next 109 | 110 | print("Index out of bounds") 111 | 112 | 113 | # Main Method 114 | if __name__ == "__main__": 115 | # Initialize the linked list 116 | linked_list = DoublyCircularLinkedList() 117 | 118 | # 1. Create from array 119 | print("Creating Linked List from array:") 120 | linked_list.create_from_array([10, 20, 30, 40, 50]) 121 | linked_list.iterate() 122 | 123 | # 2. Count items 124 | print("\nCount of items in the list:") 125 | print(linked_list.count_items()) 126 | 127 | # 3. Get node at index 128 | print("\nNode at index 2:") 129 | node = linked_list.get_node(2) 130 | if node: 131 | print(node.elem) 132 | 133 | # 4. Insert at start 134 | print("\nInserting 5 at the start:") 135 | linked_list.insert_at_start(5) 136 | linked_list.iterate() 137 | 138 | # 5. Insert at end 139 | print("\nInserting 60 at the end:") 140 | linked_list.insert_at_end(60) 141 | linked_list.iterate() 142 | 143 | # 6. Insert at index 144 | print("\nInserting 25 at index 3:") 145 | linked_list.insert_at_index(3, 25) 146 | linked_list.iterate() 147 | 148 | # 7. Remove node 149 | print("\nRemoving node at index 4:") 150 | linked_list.remove(4) 151 | linked_list.iterate() 152 | -------------------------------------------------------------------------------- /Python/Chapter 2/SinglyLinkedList.py: -------------------------------------------------------------------------------- 1 | class SinglyLinkedList: 2 | 3 | class Node: 4 | def __init__(self, elem): 5 | self.elem = elem 6 | self.next = None 7 | 8 | def __init__(self): 9 | self.head = None 10 | 11 | # 1. Create a Linked List from an array 12 | def create_from_array(self, arr): 13 | if not arr: 14 | return 15 | self.head = self.Node(arr[0]) 16 | current = self.head 17 | for elem in arr[1:]: 18 | current.next = self.Node(elem) 19 | current = current.next 20 | 21 | # 2. Iteration of the linked list 22 | def iterate(self): 23 | current = self.head 24 | while current: 25 | print(f"{current.elem} -> ", end="") 26 | current = current.next 27 | print() 28 | 29 | # 3. Count the items in the linked list 30 | def count(self): 31 | count = 0 32 | current = self.head 33 | while current: 34 | count += 1 35 | current = current.next 36 | return count 37 | 38 | # 4. Retrieve index of an element 39 | def index_of(self, elem): 40 | index = 0 41 | current = self.head 42 | while current: 43 | if current.elem == elem: 44 | return index 45 | current = current.next 46 | index += 1 47 | return -1 # Element not found 48 | 49 | # 5. Retrieve a node from an index 50 | def get_node(self, index): 51 | current_index = 0 52 | current = self.head 53 | while current: 54 | if current_index == index: 55 | return current 56 | current = current.next 57 | current_index += 1 58 | return None # Index out of bounds 59 | 60 | # 6. Update value in a specific index 61 | def update(self, index, new_value): 62 | node = self.get_node(index) 63 | if node: 64 | node.elem = new_value 65 | return True 66 | return False # Index out of bounds 67 | 68 | # 7. Search for an element in the list 69 | def search(self, elem): 70 | current = self.head 71 | while current: 72 | if current.elem == elem: 73 | return True 74 | current = current.next 75 | return False 76 | 77 | # 8. Insert a node in the list 78 | def insert(self, index, elem): 79 | new_node = self.Node(elem) 80 | if index == 0: # Insert at the beginning 81 | new_node.next = self.head 82 | self.head = new_node 83 | return 84 | prev = self.get_node(index - 1) 85 | if prev: # Insert in the middle or at the end 86 | new_node.next = prev.next 87 | prev.next = new_node 88 | 89 | # 9. Remove a node from the list 90 | def remove(self, index): 91 | if index == 0 and self.head: # Remove from the beginning 92 | self.head = self.head.next 93 | return 94 | prev = self.get_node(index - 1) 95 | if prev and prev.next: # Remove from the middle or end 96 | prev.next = prev.next.next 97 | 98 | # 10. Copying a linked list 99 | def copy(self): 100 | new_list = SinglyLinkedList() 101 | if not self.head: 102 | return new_list 103 | new_list.head = self.Node(self.head.elem) 104 | current = self.head.next 105 | new_current = new_list.head 106 | while current: 107 | new_current.next = self.Node(current.elem) 108 | current = current.next 109 | new_current = new_current.next 110 | return new_list 111 | 112 | # 11. Out-of-place reverse of a linked list 113 | def reverse_out_of_place(self): 114 | reversed_list = SinglyLinkedList() 115 | current = self.head 116 | while current: 117 | new_node = self.Node(current.elem) 118 | new_node.next = reversed_list.head 119 | reversed_list.head = new_node 120 | current = current.next 121 | return reversed_list 122 | 123 | # 12. In-place reverse of a linked list 124 | def reverse_in_place(self): 125 | prev = None 126 | current = self.head 127 | while current: 128 | next_node = current.next 129 | current.next = prev 130 | prev = current 131 | current = next_node 132 | self.head = prev 133 | 134 | # 13. Rotating the list left 135 | def rotate_left(self, k): 136 | if not self.head or k <= 0: 137 | return 138 | size = self.count() 139 | k = k % size # Handle rotations greater than size 140 | if k == 0: 141 | return 142 | 143 | current = self.head 144 | for _ in range(k - 1): 145 | current = current.next 146 | 147 | new_head = current.next 148 | current.next = None 149 | 150 | tail = new_head 151 | while tail.next: 152 | tail = tail.next 153 | tail.next = self.head 154 | self.head = new_head 155 | 156 | # 14. Rotating the list right 157 | def rotate_right(self, k): 158 | if not self.head or k <= 0: 159 | return 160 | size = self.count() 161 | k = k % size # Handle rotations greater than size 162 | if k == 0: 163 | return 164 | 165 | self.rotate_left(size - k) 166 | 167 | 168 | # Driver Code for Testing 169 | if __name__ == "__main__": 170 | list_ = SinglyLinkedList() 171 | 172 | # 1. Create a linked list from an array 173 | arr = [1, 2, 3, 4, 5] 174 | list_.create_from_array(arr) 175 | print("Original List:") 176 | list_.iterate() 177 | 178 | # 2. Iterate through the linked list 179 | print("Iterating through the list:") 180 | list_.iterate() 181 | 182 | # 3. Count the items in the linked list 183 | print(f"Count of items in the list: {list_.count()}") 184 | 185 | # 4. Retrieve index of an element 186 | elem_to_find = 3 187 | print(f"Index of element {elem_to_find}: {list_.index_of(elem_to_find)}") 188 | 189 | # 5. Retrieve a node from an index 190 | index_to_retrieve = 2 191 | node = list_.get_node(index_to_retrieve) 192 | print( 193 | f"Element at index {index_to_retrieve}: {node.elem if node else 'Index out of bounds'}" 194 | ) 195 | 196 | # 6. Update value at a specific index 197 | index_to_update = 1 198 | new_value = 10 199 | if list_.update(index_to_update, new_value): 200 | print(f"Updated value at index {index_to_update} to {new_value}") 201 | list_.iterate() 202 | else: 203 | print(f"Failed to update index {index_to_update}") 204 | 205 | # 7. Search for an element in the list 206 | search_element = 4 207 | print(f"Element {search_element} found: {list_.search(search_element)}") 208 | 209 | # 8. Insert a node in the list 210 | print("Inserting 99 at index 0:") 211 | list_.insert(0, 99) 212 | list_.iterate() 213 | 214 | print("Inserting 77 at index 3:") 215 | list_.insert(3, 77) 216 | list_.iterate() 217 | 218 | print("Inserting 55 at the end:") 219 | list_.insert(list_.count(), 55) 220 | list_.iterate() 221 | 222 | # 9. Remove a node from the list 223 | print("Removing the node at index 2:") 224 | list_.remove(2) 225 | list_.iterate() 226 | 227 | # 10. Copying the linked list 228 | copied_list = list_.copy() 229 | print("Copied list:") 230 | copied_list.iterate() 231 | 232 | # 11. Out-of-place reverse of a linked list 233 | reversed_list = list_.reverse_out_of_place() 234 | print("Reversed list (out of place):") 235 | reversed_list.iterate() 236 | 237 | # 12. In-place reverse of a linked list 238 | list_.reverse_in_place() 239 | print("Reversed list (in place):") 240 | list_.iterate() 241 | 242 | # 13. Rotating the list left 243 | print("Rotating the list left by 2 positions:") 244 | list_.rotate_left(2) 245 | list_.iterate() 246 | 247 | # 14. Rotating the list right 248 | print("Rotating the list right by 2 positions:") 249 | list_.rotate_right(2) 250 | list_.iterate() 251 | -------------------------------------------------------------------------------- /Python/Chapter 3/queuee.py: -------------------------------------------------------------------------------- 1 | import stack 2 | class Node: 3 | def __init__(self, elem): 4 | self.elem = elem 5 | self.next = None 6 | 7 | class LinkedListQueue: 8 | def __init__(self): 9 | self.front = self.rear = None 10 | 11 | def enqueue(self, elem): 12 | new_node = Node(elem) 13 | if self.rear is None: 14 | self.front = self.rear = new_node 15 | return 16 | self.rear.next = new_node 17 | self.rear = new_node 18 | 19 | def dequeue(self): 20 | if self.is_empty(): 21 | raise IndexError("Queue is empty") 22 | removed_elem = self.front.elem 23 | self.front = self.front.next 24 | if self.front is None: 25 | self.rear = None 26 | return removed_elem 27 | 28 | def peek(self): 29 | if self.is_empty(): 30 | raise IndexError("Queue is empty") 31 | return self.front.elem 32 | 33 | def is_empty(self): 34 | return self.front is None 35 | 36 | def display_queue(self): 37 | current = self.front 38 | print("Queue (front to rear):", end=" ") 39 | while current: 40 | print(f"{current.elem} ->", end=" ") 41 | current = current.next 42 | print("NULL") 43 | 44 | class QueueOperations: 45 | 46 | @staticmethod 47 | def reverse_queue(queue): 48 | st = stack.LinkedListStack() # Using our Predefined Stack Class 49 | while not queue.is_empty(): 50 | st.push(queue.dequeue()) 51 | while st.is_empty() != False: 52 | queue.enqueue(st.pop()) 53 | return queue 54 | 55 | @staticmethod 56 | def generate_binary_numbers(n): 57 | queue = LinkedListQueue() 58 | queue.enqueue(1) 59 | 60 | for _ in range(n): 61 | front = queue.dequeue() 62 | print(front, end=" ") 63 | queue.enqueue(front * 10) 64 | queue.enqueue(front * 10 + 1) 65 | print() 66 | 67 | @staticmethod 68 | def is_queue_palindrome(queue): 69 | st = stack.LinkedListStack() # Using our Predefined Stack Class 70 | temp_queue = LinkedListQueue() 71 | 72 | while not queue.is_empty(): 73 | elem = queue.dequeue() 74 | st.push(elem) 75 | temp_queue.enqueue(elem) 76 | 77 | while not temp_queue.is_empty(): 78 | if temp_queue.dequeue() != st.pop(): 79 | return False 80 | return True 81 | 82 | if __name__ == "__main__": 83 | queue = LinkedListQueue() 84 | queue.enqueue(10) 85 | queue.enqueue(20) 86 | queue.enqueue(30) 87 | print("Original Queue:") 88 | queue.display_queue() 89 | 90 | queue = QueueOperations.reverse_queue(queue) 91 | print("Reversed Queue:") 92 | queue.display_queue() 93 | 94 | print("Binary Numbers up to 5:") 95 | QueueOperations.generate_binary_numbers(5) 96 | 97 | palindrome_queue = LinkedListQueue() 98 | palindrome_queue.enqueue(1) 99 | palindrome_queue.enqueue(2) 100 | palindrome_queue.enqueue(3) 101 | palindrome_queue.enqueue(2) 102 | palindrome_queue.enqueue(1) 103 | 104 | print("Is the queue a palindrome?", QueueOperations.is_queue_palindrome(palindrome_queue)) 105 | -------------------------------------------------------------------------------- /Python/Chapter 3/stack.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, elem): 3 | self.elem = elem 4 | self.next = None 5 | 6 | 7 | class LinkedListStack: 8 | def __init__(self): 9 | self.top = None 10 | 11 | def push(self, elem): 12 | new_node = Node(elem) 13 | new_node.next = self.top 14 | self.top = new_node 15 | 16 | def pop(self): 17 | if self.is_empty(): 18 | raise IndexError("Stack is empty") 19 | popped_elem = self.top.elem 20 | self.top = self.top.next 21 | return popped_elem 22 | 23 | def peek(self): 24 | if self.is_empty(): 25 | raise IndexError("Stack is empty") 26 | return self.top.elem 27 | 28 | def is_empty(self): 29 | return self.top is None 30 | 31 | def display_stack(self): 32 | current = self.top 33 | print("Stack (top to bottom): ", end="") 34 | while current: 35 | print(f"{current.elem} -> ", end="") 36 | current = current.next 37 | print("NULL") 38 | 39 | class StackOperations: 40 | 41 | @staticmethod 42 | def reverse_stack(stack): 43 | temp_stack = LinkedListStack() 44 | while not stack.is_empty(): 45 | temp_stack.push(stack.pop()) 46 | return temp_stack 47 | 48 | @staticmethod 49 | def evaluate_postfix(expression): 50 | stack = LinkedListStack() 51 | 52 | for ch in expression: 53 | if ch.isdigit(): 54 | stack.push(int(ch)) 55 | else: 56 | operand2 = stack.pop() 57 | operand1 = stack.pop() 58 | if ch == '+': 59 | stack.push(operand1 + operand2) 60 | elif ch == '-': 61 | stack.push(operand1 - operand2) 62 | elif ch == '*': 63 | stack.push(operand1 * operand2) 64 | elif ch == '/': 65 | stack.push(operand1 // operand2) # Integer division 66 | 67 | return stack.pop() 68 | 69 | @staticmethod 70 | def is_balanced_parentheses(expression): 71 | stack = LinkedListStack() 72 | 73 | for ch in expression: 74 | if ch in "({[": 75 | stack.push(ch) 76 | elif ch in ")}]": 77 | if stack.is_empty(): 78 | return False 79 | top = stack.pop() 80 | if (ch == ')' and top != '(') or (ch == '}' and top != '{') or (ch == ']' and top != '['): 81 | return False 82 | 83 | return stack.is_empty() 84 | 85 | if __name__ == "__main__": 86 | # Testing Reverse Stack 87 | stack = LinkedListStack() 88 | stack.push(10) 89 | stack.push(20) 90 | stack.push(30) 91 | print("Original Stack:") 92 | stack.display_stack() 93 | 94 | stack = StackOperations.reverse_stack(stack) 95 | print("Reversed Stack:") 96 | stack.display_stack() 97 | 98 | # Testing Postfix Expression Evaluation 99 | postfix_expression = "53+82-*" # (5 + 3) * (8 - 2) = 48 100 | result = StackOperations.evaluate_postfix(postfix_expression) 101 | print("Postfix Evaluation Result:", result) 102 | 103 | # Testing Parentheses Matching 104 | expr1 = "{[()]}" # Balanced 105 | expr2 = "{[(])}" # Not Balanced 106 | print("Is Balanced:", StackOperations.is_balanced_parentheses(expr1)) # True 107 | print("Is Balanced:", StackOperations.is_balanced_parentheses(expr2)) # False 108 | -------------------------------------------------------------------------------- /Python/Chapter 4/hash_table.py: -------------------------------------------------------------------------------- 1 | # Node class to store key-value pairs in the linked list (collision handling) 2 | class Node: 3 | def __init__(self, key, value): 4 | self.key = key 5 | self.value = value 6 | self.next = None 7 | 8 | # HashTable class implementing Forward Chaining 9 | class HashTable: 10 | def __init__(self, size): 11 | self.size = size 12 | self.table = [None] * size # Array of linked lists 13 | 14 | # Hash function using modulus operation 15 | def hash_function(self, key): 16 | return abs(hash(key)) % self.size # Ensure positive index 17 | 18 | # Insert method (updates value if key exists) 19 | def insert(self, key, value): 20 | index = self.hash_function(key) 21 | current = self.table[index] 22 | 23 | # Check if key exists and update value 24 | while current: 25 | if current.key == key: 26 | current.value = value # Update value for existing key 27 | return 28 | current = current.next 29 | 30 | # Insert at the beginning (Forward Chaining) 31 | new_node = Node(key, value) 32 | new_node.next = self.table[index] 33 | self.table[index] = new_node 34 | 35 | # Search method 36 | def search(self, key): 37 | index = self.hash_function(key) 38 | current = self.table[index] 39 | 40 | while current: 41 | if current.key == key: 42 | return current.value 43 | current = current.next 44 | return None # Key not found 45 | 46 | # Display method 47 | def display(self): 48 | for i in range(self.size): 49 | print(f"Index {i}:", end=" ") 50 | current = self.table[i] 51 | while current: 52 | print(f"({current.key}, {current.value}) ->", end=" ") 53 | current = current.next 54 | print("NULL") 55 | 56 | # Main function for testing 57 | if __name__ == "__main__": 58 | hash_table = HashTable(5) 59 | 60 | # Insert key-value pairs 61 | hash_table.insert(12, "Apple") 62 | hash_table.insert(5, "Orange") 63 | hash_table.insert(17, "Banana") 64 | hash_table.insert(10, "Grapes") 65 | hash_table.insert(22, "Watermelon") 66 | hash_table.insert(15, "Pineapple") 67 | 68 | # Insert a duplicate key with a different value (should update) 69 | hash_table.insert(10, "Updated Grapes") 70 | 71 | # Display the hash table 72 | hash_table.display() 73 | 74 | # Search for a key 75 | print("Search for key 17:", hash_table.search(17)) 76 | print("Search for key 10:", hash_table.search(10)) # Should return "Updated Grapes" 77 | print("Search for key 8:", hash_table.search(8)) # Should return None 78 | -------------------------------------------------------------------------------- /Python/Chapter 5/binary_tree.py: -------------------------------------------------------------------------------- 1 | class TreeNode: 2 | def __init__(self, elem): 3 | self.elem = elem 4 | self.left = None 5 | self.right = None 6 | 7 | class BinaryTree: 8 | def __init__(self): 9 | self.root = None 10 | 11 | # 1. Create a binary tree from array (ignoring index 0) 12 | def create_tree_from_array(self, arr, i): 13 | if i >= len(arr): 14 | return None 15 | node = TreeNode(arr[i]) 16 | node.left = self.create_tree_from_array(arr, 2 * i) 17 | node.right = self.create_tree_from_array(arr, 2 * i + 1) 18 | return node 19 | 20 | # 2. Depth of a node 21 | def depth(self, node, key, d): 22 | if node is None: 23 | return -1 24 | if node.elem == key: 25 | return d 26 | left = self.depth(node.left, key, d + 1) 27 | if left != -1: 28 | return left 29 | return self.depth(node.right, key, d + 1) 30 | 31 | # 3. Height of a node 32 | def height(self, node): 33 | if node is None: 34 | return -1 35 | left = self.height(node.left) 36 | right = self.height(node.right) 37 | return max(left, right) + 1 38 | 39 | # 4. Number of nodes 40 | def count_nodes(self, node): 41 | if node is None: 42 | return 0 43 | return 1 + self.count_nodes(node.left) + self.count_nodes(node.right) 44 | 45 | # 5. Full binary tree check 46 | def is_full(self, node): 47 | if node is None: 48 | return True 49 | if (node.left is None and node.right is not None) or (node.left is not None and node.right is None): 50 | return False 51 | return self.is_full(node.left) and self.is_full(node.right) 52 | 53 | # 6. Complete binary tree check 54 | def is_complete(self, node, index, total_nodes): 55 | if node is None: 56 | return True 57 | if index > total_nodes: 58 | return False 59 | return (self.is_complete(node.left, 2 * index, total_nodes) and 60 | self.is_complete(node.right, 2 * index + 1, total_nodes)) 61 | 62 | # 7. Perfect binary tree check 63 | def is_perfect(self, node, depth, level): 64 | if node is None: 65 | return True 66 | if node.left is None and node.right is None: 67 | return depth == level 68 | if node.left is None or node.right is None: 69 | return False 70 | return (self.is_perfect(node.left, depth, level + 1) and 71 | self.is_perfect(node.right, depth, level + 1)) 72 | 73 | # 8. Balanced binary tree check 74 | def is_balanced(self, node): 75 | return self.check_balance(node) != -1 76 | 77 | def check_balance(self, node): 78 | if node is None: 79 | return 0 80 | left = self.check_balance(node.left) 81 | right = self.check_balance(node.right) 82 | if left == -1 or right == -1 or abs(left - right) > 1: 83 | return -1 84 | return max(left, right) + 1 85 | 86 | # Testing the BinaryTree class 87 | if __name__ == "__main__": 88 | bt = BinaryTree() 89 | arr = [0, 1, 2, 3, 4, 5, 6, 7] # index 0 is ignored 90 | bt.root = bt.create_tree_from_array(arr, 1) 91 | 92 | print("Depth of 6:", bt.depth(bt.root, 6, 0)) 93 | print("Height of root:", bt.height(bt.root)) 94 | print("Number of nodes:", bt.count_nodes(bt.root)) 95 | print("Is Full:", bt.is_full(bt.root)) 96 | total_nodes = bt.count_nodes(bt.root) 97 | print("Is Complete:", bt.is_complete(bt.root, 1, total_nodes)) 98 | print("Is Perfect:", bt.is_perfect(bt.root, bt.height(bt.root), 0)) 99 | print("Is Balanced:", bt.is_balanced(bt.root)) 100 | -------------------------------------------------------------------------------- /Python/Chapter 6/bst.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, elem): 3 | self.elem = elem 4 | self.left = None 5 | self.right = None 6 | 7 | class BinarySearchTree: 8 | def __init__(self): 9 | self.root = None 10 | 11 | # Insert element 12 | def insert(self, elem): 13 | self.root = self._insert_recursive(self.root, elem) 14 | 15 | def _insert_recursive(self, node, elem): 16 | if node is None: 17 | return Node(elem) 18 | if elem < node.elem: 19 | node.left = self._insert_recursive(node.left, elem) 20 | elif elem > node.elem: 21 | node.right = self._insert_recursive(node.right, elem) 22 | return node 23 | 24 | # Search for an element 25 | def search(self, elem): 26 | return self._search_recursive(self.root, elem) 27 | 28 | def _search_recursive(self, node, elem): 29 | if node is None: 30 | return False 31 | if elem == node.elem: 32 | return True 33 | elif elem < node.elem: 34 | return self._search_recursive(node.left, elem) 35 | else: 36 | return self._search_recursive(node.right, elem) 37 | 38 | # Delete using Inorder Successor 39 | def delete_with_successor(self, elem): 40 | self.root = self._delete_successor(self.root, elem) 41 | 42 | def _delete_successor(self, node, elem): 43 | if node is None: 44 | return None 45 | if elem < node.elem: 46 | node.left = self._delete_successor(node.left, elem) 47 | elif elem > node.elem: 48 | node.right = self._delete_successor(node.right, elem) 49 | else: 50 | if node.left is None: 51 | return node.right 52 | elif node.right is None: 53 | return node.left 54 | successor = self._find_min(node.right) 55 | node.elem = successor.elem 56 | node.right = self._delete_successor(node.right, successor.elem) 57 | return node 58 | 59 | # Delete using Inorder Predecessor 60 | def delete_with_predecessor(self, elem): 61 | self.root = self._delete_predecessor(self.root, elem) 62 | 63 | def _delete_predecessor(self, node, elem): 64 | if node is None: 65 | return None 66 | if elem < node.elem: 67 | node.left = self._delete_predecessor(node.left, elem) 68 | elif elem > node.elem: 69 | node.right = self._delete_predecessor(node.right, elem) 70 | else: 71 | if node.left is None: 72 | return node.right 73 | elif node.right is None: 74 | return node.left 75 | predecessor = self._find_max(node.left) 76 | node.elem = predecessor.elem 77 | node.left = self._delete_predecessor(node.left, predecessor.elem) 78 | return node 79 | 80 | def _find_min(self, node): 81 | while node.left: 82 | node = node.left 83 | return node 84 | 85 | def _find_max(self, node): 86 | while node.right: 87 | node = node.right 88 | return node 89 | 90 | # Balance the BST 91 | def balance(self): 92 | sorted_array = self._to_sorted_array() 93 | self.root = self._build_balanced_bst(sorted_array, 0, len(sorted_array) - 1) 94 | 95 | def _build_balanced_bst(self, arr, start, end): 96 | if start > end: 97 | return None 98 | mid = (start + end) // 2 99 | node = Node(arr[mid]) 100 | node.left = self._build_balanced_bst(arr, start, mid - 1) 101 | node.right = self._build_balanced_bst(arr, mid + 1, end) 102 | return node 103 | 104 | def _to_sorted_array(self): 105 | result = [] 106 | self._inorder_fill(self.root, result) 107 | return result 108 | 109 | def _inorder_fill(self, node, arr): 110 | if node is None: 111 | return 112 | self._inorder_fill(node.left, arr) 113 | arr.append(node.elem) 114 | self._inorder_fill(node.right, arr) 115 | 116 | # In-order print 117 | def print_in_order(self): 118 | self._print_in_order(self.root) 119 | print() 120 | 121 | def _print_in_order(self, node): 122 | if node is None: 123 | return 124 | self._print_in_order(node.left) 125 | print(node.elem, end=' ') 126 | self._print_in_order(node.right) 127 | 128 | # Example Usage 129 | if __name__ == "__main__": 130 | bst = BinarySearchTree() 131 | values = [30, 10, 50, 5, 20, 40, 60, 1] 132 | 133 | for v in values: 134 | bst.insert(v) 135 | 136 | print("In-order before deletion:") 137 | bst.print_in_order() 138 | 139 | print("Search 20:", bst.search(20)) 140 | print("Search 100:", bst.search(100)) 141 | 142 | bst.delete_with_successor(30) 143 | print("In-order after deleting 30 using successor:") 144 | bst.print_in_order() 145 | 146 | bst.insert(30) 147 | bst.delete_with_predecessor(50) 148 | print("In-order after deleting 50 using predecessor:") 149 | bst.print_in_order() 150 | 151 | bst.balance() 152 | print("In-order after balancing:") 153 | bst.print_in_order() 154 | -------------------------------------------------------------------------------- /Python/Chapter 6/max_heap.py: -------------------------------------------------------------------------------- 1 | class MaxHeap: 2 | def __init__(self, capacity): 3 | self.capacity = capacity 4 | self.heap = [0] * capacity 5 | self.size = 0 6 | 7 | def insert(self, value): 8 | if self.size == self.capacity: 9 | print("Heap is full") 10 | return 11 | self.heap[self.size] = value 12 | self._swim(self.size) 13 | self.size += 1 14 | 15 | def _swim(self, index): 16 | while index > 0 and self.heap[index] > self.heap[self._parent(index)]: 17 | self._swap(index, self._parent(index)) 18 | index = self._parent(index) 19 | 20 | def _parent(self, index): 21 | return (index - 1) // 2 22 | 23 | def delete_max(self): 24 | if self.size == 0: 25 | raise IndexError("Heap is empty") 26 | max_val = self.heap[0] 27 | self._swap(0, self.size - 1) 28 | self.size -= 1 29 | self._heapify(0) 30 | return max_val 31 | 32 | def _heapify(self, index): 33 | largest = index 34 | left = 2 * index + 1 35 | right = 2 * index + 2 36 | 37 | if left < self.size and self.heap[left] > self.heap[largest]: 38 | largest = left 39 | if right < self.size and self.heap[right] > self.heap[largest]: 40 | largest = right 41 | 42 | if largest != index: 43 | self._swap(index, largest) 44 | self._heapify(largest) 45 | 46 | def _swap(self, i, j): 47 | self.heap[i], self.heap[j] = self.heap[j], self.heap[i] 48 | 49 | def heap_sort(self): 50 | original_size = self.size 51 | for i in range(self.size - 1, 0, -1): 52 | self._swap(0, i) 53 | self.size -= 1 54 | self._heapify(0) 55 | self.size = original_size 56 | 57 | def print_heap(self): 58 | print(self.heap[:self.size]) 59 | 60 | def print_sorted(self): 61 | self.heap_sort() 62 | print(self.heap[:self.size]) 63 | 64 | 65 | # === Test Code === 66 | if __name__ == "__main__": 67 | max_heap = MaxHeap(10) 68 | max_heap.insert(10) 69 | max_heap.insert(20) 70 | max_heap.insert(5) 71 | max_heap.insert(7) 72 | max_heap.insert(30) 73 | max_heap.insert(15) 74 | 75 | print("Heap:") 76 | max_heap.print_heap() 77 | 78 | print("Deleted Max:", max_heap.delete_max()) 79 | 80 | print("Heap After Deletion:") 81 | max_heap.print_heap() 82 | 83 | print("Heap Sort:") 84 | max_heap.print_sorted() 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Structures-and-their-Use-in-Elementary-Algorithms 2 | This repo has all the Java and Python code given in the book as pseudocode. 3 | --------------------------------------------------------------------------------