diff --git a/CPP/algorithms/sorting/Shell_Sort.cpp b/CPP/algorithms/sorting/Shell_Sort.cpp index f092fb77..33f8965a 100644 --- a/CPP/algorithms/sorting/Shell_Sort.cpp +++ b/CPP/algorithms/sorting/Shell_Sort.cpp @@ -27,4 +27,4 @@ int main() { for (int x : a) cout << x << ' '; cout << '\n'; return 0; -} +} \ No newline at end of file diff --git a/Java/algorithms/sorting/RadixSortREVANT.java b/Java/algorithms/sorting/RadixSortREVANT.java deleted file mode 100644 index 5b372ab2..00000000 --- a/Java/algorithms/sorting/RadixSortREVANT.java +++ /dev/null @@ -1,106 +0,0 @@ - -/* - * Algorithm Name: - * Radix Sort - * - * Programming Language: - * Java - * - * Category: - * Sorting - * - * Difficulty Level: - * Medium - * - * Algorithm Description: - * - * 1. Problem it solves: - * -> Radix Sort is a non-comparative sorting algorithm that sorts integers by processing digits - * from least significant digit (LSD) to most significant digit (MSD). - * - * 2. Approach / Idea: - * -> Find the maximum number to know the number of digits. - * -> Do counting sort for every digit, starting from least significant to most significant. - * -> Counting sort is used as a subroutine to sort elements based on the current digit. - * - * 3. Complexity: - * Time: O(d * (n + k)), where n = number of elements, k = range of digits (0-9), d = number of digits - * Space: O(n + k) - * - * Author: - * Revant Singh - */ -package DSA_Code.Java.algorithms.sorting; -import java.util.Arrays; -import java.util.Scanner; - -public class RadixSort { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - - System.out.print("Enter number of elements: "); - int n = sc.nextInt(); - - int[] arr = new int[n]; - System.out.println("Enter elements: "); - for (int i = 0; i < n; i++) { - arr[i] = sc.nextInt(); - } - - System.out.println("Original Array: " + Arrays.toString(arr)); - - radixSort(arr); - - System.out.println("Sorted Array: " + Arrays.toString(arr)); - } - - // Radix Sort function - static void radixSort(int[] arr) { - int max = getMax(arr); - - // Apply counting sort for each digit - for (int exp = 1; max / exp > 0; exp *= 10) { - countingSortByDigit(arr, exp); - } - } - - // Get maximum value in the array - static int getMax(int[] arr) { - int max = arr[0]; - for (int num : arr) { - if (num > max) max = num; - } - return max; - } - - // Counting sort based on digit represented by exp - static void countingSortByDigit(int[] arr, int exp) { - int n = arr.length; - int[] output = new int[n]; // output array - int[] count = new int[10]; // count array for digits 0-9 - - // Count occurrences of each digit - for (int i = 0; i < n; i++) { - int digit = (arr[i] / exp) % 10; - count[digit]++; - } - - // Transform count[i] so that it contains actual position - for (int i = 1; i < 10; i++) { - count[i] += count[i - 1]; - } - - // Build the output array - for (int i = n - 1; i >= 0; i--) { - int digit = (arr[i] / exp) % 10; - output[count[digit] - 1] = arr[i]; - count[digit]--; - } - - // Copy output to original array - for (int i = 0; i < n; i++) { - arr[i] = output[i]; - } - } -} diff --git a/Java/algorithms/sorting/RadixSortRevant.java b/Java/algorithms/sorting/RadixSortRevant.java index ce5d463e..ea3801bc 100644 --- a/Java/algorithms/sorting/RadixSortRevant.java +++ b/Java/algorithms/sorting/RadixSortRevant.java @@ -1,3 +1,4 @@ + /* * Algorithm Name: * Radix Sort @@ -29,11 +30,11 @@ * Author: * Revant Singh */ -package DSA_Code.Java.algorithms.sorting; +// package DSA_Code.Java.algorithms.sorting; import java.util.Arrays; import java.util.Scanner; -public class RadixSortRevant{ +public class RadixSortRevant { public static void main(String[] args) { Scanner sc = new Scanner(System.in); @@ -103,4 +104,3 @@ static void countingSortByDigit(int[] arr, int exp) { } } } - diff --git a/Shell_Sort b/Shell_Sort index 5f34e6bb..7107ed94 100755 Binary files a/Shell_Sort and b/Shell_Sort differ diff --git a/go/graph/BFSTraversal.go b/go/graph/BFSTraversal.go new file mode 100644 index 00000000..1ce2709c --- /dev/null +++ b/go/graph/BFSTraversal.go @@ -0,0 +1,232 @@ +// BFSTraversal.go +// +// Breadth-First Search (BFS) Traversal - Numeric Node IDs +// +// Description: +// BFS is a graph traversal algorithm that visits vertices in increasing +// order of their distance (number of edges) from a chosen start vertex. +// It uses a queue (FIFO) to explore the graph layer-by-layer. BFS is the +// canonical way to compute shortest path distances (in edges) in an +// unweighted graph and to enumerate nodes by level. +// +// Purpose / Use cases: +// - Compute the order in which nodes are visited (level-order traversal). +// - Find shortest paths in unweighted graphs (by edge count). +// - Discover connected components or check reachability. +// - Useful in many graph problems: bipartiteness test, shortest path in +// unweighted graphs, minimum number of moves in puzzles, etc. +// +// Approach / Methodology: +// - Represent an undirected graph with an adjacency list map[int][]int. +// - Maintain a visited set and a queue of nodes to process. +// - Start from the source node: mark visited, enqueue it, then repeatedly +// dequeue a node, visit it, and enqueue all its unvisited neighbors. +// - The order nodes are dequeued is the BFS visit order (layer-by-layer). +// +// Complexity Analysis: +// - Time complexity: O(V + E) +// where V = number of vertices and E = number of edges. Each vertex is +// enqueued/dequeued at most once and each edge is examined once. +// - Space complexity: O(V) +// for the visited set and the queue (in worst case the queue can hold O(V)). +// +// File contents: +// - Graph type and methods (AddEdge, AddNode). +// - BFS function that returns visit order (slice of ints) or nil if start missing. +// - Simple test harness with deterministic small numeric graphs and pass/fail checks. +// - Tests now print the BFS visit order for each case. +// +// Author: (your name) +// Date: (optional) + +package main + +import ( + "fmt" + "os" + "strconv" +) + +// Graph represents an undirected graph with integer node IDs. +type Graph struct { + adj map[int][]int // adjacency list: node -> list of neighbors +} + +// NewGraph creates and returns an empty Graph. +func NewGraph() *Graph { + return &Graph{adj: make(map[int][]int)} +} + +// AddNode ensures a node entry exists in the adjacency map. +// It's safe to call this before adding edges if you want isolated nodes. +func (g *Graph) AddNode(id int) { + if _, ok := g.adj[id]; !ok { + g.adj[id] = []int{} + } +} + +// AddEdge adds an undirected edge between a and b. +// If nodes don't exist yet they are created automatically. +// The order of AddEdge calls determines neighbor order and therefore +// BFS deterministic visit order for the same insertion order. +func (g *Graph) AddEdge(a, b int) { + g.adj[a] = append(g.adj[a], b) + g.adj[b] = append(g.adj[b], a) +} + +// BFS runs breadth-first search starting from `start`. +// Returns a slice with the visit order (nodes in the order they were dequeued). +// If the start node is not present in the graph, BFS returns nil. +// +// Time complexity: O(V + E) +// Space complexity: O(V) +func (g *Graph) BFS(start int) []int { + // If the start node is not present, return nil to indicate an invalid start. + if _, ok := g.adj[start]; !ok { + return nil + } + + visited := make(map[int]bool, len(g.adj)) // tracks visited nodes + queue := make([]int, 0, len(g.adj)) // queue implemented as a slice + head := 0 // index of current head in queue + + // Initialize BFS + visited[start] = true + queue = append(queue, start) + + visitOrder := make([]int, 0, len(g.adj)) + + // Process queue until empty + for head < len(queue) { + cur := queue[head] + head++ + visitOrder = append(visitOrder, cur) + + // Visit neighbors in the order they were added. + for _, nb := range g.adj[cur] { + if !visited[nb] { + visited[nb] = true + queue = append(queue, nb) + } + } + } + + return visitOrder +} + +// compareSlices checks equality of two integer slices. +func compareSlices(a, b []int) bool { + if a == nil && b == nil { + return true + } + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// expect checks the BFS output against expected result and prints pass/fail. +func expect(got, expected []int, testName string) { + // Always print the BFS order to make results explicit. + fmt.Printf("%s - BFS order: %v\n", testName, got) + if compareSlices(got, expected) { + fmt.Printf("[PASS] %s\n\n", testName) + } else { + fmt.Printf("[FAIL] %s\n", testName) + fmt.Printf(" Got : %v\n", got) + fmt.Printf(" Expected: %v\n\n", expected) + } +} + +// runTests builds small numeric graphs and runs compact, deterministic tests. +// These tests are focused only on BFS visit order (the requirement you stated). +func runTests() { + fmt.Println("BFS Traversal Tests (numeric nodes)\n") + + // Graph G: + // 1 - 2 - 4 + // | + // 3 - 5 - 6 + // + // (Edges are added in order to make BFS deterministic for the tests) + g := NewGraph() + g.AddEdge(1, 2) // neighbors: 1:[2], 2:[1] + g.AddEdge(1, 3) // 1:[2,3], 3:[1] + g.AddEdge(2, 4) // 2:[1,4], 4:[2] + g.AddEdge(3, 5) // 3:[1,5], 5:[3] + g.AddEdge(5, 6) // 5:[3,6], 6:[5] + // Add isolated node 7 (no edges) + g.AddNode(7) + + // Test 1: start = 1 (connected component) + // Expected BFS order: + // 1,2,3,4,5,6 + expected1 := []int{1, 2, 3, 4, 5, 6} + got1 := g.BFS(1) + expect(got1, expected1, "Test 1: start=1 (connected)") + + // Test 2: start = 3 (middle node) + // Expected order: 3,1,5,2,6,4 + expected2 := []int{3, 1, 5, 2, 6, 4} + got2 := g.BFS(3) + expect(got2, expected2, "Test 2: start=3 (middle node)") + + // Test 3: isolated node start = 7 + // Node 7 exists but is isolated => visit order [7] + expected3 := []int{7} + got3 := g.BFS(7) + expect(got3, expected3, "Test 3: start=7 (isolated node)") + + // Test 4: start missing => nil returned + got4 := g.BFS(99) + expect(got4, nil, "Test 4: start missing (99) => nil") + + // Test 5: empty graph => start not present => nil + empty := NewGraph() + got5 := empty.BFS(1) + expect(got5, nil, "Test 5: empty graph => start not found") + + fmt.Println("Tests completed.") +} + +// main: runs tests by default. If first CLI argument is present and is an integer, +// builds the sample graph and runs BFS starting from that node, printing only the visit order. +func main() { + // If CLI arg provided, run BFS interactively on the sample graph and print the visit order. + if len(os.Args) > 1 { + startStr := os.Args[1] + start, err := strconv.Atoi(startStr) + if err != nil { + fmt.Printf("Invalid start node: %q. Provide integer node id.\n", startStr) + return + } + // Build the same small sample graph used in tests: + g := NewGraph() + g.AddEdge(1, 2) + g.AddEdge(1, 3) + g.AddEdge(2, 4) + g.AddEdge(3, 5) + g.AddEdge(5, 6) + g.AddNode(7) + + order := g.BFS(start) + if order == nil { + fmt.Printf("Start node %d not found in graph\n", start) + return + } + // Print the BFS visit order explicitly for interactive runs. + fmt.Printf("BFS visit order from %d: %v\n", start, order) + return + } + + // No CLI arg: run the compact test suite. + runTests() +} diff --git a/go/graph/DFSTraversal.go b/go/graph/DFSTraversal.go new file mode 100644 index 00000000..d5dcad06 --- /dev/null +++ b/go/graph/DFSTraversal.go @@ -0,0 +1,211 @@ +// DFSTraversal.go +// +// Depth-First Search (DFS) Traversal - Numeric Node IDs +// +// Description: +// DFS is a graph traversal algorithm that explores as far as possible +// along each branch before backtracking. This implementation uses recursion +// and returns nodes in preorder (the order they are first discovered). +// +// Purpose / Use cases: +// - Enumerate nodes by depth-first order. +// - Detect cycles, compute connected components, topological sorts (with mods). +// - Useful in search problems, path finding (not shortest by edges), etc. +// +// Approach / Methodology: +// - Represent an undirected graph with an adjacency list map[int][]int. +// - Maintain a visited set and recursively visit neighbors in insertion order. +// - The order nodes are appended when first visited is the DFS visit order. +// +// Complexity Analysis: +// - Time complexity: O(V + E) +// - Space complexity: O(V) for visited set + recursion stack (worst-case O(V)). +// +// File contents: +// - Graph type and methods (AddEdge, AddNode). +// - DFS function that returns visit order (slice of ints) or nil if start missing. +// - Simple test harness with deterministic small numeric graphs and pass/fail checks. +// +// Author: (your name) +// Date: (optional) + +package main + +import ( + "fmt" + "os" + "strconv" +) + +// Graph represents an undirected graph with integer node IDs. +type Graph struct { + adj map[int][]int // adjacency list: node -> list of neighbors +} + +// NewGraph creates and returns an empty Graph. +func NewGraph() *Graph { + return &Graph{adj: make(map[int][]int)} +} + +// AddNode ensures a node entry exists in the adjacency map. +// It's safe to call this before adding edges if you want isolated nodes. +func (g *Graph) AddNode(id int) { + if _, ok := g.adj[id]; !ok { + g.adj[id] = []int{} + } +} + +// AddEdge adds an undirected edge between a and b. +// If nodes don't exist yet they are created automatically. +// The order of AddEdge calls determines neighbor order and therefore +// DFS deterministic visit order for the same insertion order. +func (g *Graph) AddEdge(a, b int) { + g.adj[a] = append(g.adj[a], b) + g.adj[b] = append(g.adj[b], a) +} + +// DFS runs depth-first search starting from `start` (preorder). +// Returns a slice with the visit order (nodes in the order first discovered). +// If the start node is not present in the graph, DFS returns nil. +// +// Time complexity: O(V + E) +// Space complexity: O(V) +func (g *Graph) DFS(start int) []int { + // If the start node is not present, return nil to indicate an invalid start. + if _, ok := g.adj[start]; !ok { + return nil + } + + visited := make(map[int]bool, len(g.adj)) + visitOrder := make([]int, 0, len(g.adj)) + + var dfsRec func(int) + dfsRec = func(u int) { + visited[u] = true + visitOrder = append(visitOrder, u) + for _, nb := range g.adj[u] { + if !visited[nb] { + dfsRec(nb) + } + } + } + + dfsRec(start) + return visitOrder +} + +// compareSlices checks equality of two integer slices. +func compareSlices(a, b []int) bool { + if a == nil && b == nil { + return true + } + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// expect checks the DFS output against expected result and prints pass/fail. +func expect(got, expected []int, testName string) { + // Always print the DFS order to make results explicit. + fmt.Printf("%s - DFS order: %v\n", testName, got) + if compareSlices(got, expected) { + fmt.Printf("[PASS] %s\n\n", testName) + } else { + fmt.Printf("[FAIL] %s\n", testName) + fmt.Printf(" Got : %v\n", got) + fmt.Printf(" Expected: %v\n\n", expected) + } +} + +// runTests builds small numeric graphs and runs compact, deterministic tests. +func runTests() { + fmt.Println("DFS Traversal Tests (numeric nodes)\n") + + // Graph G: + // 1 - 2 - 4 + // | + // 3 - 5 - 6 + // + // (Edges are added in order to make DFS deterministic for the tests) + g := NewGraph() + g.AddEdge(1, 2) // neighbors: 1:[2], 2:[1] + g.AddEdge(1, 3) // 1:[2,3], 3:[1] + g.AddEdge(2, 4) // 2:[1,4], 4:[2] + g.AddEdge(3, 5) // 3:[1,5], 5:[3] + g.AddEdge(5, 6) // 5:[3,6], 6:[5] + // Add isolated node 7 (no edges) + g.AddNode(7) + + // Test 1: start = 1 (connected component) + // Expected DFS preorder: + // 1,2,4,3,5,6 + expected1 := []int{1, 2, 4, 3, 5, 6} + got1 := g.DFS(1) + expect(got1, expected1, "Test 1: start=1 (connected)") + + // Test 2: start = 3 (middle node) + // Expected order: 3,1,2,4,5,6 + expected2 := []int{3, 1, 2, 4, 5, 6} + got2 := g.DFS(3) + expect(got2, expected2, "Test 2: start=3 (middle node)") + + // Test 3: isolated node start = 7 + // Node 7 exists but is isolated => visit order [7] + expected3 := []int{7} + got3 := g.DFS(7) + expect(got3, expected3, "Test 3: start=7 (isolated node)") + + // Test 4: start missing => nil returned + got4 := g.DFS(99) + expect(got4, nil, "Test 4: start missing (99) => nil") + + // Test 5: empty graph => start not present => nil + empty := NewGraph() + got5 := empty.DFS(1) + expect(got5, nil, "Test 5: empty graph => start not found") + + fmt.Println("Tests completed.") +} + +// main: runs tests by default. If first CLI argument is present and is an integer, +// builds the sample graph and runs DFS starting from that node, printing only the visit order. +func main() { + // If CLI arg provided, run DFS interactively on the sample graph and print the visit order. + if len(os.Args) > 1 { + startStr := os.Args[1] + start, err := strconv.Atoi(startStr) + if err != nil { + fmt.Printf("Invalid start node: %q. Provide integer node id.\n", startStr) + return + } + // Build the same small sample graph used in tests: + g := NewGraph() + g.AddEdge(1, 2) + g.AddEdge(1, 3) + g.AddEdge(2, 4) + g.AddEdge(3, 5) + g.AddEdge(5, 6) + g.AddNode(7) + + order := g.DFS(start) + if order == nil { + fmt.Printf("Start node %d not found in graph\n", start) + return + } + // Print the DFS visit order explicitly for interactive runs. + fmt.Printf("DFS visit order from %d: %v\n", start, order) + return + } + + // No CLI arg: run the compact test suite. + runTests() +}