diff --git a/Algorithms/BellmanFord.java b/Algorithms/BellmanFord.java new file mode 100644 index 0000000..f8029e8 --- /dev/null +++ b/Algorithms/BellmanFord.java @@ -0,0 +1,99 @@ +/** + * Program Title: Bellman-Ford Shortest Path Algorithm + * Author: [chaanakyaaM] + * Date: 2025-10-08 + * + * Description: Computes the shortest path from a single source vertex to all other + * vertices in a weighted, directed graph. It handles graphs with negative edge + * weights but is crucial for detecting and reporting negative cycles. + * + * Time Complexity: O(V * E) (Vertices * Edges) + * Space Complexity: O(V + E) (for the distance array and edge list) + */ + +import java.util.Arrays; + +public class BellmanFord { + + // Structure to represent a weighted edge + static class Edge { + int source, destination, weight; + + Edge(int source, int destination, int weight) { + this.source = source; + this.destination = destination; + this.weight = weight; + } + } + + // Function that implements the Bellman-Ford algorithm + public static void bellmanFord(Edge[] edges, int V, int E, int source) { + // Initialize distances from source to all vertices as INFINITE + int[] distance = new int[V]; + Arrays.fill(distance, Integer.MAX_VALUE); + distance[source] = 0; + + // Relax all edges |V| - 1 times + for (int i = 1; i < V; i++) { + for (int j = 0; j < E; j++) { + int u = edges[j].source; + int v = edges[j].destination; + int weight = edges[j].weight; + + if (distance[u] != Integer.MAX_VALUE && distance[u] + weight < distance[v]) { + distance[v] = distance[u] + weight; + } + } + } + + // Check for negative-weight cycles + for (int i = 0; i < E; i++) { + int u = edges[i].source; + int v = edges[i].destination; + int weight = edges[i].weight; + + if (distance[u] != Integer.MAX_VALUE && distance[u] + weight < distance[v]) { + System.out.println("Graph contains negative weight cycle"); + return; + } + } + + // Print the distances + printSolution(distance); + } + + // Utility function to print the distance array + public static void printSolution(int[] distance) { + System.out.println("Vertex Distance from Source"); + for (int i = 0; i < distance.length; i++) { + if (distance[i] == Integer.MAX_VALUE) { + System.out.println(i + " INF"); + } else { + System.out.println(i + " " + distance[i]); + } + } + } + + public static void main(String[] args) { + // Number of vertices and edges + int V = 5; // Number of vertices + int E = 8; // Number of edges + + // List of edges (source, destination, weight) + Edge[] edges = new Edge[E]; + edges[0] = new Edge(0, 1, -1); + edges[1] = new Edge(0, 2, 4); + edges[2] = new Edge(1, 2, 3); + edges[3] = new Edge(1, 3, 2); + edges[4] = new Edge(1, 4, 2); + edges[5] = new Edge(3, 2, 5); + edges[6] = new Edge(3, 1, 1); + edges[7] = new Edge(4, 3, -3); + + // Source vertex + int source = 0; + + // Run Bellman-Ford algorithm + bellmanFord(edges, V, E, source); + } +} diff --git a/Algorithms/KMPAlgorithm.java b/Algorithms/KMPAlgorithm.java new file mode 100644 index 0000000..88cc795 --- /dev/null +++ b/Algorithms/KMPAlgorithm.java @@ -0,0 +1,95 @@ +// KMP Algorithm in Java +// ------------------------------------------------------ +// Author: Jatin Vishwakarma +// Description: Implementation of the Knuth–Morris–Pratt (KMP) +// Pattern Searching Algorithm in Java. +// This algorithm efficiently finds all occurrences of a pattern +// in a given text with O(n + m) time complexity. + +import java.util.Scanner; + +public class KMPAlgorithm { + + // Function to preprocess the pattern and build the LPS (Longest Prefix Suffix) array + private static void computeLPSArray(String pattern, int[] lps) { + int length = 0; // length of the previous longest prefix suffix + int i = 1; + lps[0] = 0; // LPS of the first character is always 0 + + // Loop to calculate lps[i] for i = 1 to pattern.length - 1 + while (i < pattern.length()) { + if (pattern.charAt(i) == pattern.charAt(length)) { + length++; + lps[i] = length; + i++; + } else { + if (length != 0) { + // This is tricky — consider the example "AAACAAAA" + length = lps[length - 1]; + } else { + lps[i] = 0; + i++; + } + } + } + } + + // KMP Search Function + public static void KMPSearch(String pattern, String text) { + int M = pattern.length(); + int N = text.length(); + + // Create LPS array + int[] lps = new int[M]; + computeLPSArray(pattern, lps); + + int i = 0; // index for text[] + int j = 0; // index for pattern[] + + boolean found = false; + + while (i < N) { + if (pattern.charAt(j) == text.charAt(i)) { + i++; + j++; + } + + if (j == M) { + System.out.println("✅ Pattern found at index: " + (i - j)); + j = lps[j - 1]; + found = true; + } + + // Mismatch after j matches + else if (i < N && pattern.charAt(j) != text.charAt(i)) { + // Do not match lps[0..lps[j-1]] characters, they will match anyway + if (j != 0) + j = lps[j - 1]; + else + i++; + } + } + + if (!found) + System.out.println("❌ Pattern not found in the given text."); + } + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + + System.out.println("====================================="); + System.out.println(" KMP STRING MATCHING ALGORITHM"); + System.out.println("====================================="); + System.out.print("Enter the text: "); + String text = sc.nextLine(); + + System.out.print("Enter the pattern to search: "); + String pattern = sc.nextLine(); + + System.out.println("\n🔍 Searching for pattern..."); + KMPSearch(pattern, text); + + System.out.println("\n--- Program Completed Successfully ---"); + sc.close(); + } +} diff --git a/Algorithms/NQueens.java b/Algorithms/NQueens.java new file mode 100644 index 0000000..28685b5 --- /dev/null +++ b/Algorithms/NQueens.java @@ -0,0 +1,116 @@ +import java.util.Scanner; + +/** + * Program Title: N-Queens Solver + * Author: [Sreenivasulu-03] + * Date: 2025-10-07 + * + * Description: This program solves the N-Queens problem using backtracking. + * It places N queens on an N×N chessboard so that no two queens attack each other. + * The program prints all possible solutions and demonstrates recursion, backtracking, + * and array manipulation in Java. + * + * Time Complexity: O(N!) + * Space Complexity: O(N^2) for the board representation + */ +public class NQueens { + + /** + * Solves the N-Queens problem and prints all solutions. + * @param n The size of the chessboard and the number of queens. + */ + public static void solveNQueens(int n) { + char[][] board = new char[n][n]; + + // Initialize board with empty cells + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + board[i][j] = '.'; + } + } + + backtrack(board, 0); + } + + /** + * Recursively tries to place queens row by row using backtracking. + * @param board The current state of the chessboard. + * @param row The current row to place a queen. + */ + private static void backtrack(char[][] board, int row) { + int n = board.length; + + if (row == n) { + printBoard(board); + return; + } + + for (int col = 0; col < n; col++) { + if (isSafe(board, row, col)) { + board[row][col] = 'Q'; + backtrack(board, row + 1); + board[row][col] = '.'; // Backtrack + } + } + } + + /** + * Checks if placing a queen at (row, col) is safe. + * @param board The current board state. + * @param row Row index. + * @param col Column index. + * @return true if safe, false otherwise. + */ + private static boolean isSafe(char[][] board, int row, int col) { + int n = board.length; + + // Check column + for (int i = 0; i < row; i++) { + if (board[i][col] == 'Q') return false; + } + + // Check upper-left diagonal + for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { + if (board[i][j] == 'Q') return false; + } + + // Check upper-right diagonal + for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) { + if (board[i][j] == 'Q') return false; + } + + return true; + } + + /** + * Prints the current board configuration. + * @param board The chessboard to print. + */ + private static void printBoard(char[][] board) { + System.out.println("Solution:"); + for (char[] row : board) { + for (char c : row) { + System.out.print(c + " "); + } + System.out.println(); + } + System.out.println(); + } + + public static void main(String[] args) { + try (Scanner sc = new Scanner(System.in)) { + System.out.print("Enter the number of queens (N): "); + + while (!sc.hasNextInt()) { + System.out.print("Invalid input! Enter a numeric value: "); + sc.next(); + } + int n = sc.nextInt(); + + solveNQueens(n); + + } catch (Exception e) { + System.err.println("An unexpected error occurred: " + e.getMessage()); + } + } +} diff --git a/Algorithms/PrimsAlgorithm.java b/Algorithms/PrimsAlgorithm.java new file mode 100644 index 0000000..030784d --- /dev/null +++ b/Algorithms/PrimsAlgorithm.java @@ -0,0 +1,75 @@ +/** + * Program Title: Prim's Algorithm for Minimum Spanning Tree (MST) + * Author: [@chaanakyaaM] + * Date: [2025-10-07] + * + * Description: Finds the Minimum Spanning Tree (MST) of a connected, undirected + * weighted graph using a Priority Queue (Min-Heap) to efficiently select the + * next cheapest edge. + * Time Complexity: O(E log V) (where E is edges, V is vertices) + * Space Complexity: O(V + E) + */ + +import java.util.*; + +class Edge { + int to; + int weight; + + Edge(int to, int weight) { + this.to = to; + this.weight = weight; + } +} + +public class PrimsAlgorithm { + public static int prim(int n, List> adj) { + boolean[] visited = new boolean[n]; + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(e -> e.weight)); + pq.offer(new Edge(0, 0)); // Start from node 0 + int mstWeight = 0; + + while (!pq.isEmpty()) { + Edge current = pq.poll(); + + if (visited[current.to]) continue; + + visited[current.to] = true; + mstWeight += current.weight; + + for (Edge neighbor : adj.get(current.to)) { + if (!visited[neighbor.to]) { + pq.offer(neighbor); + } + } + } + + return mstWeight; + } + + public static void main(String[] args) { + int n = 5; // number of nodes + List> adj = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + adj.add(new ArrayList<>()); + } + + // Adding undirected edges + addEdge(adj, 0, 1, 2); + addEdge(adj, 0, 3, 6); + addEdge(adj, 1, 2, 3); + addEdge(adj, 1, 3, 8); + addEdge(adj, 1, 4, 5); + addEdge(adj, 2, 4, 7); + addEdge(adj, 3, 4, 9); + + int result = prim(n, adj); + System.out.println("Total weight of MST: " + result); + } + + static void addEdge(List> adj, int u, int v, int w) { + adj.get(u).add(new Edge(v, w)); + adj.get(v).add(new Edge(u, w)); // Since the graph is undirected + } +} diff --git a/Algorithms/QuickSort.java b/Algorithms/QuickSort.java new file mode 100644 index 0000000..aa76b80 --- /dev/null +++ b/Algorithms/QuickSort.java @@ -0,0 +1,69 @@ + +public class QuickSort { + + /** + * Sorts an array using Quick Sort algorithm. + * + * @param arr The array to be sorted + * @param low Starting index + * @param high Ending index + */ + public static void quickSort(int[] arr, int low, int high) { + if (low < high) { + int pivotIndex = partition(arr, low, high); + quickSort(arr, low, pivotIndex - 1); + quickSort(arr, pivotIndex + 1, high); + } + } + + /** + * Partitions the array around a pivot element. + * + * @param arr The array to partition + * @param low Starting index + * @param high Ending index + * @return The index of the pivot after partition + */ + private static int partition(int[] arr, int low, int high) { + int pivot = arr[high]; // Choosing the last element as pivot + int i = low - 1; // Index of smaller element + + for (int j = low; j < high; j++) { + if (arr[j] <= pivot) { + i++; + // Swap arr[i] and arr[j] + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + } + + // Swap arr[i+1] and pivot (arr[high]) + int temp = arr[i + 1]; + arr[i + 1] = arr[high]; + arr[high] = temp; + + return i + 1; + } + + public static void main(String[] args) { + int[] sampleArray = { 10, 7, 8, 9, 1, 5 }; + + if (sampleArray == null || sampleArray.length == 0) { + System.out.println("Array is empty or null."); + return; + } + + System.out.println("Original Array:"); + for (int num : sampleArray) { + System.out.print(num + " "); + } + + quickSort(sampleArray, 0, sampleArray.length - 1); + + System.out.println("\n\nSorted Array:"); + for (int num : sampleArray) { + System.out.print(num + " "); + } + } +} diff --git a/Algorithms/SudokuSolver.java b/Algorithms/SudokuSolver.java new file mode 100644 index 0000000..f7bbe0d --- /dev/null +++ b/Algorithms/SudokuSolver.java @@ -0,0 +1,98 @@ +// Metadata Header (MANDATORY) +// ----------------------------- +// Program Title: Sudoku Solver (Backtracking) +// Author: [Madipadige-ManishKumar] +// Date: 2025-10-09 +// +// Description: Solves a standard 9x9 Sudoku puzzle using the Backtracking algorithm. +// +// Language: Java +// +// Time Complexity (Practical): O(1) +// Time Complexity (Worst-Case): O(9^N), where N is the number of empty cells. +// Space Complexity: O(1). +// ----------------------------- + +public class SudokuSolver { + + private static final int SIZE = 9; // Standard Sudoku size + + // Function to print the Sudoku board + public static void printBoard(int[][] board) { + for (int row = 0; row < SIZE; row++) { + for (int col = 0; col < SIZE; col++) { + System.out.print(board[row][col] + " "); + } + System.out.println(); + } + } + + // Check if placing num at board[row][col] is valid + public static boolean isSafe(int[][] board, int row, int col, int num) { + // Check row and column + for (int i = 0; i < SIZE; i++) { + if (board[row][i] == num || board[i][col] == num) + return false; + } + + // Check 3x3 subgrid + int startRow = row - row % 3; + int startCol = col - col % 3; + + for (int i = startRow; i < startRow + 3; i++) { + for (int j = startCol; j < startCol + 3; j++) { + if (board[i][j] == num) + return false; + } + } + + return true; + } + + // Recursive function to solve Sudoku + public static boolean solveSudoku(int[][] board) { + for (int row = 0; row < SIZE; row++) { + for (int col = 0; col < SIZE; col++) { + // Find an empty cell + if (board[row][col] == 0) { + // Try digits 1-9 + for (int num = 1; num <= 9; num++) { + if (isSafe(board, row, col, num)) { + board[row][col] = num; + + // Recursively solve the rest + if (solveSudoku(board)) + return true; + + // Backtrack + board[row][col] = 0; + } + } + return false; // No valid number found + } + } + } + return true; // Solved + } + + public static void main(String[] args) { + int[][] board = { + {5, 3, 0, 0, 7, 0, 0, 0, 0}, + {6, 0, 0, 1, 9, 5, 0, 0, 0}, + {0, 9, 8, 0, 0, 0, 0, 6, 0}, + {8, 0, 0, 0, 6, 0, 0, 0, 3}, + {4, 0, 0, 8, 0, 3, 0, 0, 1}, + {7, 0, 0, 0, 2, 0, 0, 0, 6}, + {0, 6, 0, 0, 0, 0, 2, 8, 0}, + {0, 0, 0, 4, 1, 9, 0, 0, 5}, + {0, 0, 0, 0, 8, 0, 0, 7, 9} + }; + + if (solveSudoku(board)) { + System.out.println("Sudoku solved successfully:"); + printBoard(board); + } else { + System.out.println("No solution exists for the given Sudoku."); + } + } +} diff --git a/Algorithms/TarjanSCC.java b/Algorithms/TarjanSCC.java new file mode 100644 index 0000000..2b73935 --- /dev/null +++ b/Algorithms/TarjanSCC.java @@ -0,0 +1,85 @@ +// Tarjan’s Algorithm in Java +// ------------------------------------------------------ +// Author: Jatin Vishwakarma +// Description: Implementation of Tarjan’s Algorithm for finding +// Strongly Connected Components (SCCs) in a directed graph. +// This algorithm uses DFS and low-link values to efficiently +// detect all SCCs in O(V + E) time complexity. + +import java.util.*; + +public class TarjanSCC { + private final int V; + private final List> adj; + private int time; + private final int[] disc; + private final int[] low; + private final boolean[] stackMember; + private final Stack stack; + + public TarjanSCC(int vertices) { + V = vertices; + adj = new ArrayList<>(); + for (int i = 0; i < vertices; i++) adj.add(new ArrayList<>()); + disc = new int[vertices]; + low = new int[vertices]; + stackMember = new boolean[vertices]; + stack = new Stack<>(); + Arrays.fill(disc, -1); + Arrays.fill(low, -1); + } + + // Add a directed edge from u to v + public void addEdge(int u, int v) { + adj.get(u).add(v); + } + + private void SCCUtil(int u) { + disc[u] = low[u] = ++time; + stack.push(u); + stackMember[u] = true; + + for (int v : adj.get(u)) { + if (disc[v] == -1) { // If v is not visited + SCCUtil(v); + low[u] = Math.min(low[u], low[v]); + } else if (stackMember[v]) { // Back edge + low[u] = Math.min(low[u], disc[v]); + } + } + + // If u is the root of an SCC + if (low[u] == disc[u]) { + System.out.print("SCC: "); + while (true) { + int v = stack.pop(); + stackMember[v] = false; + System.out.print(v + " "); + if (v == u) break; + } + System.out.println(); + } + } + + public void findSCCs() { + for (int i = 0; i < V; i++) { + if (disc[i] == -1) + SCCUtil(i); + } + } + + public static void main(String[] args) { + TarjanSCC g = new TarjanSCC(7); + g.addEdge(0, 1); + g.addEdge(1, 2); + g.addEdge(2, 0); + g.addEdge(1, 3); + g.addEdge(3, 4); + g.addEdge(4, 5); + g.addEdge(5, 3); + g.addEdge(5, 6); + + System.out.println("Strongly Connected Components in the given graph:"); + g.findSCCs(); + } +} diff --git a/Algorithms/UnionFind.java b/Algorithms/UnionFind.java new file mode 100644 index 0000000..2316eeb --- /dev/null +++ b/Algorithms/UnionFind.java @@ -0,0 +1,67 @@ +// Metadata Header (MANDATORY) +// ----------------------------- +// Program Title: Union-Find (Disjoint Set Union) +// Author: [KotlinKing] +// Date: 2025-10-10 +// +// Description: Implements the Disjoint Set Union data structure, or Union-Find. +// It includes the two essential optimizations: Path Compression and Union by Rank. +// +// Language: Java +// +// Time Complexity: O(α(n)) for find/union. +// Space Complexity: O(n). +// ----------------------------- + +public class UnionFind { + private int[] parent; + private int[] rank; + + // Initialize n disjoint sets + public UnionFind(int n) { + parent = new int[n]; + rank = new int[n]; + for(int i = 0; i < n; i++) { + parent[i] = i; + rank[i] = 0; + } + } + + // Find root of x with path compression + public int find(int x) { + if(parent[x] != x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + // Union two sets by rank + public boolean union(int x, int y) { + int rootX = find(x); + int rootY = find(y); + + if(rootX == rootY) return false; // already in same set + + if(rank[rootX] < rank[rootY]) { + parent[rootX] = rootY; + } else if(rank[rootX] > rank[rootY]) { + parent[rootY] = rootX; + } else { + parent[rootY] = rootX; + rank[rootX]++; + } + return true; + } + + // Example usage + public static void main(String[] args) { + UnionFind uf = new UnionFind(5); + + uf.union(0, 1); + uf.union(1, 2); + uf.union(3, 4); + + System.out.println("Are 0 and 2 connected? " + (uf.find(0) == uf.find(2))); // true + System.out.println("Are 0 and 3 connected? " + (uf.find(0) == uf.find(3))); // false + } +} diff --git a/Beginner/GradeCalculator.java b/Beginner/GradeCalculator.java new file mode 100644 index 0000000..473074c --- /dev/null +++ b/Beginner/GradeCalculator.java @@ -0,0 +1,46 @@ +/** + * ------------------------------------------------------------ + * Program Name : GradeCalculator + * Author : Anukalp Pandey + * Description : A simple console application that takes a student's numerical score + * and prints the corresponding letter grade (A, B, C, D, F) + * using if-else if statements. + * Complexity : O(1) - Constant time complexity, since it performs a fixed + * number of comparisons regardless of input size. + * ------------------------------------------------------------ + */ + +import java.util.Scanner; + +public class GradeCalculator { + + public static void main(String[] args) { + + // Using try-with-resources to ensure Scanner is closed automatically + try (Scanner sc = new Scanner(System.in)) { + System.out.print("Enter student's score (0 - 100): "); + int score = sc.nextInt(); + + char grade; + + if (score >= 90 && score <= 100) { + grade = 'A'; + } else if (score >= 80) { + grade = 'B'; + } else if (score >= 70) { + grade = 'C'; + } else if (score >= 60) { + grade = 'D'; + } else if (score >= 0) { + grade = 'F'; + } else { + System.out.println("Invalid score entered! Please enter between 0 and 100."); + return; + } + + System.out.println("Grade: " + grade); + } catch (Exception e) { + System.out.println("Error: Please enter a valid numerical score."); + } + } +} diff --git a/Beginner/RockPaperScissors.java b/Beginner/RockPaperScissors.java new file mode 100644 index 0000000..9008679 --- /dev/null +++ b/Beginner/RockPaperScissors.java @@ -0,0 +1,45 @@ +/** + * Program Title: Rock-Paper-Scissors Game + * Author: [VinayKumarBM] + * Date: 2025-10-10 + * + * Description: Implements the classic Rock-Paper-Scissors game against a computer opponent. + * + * Language: Java + * + * Time Complexity: O(1). + * Space Complexity: O(1). + */ + +import java.util.*; + +public class RockPaperScissors { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + String[] options = {"rock", "paper", "scissors"}; + Random random = new Random(); + + while (true) { + System.out.print("Enter rock, paper, or scissors (or 'quit'): "); + String user = sc.nextLine().toLowerCase(); + + if (user.equals("quit")) break; + if (!Arrays.asList(options).contains(user)) { + System.out.println("Invalid choice! Try again."); + continue; + } + + String computer = options[random.nextInt(3)]; + System.out.println("Computer chose: " + computer); + + if (user.equals(computer)) + System.out.println("It's a tie!"); + else if ((user.equals("rock") && computer.equals("scissors")) || + (user.equals("scissors") && computer.equals("paper")) || + (user.equals("paper") && computer.equals("rock"))) + System.out.println("You win! 🎉"); + else + System.out.println("You lose! 💻 wins!"); + } + } +} diff --git a/DataStructures/AVLTree.java b/DataStructures/AVLTree.java new file mode 100644 index 0000000..8ce9313 --- /dev/null +++ b/DataStructures/AVLTree.java @@ -0,0 +1,234 @@ +// Metadata Header (MANDATORY) +// ----------------------------- +// Program Title: AVL Tree Implementation +// Author: [Madipadige-ManishKumar] +// Date: 2025-10-10 +// +// Description: Implements the AVL Self-Balancing Binary Search Tree. +// +// Language: Java +// +// Time Complexity: O(log n). +// Space Complexity: O(n). +// ----------------------------- + +class AVLTree { + + // Node class - Declared as private for better encapsulation + private class Node { + int key, height; + Node left, right; + + Node(int data) { + key = data; + height = 1; + } + } + + private Node root; // Should be private + + // ... (rest of the excellent code follows) + +class AVLTree { + + // Node class + class Node { + int key, height; + Node left, right; + + Node(int data) { + key = data; + height = 1; + } + } + + private Node root; + + // Utility: get height of a node + int height(Node n) { + if (n == null) return 0; + return n.height; + } + + // Utility: get balance factor of a node + int getBalance(Node n) { + if (n == null) return 0; + return height(n.left) - height(n.right); + } + + // Right rotation (LL rotation) + Node rotateRight(Node y) { + Node x = y.left; + Node T2 = x.right; + + // Perform rotation + x.right = y; + y.left = T2; + + // Update heights + y.height = Math.max(height(y.left), height(y.right)) + 1; + x.height = Math.max(height(x.left), height(x.right)) + 1; + + // Return new root + return x; + } + + // Left rotation (RR rotation) + Node rotateLeft(Node x) { + Node y = x.right; + Node T2 = y.left; + + // Perform rotation + y.left = x; + x.right = T2; + + // Update heights + x.height = Math.max(height(x.left), height(x.right)) + 1; + y.height = Math.max(height(y.left), height(y.right)) + 1; + + // Return new root + return y; + } + + // Insert a key + Node insert(Node node, int key) { + // 1️⃣ Perform normal BST insertion + if (node == null) return new Node(key); + + if (key < node.key) + node.left = insert(node.left, key); + else if (key > node.key) + node.right = insert(node.right, key); + else + return node; // Duplicate keys not allowed + + // 2️⃣ Update height + node.height = 1 + Math.max(height(node.left), height(node.right)); + + // 3️⃣ Get balance factor + int balance = getBalance(node); + + // 4️⃣ Balance the tree using rotations + // LL + if (balance > 1 && key < node.left.key) + return rotateRight(node); + + // RR + if (balance < -1 && key > node.right.key) + return rotateLeft(node); + + // LR + if (balance > 1 && key > node.left.key) { + node.left = rotateLeft(node.left); + return rotateRight(node); + } + + // RL + if (balance < -1 && key < node.right.key) { + node.right = rotateRight(node.right); + return rotateLeft(node); + } + + return node; + } + + // Find node with minimum key + Node minValueNode(Node node) { + Node current = node; + while (current.left != null) + current = current.left; + return current; + } + + // Delete a key + Node delete(Node root, int key) { + if (root == null) + return root; + + // Perform standard BST delete + if (key < root.key) + root.left = delete(root.left, key); + else if (key > root.key) + root.right = delete(root.right, key); + else { + // Node with one or no child + if ((root.left == null) || (root.right == null)) { + Node temp = (root.left != null) ? root.left : root.right; + root = (temp == null) ? null : temp; + } else { + // Node with two children + Node temp = minValueNode(root.right); + root.key = temp.key; + root.right = delete(root.right, temp.key); + } + } + + // If the tree had only one node + if (root == null) + return root; + + // Update height + root.height = Math.max(height(root.left), height(root.right)) + 1; + + // Check balance + int balance = getBalance(root); + + // Perform rotations + if (balance > 1 && getBalance(root.left) >= 0) + return rotateRight(root); + + if (balance > 1 && getBalance(root.left) < 0) { + root.left = rotateLeft(root.left); + return rotateRight(root); + } + + if (balance < -1 && getBalance(root.right) <= 0) + return rotateLeft(root); + + if (balance < -1 && getBalance(root.right) > 0) { + root.right = rotateRight(root.right); + return rotateLeft(root); + } + + return root; + } + + // Public methods for user + public void insert(int key) { + root = insert(root, key); + } + + public void delete(int key) { + root = delete(root, key); + } + + // Inorder Traversal + public void inorder() { + inorderTraversal(root); + System.out.println(); + } + + private void inorderTraversal(Node node) { + if (node != null) { + inorderTraversal(node.left); + System.out.print(node.key + " "); + inorderTraversal(node.right); + } + } + + // Driver Example + public static void main(String[] args) { + AVLTree tree = new AVLTree(); + + int[] keys = {10, 20, 30, 40, 50, 25}; + for (int key : keys) + tree.insert(key); + + System.out.println("Inorder traversal after insertions:"); + tree.inorder(); + + tree.delete(40); + System.out.println("After deleting 40:"); + tree.inorder(); + } +} diff --git a/DataStructures/LinkedList.java b/DataStructures/LinkedList.java new file mode 100644 index 0000000..6fb3276 --- /dev/null +++ b/DataStructures/LinkedList.java @@ -0,0 +1,117 @@ +/** + * Linked List Implementation in Java + * + * A Linked List is a linear data structure where elements (nodes) + * are connected using references (pointers). Each node contains: + * - data (value) + * - next (reference to next node) + * + * Advantages: + * - Dynamic size (no need to define capacity) + * - Easy insertion/deletion at any position + * + * Disadvantages: + * - Random access not possible (must traverse sequentially) + * - Uses extra memory (pointer/reference for each node) + * + * Example: + * Insert 10 → Insert 20 → Insert 30 + * Linked List: 10 -> 20 -> 30 + * Delete 20 + * Linked List: 10 -> 30 + */ + +class LinkedList { + + // Node class: represents a single element in Linked List + static class Node { + int data; + Node next; + + Node(int data) { + this.data = data; // store value + this.next = null; // initially no link + } + } + + Node head; // head (first node of the list) + + // Insert new node at the end + public void insert(int data) { + Node newNode = new Node(data); + + if (head == null) { + head = newNode; // if list is empty + } else { + Node temp = head; + while (temp.next != null) { // traverse till last node + temp = temp.next; + } + temp.next = newNode; // link new node at end + } + } + + // Delete a node by value + public void delete(int key) { + Node temp = head, prev = null; + + // If head itself holds the key + if (temp != null && temp.data == key) { + head = temp.next; // move head + return; + } + + // Search for the key + while (temp != null && temp.data != key) { + prev = temp; + temp = temp.next; + } + + // If key not found + if (temp == null) return; + + // Unlink the node + prev.next = temp.next; + } + + // Search an element + public boolean search(int key) { + Node temp = head; + while (temp != null) { + if (temp.data == key) return true; + temp = temp.next; + } + return false; + } + + // Display the linked list + public void display() { + Node temp = head; + while (temp != null) { + System.out.print(temp.data + " -> "); + temp = temp.next; + } + System.out.println("null"); + } + + // Main method to test LinkedList + public static void main(String[] args) { + LinkedList list = new LinkedList(); + + // Insert elements + list.insert(10); + list.insert(20); + list.insert(30); + System.out.println("After Insertion:"); + list.display(); // 10 -> 20 -> 30 -> null + + // Delete element + list.delete(20); + System.out.println("After Deletion of 20:"); + list.display(); // 10 -> 30 -> null + + // Search element + System.out.println("Search 30: " + list.search(30)); // true + System.out.println("Search 50: " + list.search(50)); // false + } +} diff --git a/DataStructures/Queue.java b/DataStructures/Queue.java new file mode 100644 index 0000000..8a2b1ae --- /dev/null +++ b/DataStructures/Queue.java @@ -0,0 +1,76 @@ +/** + * Program Title: Queue (Linked List Implementation) + * Author: [Ahad-23] + * Date: 2025-10-08 + * + * Description: Implements a generic Queue data structure using a custom + * Singly Linked List. Operations (enqueue, dequeue, peek) are designed + * to adhere to the FIFO (First-In, First-Out) principle. + * + * Time Complexity: O(1) for all main operations (enqueue, dequeue, peek). + * Space Complexity: O(N) where N is the number of elements stored. + */ + +public class Queue { + // Node class for custom singly linked list + private static class Node { + T data; + Node next; + + Node(T data) { + this.data = data; + this.next = null; + } + } + + private Node front; + private Node rear; + private int size; + + public Queue() { + this.front = null; + this.rear = null; + this.size = 0; + } + + public void enqueue(T data) { + Node newNode = new Node<>(data); + if (rear == null) front = rear = newNode; + + else + { + rear.next = newNode; + rear = newNode; + } + size++; + } + + public T dequeue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty. Cannot dequeue."); + } + T value = front.data; + front = front.next; + if (front == null) rear = null; + + size--; + return value; + } + + + public T peek() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty. Cannot dequeue."); + } + return front.data; + } + + public boolean isEmpty() { + return front == null; + } + + // Get current size of the queue + public int size() { + return size; + } +} diff --git a/OOP/ShapeMain.java b/OOP/ShapeMain.java new file mode 100644 index 0000000..30e0712 --- /dev/null +++ b/OOP/ShapeMain.java @@ -0,0 +1,107 @@ +import java.util.*; + +/** + * Program Title: OOP Inheritance & Polymorphism + * Author: @ashwil-colaco + * Date: 2025-10-07 + * + * Description: Demonstrates core OOP concepts (inheritance, polymorphism, abstract classes) + * by creating a Shape abstract class with Circle and Rectangle subclasses. + * The program calculates and prints the area of shapes using polymorphism. + * Time Complexity: O(1) for each area calculation. + * Space Complexity: O(n) for storing Shape objects in an array. + */ + +/** + * Abstract class representing a generic shape. + */ +abstract class Shape { + /** + * Calculates and returns the area of the shape. + * + * @return area of the shape + */ + public abstract double getArea(); +} + +/** + * Class representing a circle shape. + */ +class Circle extends Shape { + private double radius; + + /** + * Constructor to initialize the radius of the circle. + * + * @param radius radius of the circle + */ + public Circle(double radius) { + this.radius = radius; + } + + /** + * Calculates and returns the area of the circle. + * + * @return area of the circle + */ + @Override + public double getArea() { + return Math.PI * radius * radius; + } +} + +/** + * Class representing a rectangle shape. + */ +class Rectangle extends Shape { + private double length; + private double width; + + /** + * Constructor to initialize the length and width of the rectangle. + * + * @param length length of the rectangle + * @param width width of the rectangle + */ + public Rectangle(double length, double width) { + this.length = length; + this.width = width; + } + + /** + * Calculates and returns the area of the rectangle. + * + * @return area of the rectangle + */ + @Override + public double getArea() { + return length * width; + } +} + +/** + * Main class to demonstrate polymorphism with Shape, Circle, and Rectangle. + */ +public class ShapeMain { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + + Shape[] shapes = new Shape[2]; + + System.out.print("Enter the radius of the Circle: "); + double radius = sc.nextDouble(); + + System.out.print("Enter the length and breadth of the Rectangle: "); + double length = sc.nextDouble(); + double breadth = sc.nextDouble(); + + shapes[0] = new Circle(radius); + shapes[1] = new Rectangle(length, breadth); + + for (Shape shape : shapes) { + System.out.println("Area: " + shape.getArea()); + } + + sc.close(); + } +}