From 3f6c91ea4520d93a6ce08f1aa598d41651ca5316 Mon Sep 17 00:00:00 2001 From: Sohan Rout Date: Mon, 3 Aug 2026 23:16:21 +0530 Subject: [PATCH] Feat : all modules completed --- .../graph/algorithms/dijkstra/animation.jsx | 490 ++++++++++++++++++ .../graph/algorithms/dijkstra/code.js | 215 ++++++++ .../graph/algorithms/dijkstra/content.jsx | 218 ++++++++ .../graph/algorithms/dijkstra/page.jsx | 116 +++++ .../graph/algorithms/dijkstra/quiz.jsx | 379 ++++++++++++++ .../graph/algorithms/kruskal/animation.jsx | 401 ++++++++++++++ .../graph/algorithms/kruskal/code.js | 183 +++++++ .../graph/algorithms/kruskal/content.jsx | 216 ++++++++ .../graph/algorithms/kruskal/page.jsx | 115 ++++ .../graph/algorithms/kruskal/quiz.jsx | 384 ++++++++++++++ .../graph/algorithms/prim/animation.jsx | 438 ++++++++++++++++ app/visualizer/graph/algorithms/prim/code.js | 202 ++++++++ .../graph/algorithms/prim/content.jsx | 219 ++++++++ app/visualizer/graph/algorithms/prim/page.jsx | 113 ++++ app/visualizer/graph/algorithms/prim/quiz.jsx | 384 ++++++++++++++ .../algorithms/topological-sort/animation.jsx | 407 +++++++++++++++ .../graph/algorithms/topological-sort/code.js | 156 ++++++ .../algorithms/topological-sort/content.jsx | 212 ++++++++ .../algorithms/topological-sort/page.jsx | 113 ++++ .../algorithms/topological-sort/quiz.jsx | 384 ++++++++++++++ app/visualizer/graph/traversal/bfs/page.jsx | 1 + app/visualizer/graph/traversal/dfs/page.jsx | 1 + lib/modulesMap.js | 4 + public/sitemap-0.xml | 146 +++--- 24 files changed, 5428 insertions(+), 69 deletions(-) create mode 100755 app/visualizer/graph/algorithms/dijkstra/animation.jsx create mode 100755 app/visualizer/graph/algorithms/dijkstra/code.js create mode 100755 app/visualizer/graph/algorithms/dijkstra/content.jsx create mode 100755 app/visualizer/graph/algorithms/dijkstra/page.jsx create mode 100755 app/visualizer/graph/algorithms/dijkstra/quiz.jsx create mode 100755 app/visualizer/graph/algorithms/kruskal/animation.jsx create mode 100755 app/visualizer/graph/algorithms/kruskal/code.js create mode 100755 app/visualizer/graph/algorithms/kruskal/content.jsx create mode 100755 app/visualizer/graph/algorithms/kruskal/page.jsx create mode 100755 app/visualizer/graph/algorithms/kruskal/quiz.jsx create mode 100755 app/visualizer/graph/algorithms/prim/animation.jsx create mode 100755 app/visualizer/graph/algorithms/prim/code.js create mode 100755 app/visualizer/graph/algorithms/prim/content.jsx create mode 100755 app/visualizer/graph/algorithms/prim/page.jsx create mode 100755 app/visualizer/graph/algorithms/prim/quiz.jsx create mode 100755 app/visualizer/graph/algorithms/topological-sort/animation.jsx create mode 100755 app/visualizer/graph/algorithms/topological-sort/code.js create mode 100755 app/visualizer/graph/algorithms/topological-sort/content.jsx create mode 100755 app/visualizer/graph/algorithms/topological-sort/page.jsx create mode 100755 app/visualizer/graph/algorithms/topological-sort/quiz.jsx diff --git a/app/visualizer/graph/algorithms/dijkstra/animation.jsx b/app/visualizer/graph/algorithms/dijkstra/animation.jsx new file mode 100755 index 0000000..f67afb6 --- /dev/null +++ b/app/visualizer/graph/algorithms/dijkstra/animation.jsx @@ -0,0 +1,490 @@ +"use client"; +import React, { useState } from "react"; +import { gsap } from "gsap"; +import { Plus, Shuffle, RotateCcw, Play, Route } from "lucide-react"; + +const LETTERS = "ABCDEFGHIJ".split(""); +const MAX_VERTICES = 10; + +const layoutCircle = (vertices) => { + const n = vertices.length; + const radius = n <= 1 ? 0 : 130; + const cx = 220; + const cy = 170; + return vertices.map((v, i) => { + const angle = (2 * Math.PI * i) / n - Math.PI / 2; + return { label: v, x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) }; + }); +}; + +const buildWeightedAdjList = (vertices, edges) => { + const list = {}; + vertices.forEach((v) => (list[v] = [])); + edges.forEach((e) => { + if (list[e.from]) list[e.from].push({ to: e.to, weight: e.weight }); + if (!e.directed && list[e.to]) list[e.to].push({ to: e.from, weight: e.weight }); + }); + return list; +}; + +// Greedy relaxation: always finalize whichever unvisited vertex currently +// has the smallest tentative distance — since all weights are non-negative, +// no edge discovered later could ever produce a shorter path to it. +const dijkstraWithSteps = (vertices, adjList, start) => { + const dist = {}; + const prev = {}; + const visited = new Set(); + vertices.forEach((v) => (dist[v] = Infinity)); + dist[start] = 0; + const steps = []; + + while (visited.size < vertices.length) { + let u = null; + let best = Infinity; + for (const v of vertices) { + if (!visited.has(v) && dist[v] < best) { + best = dist[v]; + u = v; + } + } + if (u === null) break; // everything remaining is unreachable + + visited.add(u); + steps.push({ type: "select", vertex: u, dist: { ...dist } }); + + for (const { to, weight } of adjList[u] || []) { + if (visited.has(to)) continue; + const candidate = dist[u] + weight; + if (candidate < dist[to]) { + dist[to] = candidate; + prev[to] = u; + steps.push({ type: "relax", from: u, to, newDist: candidate, dist: { ...dist } }); + } else { + steps.push({ type: "check", from: u, to }); + } + } + } + + return { steps, dist, prev }; +}; + +const buildPath = (prev, start, target) => { + if (target === start) return [start]; + const path = []; + let cur = target; + while (cur !== undefined && cur !== start) { + path.unshift(cur); + cur = prev[cur]; + } + if (cur !== start) return null; // unreachable + path.unshift(start); + return path; +}; + +const EXAMPLE_VERTICES = ["A", "B", "C", "D", "E"]; +const EXAMPLE_EDGES = [ + { from: "A", to: "B", weight: 4, directed: false }, + { from: "A", to: "C", weight: 1, directed: false }, + { from: "C", to: "B", weight: 2, directed: false }, + { from: "B", to: "D", weight: 5, directed: false }, + { from: "C", to: "D", weight: 8, directed: false }, + { from: "D", to: "E", weight: 3, directed: false }, +]; + +const STEP_DELAY = 650; + +const DijkstraVisualizer = () => { + const [vertices, setVertices] = useState([]); + const [edges, setEdges] = useState([]); + const [directedMode, setDirectedMode] = useState(false); + const [fromVertex, setFromVertex] = useState(""); + const [toVertex, setToVertex] = useState(""); + const [weightInput, setWeightInput] = useState("1"); + const [startVertex, setStartVertex] = useState(""); + const [targetVertex, setTargetVertex] = useState(""); + const [message, setMessage] = useState("Build a weighted graph, pick a start vertex, and run Dijkstra"); + const [busy, setBusy] = useState(false); + + const [distances, setDistances] = useState({}); + const [visited, setVisited] = useState(new Set()); + const [current, setCurrent] = useState(null); + const [activeEdge, setActiveEdge] = useState(null); + const [finalPrev, setFinalPrev] = useState(null); + const [pathEdges, setPathEdges] = useState(null); + const [pathInfo, setPathInfo] = useState(null); + + const clearResult = () => { + setDistances({}); + setVisited(new Set()); + setCurrent(null); + setActiveEdge(null); + setFinalPrev(null); + setPathEdges(null); + setPathInfo(null); + }; + + const addVertex = () => { + if (vertices.length >= MAX_VERTICES) { + setMessage(`Limit of ${MAX_VERTICES} vertices reached`); + return; + } + const next = LETTERS[vertices.length]; + setVertices((prev) => [...prev, next]); + setMessage(`Added vertex ${next}`); + clearResult(); + }; + + const addEdge = () => { + if (!fromVertex || !toVertex) { + setMessage("Choose both a From and a To vertex"); + return; + } + const weight = parseFloat(weightInput); + if (Number.isNaN(weight) || weight < 0) { + setMessage("Enter a valid non-negative weight"); + return; + } + setEdges((prev) => { + const existingIndex = prev.findIndex( + (e) => (e.from === fromVertex && e.to === toVertex) || (!e.directed && e.from === toVertex && e.to === fromVertex) + ); + const newEdge = { from: fromVertex, to: toVertex, weight, directed: directedMode }; + if (existingIndex >= 0) { + const copy = [...prev]; + copy[existingIndex] = newEdge; + return copy; + } + return [...prev, newEdge]; + }); + setMessage(`Connected ${fromVertex} ${directedMode ? "→" : "↔"} ${toVertex} (weight ${weight})`); + clearResult(); + }; + + const loadExample = () => { + if (busy) return; + setVertices(EXAMPLE_VERTICES); + setEdges(EXAMPLE_EDGES); + setStartVertex("A"); + setTargetVertex("E"); + clearResult(); + setMessage("Loaded an example graph — click Run Dijkstra"); + }; + + const reset = () => { + if (busy) return; + setVertices([]); + setEdges([]); + setFromVertex(""); + setToVertex(""); + setWeightInput("1"); + setStartVertex(""); + setTargetVertex(""); + clearResult(); + setMessage("Build a weighted graph, pick a start vertex, and run Dijkstra"); + }; + + const handleRun = () => { + if (busy || !startVertex) return; + const adjList = buildWeightedAdjList(vertices, edges); + const { steps, dist, prev } = dijkstraWithSteps(vertices, adjList, startVertex); + + setBusy(true); + clearResult(); + const initialDist = {}; + vertices.forEach((v) => (initialDist[v] = v === startVertex ? 0 : Infinity)); + setDistances(initialDist); + + let i = 0; + const reveal = () => { + const step = steps[i]; + + if (step.type === "select") { + setCurrent(step.vertex); + setVisited((p) => new Set(p).add(step.vertex)); + setActiveEdge(null); + setMessage(`Finalize ${step.vertex} — no shorter path to it can exist now`); + } else if (step.type === "relax") { + setActiveEdge({ from: step.from, to: step.to }); + setDistances((prevD) => ({ ...prevD, [step.to]: step.newDist })); + setMessage(`Relax ${step.from} → ${step.to}: found a shorter distance of ${step.newDist}`); + } else if (step.type === "check") { + setActiveEdge({ from: step.from, to: step.to }); + setMessage(`Check ${step.from} → ${step.to}: no improvement, keep current distance`); + } + + i++; + if (i < steps.length) { + setTimeout(reveal, STEP_DELAY); + } else { + setTimeout(() => { + setCurrent(null); + setActiveEdge(null); + setFinalPrev(prev); + setMessage("Dijkstra complete — every vertex now has its shortest distance from the start"); + setBusy(false); + }, STEP_DELAY); + } + }; + reveal(); + }; + + const handleShowPath = () => { + if (!finalPrev || !targetVertex || !startVertex) return; + const path = buildPath(finalPrev, startVertex, targetVertex); + if (!path) { + setPathEdges(null); + setPathInfo({ unreachable: true }); + return; + } + const pairs = []; + for (let i = 0; i < path.length - 1; i++) pairs.push({ from: path[i], to: path[i + 1] }); + setPathEdges(pairs); + setPathInfo({ path, distance: distances[targetVertex] }); + }; + + const positions = layoutCircle(vertices); + const posByLabel = Object.fromEntries(positions.map((p) => [p.label, p])); + + const isOnPath = (from, to) => pathEdges && pathEdges.some((p) => (p.from === from && p.to === to) || (p.from === to && p.to === from)); + + const animateDropIn = (el) => { + if (!el || el.dataset.animated) return; + el.dataset.animated = "true"; + gsap.fromTo(el, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.4, ease: "back.out(1.7)" }); + }; + + return ( +
+

+ Find the shortest weighted-distance path from a start vertex to every other vertex +

+ +
+ {/* Controls */} +
+
+ + +
+ +
+ + + setWeightInput(e.target.value)} + placeholder="Weight" + disabled={busy} + className="w-20 px-3 py-2 text-sm rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-neutral-900 text-gray-800 dark:text-gray-100 outline-none focus:ring-2 focus:ring-blue-500/40" + /> + +
+ +
+ + +
+ + {finalPrev && ( +
+ + +
+ )} + +
+ + +
+
+ + {/* Message */} +
+ {message} +
+ + {pathInfo && ( +
+ {pathInfo.unreachable ? `${targetVertex} is not reachable from ${startVertex}` : `Shortest path: ${pathInfo.path.join(" → ")} (distance ${pathInfo.distance})`} +
+ )} + + {/* Distance table */} + {Object.keys(distances).length > 0 && ( +
+

Distances from {startVertex}

+
+ {vertices.map((v) => ( +
+ {v}: {distances[v] === Infinity ? "∞" : distances[v]} +
+ ))} +
+
+ )} + + {/* Graph */} +
+

Graph

+
+ {vertices.length > 0 ? ( + + + + + + + + + + + + + + + + {edges.map((e, i) => { + const a = posByLabel[e.from]; + const b = posByLabel[e.to]; + if (!a || !b) return null; + const midX = (a.x + b.x) / 2; + const midY = (a.y + b.y) / 2; + const isActive = activeEdge && ((activeEdge.from === e.from && activeEdge.to === e.to) || (!e.directed && activeEdge.from === e.to && activeEdge.to === e.from)); + const onPath = isOnPath(e.from, e.to); + const stroke = onPath ? "#8b5cf6" : isActive ? "#f59e0b" : "#818cf8"; + return ( + + + + + {e.weight} + + + ); + })} + + {positions.map((p, i) => { + const isVisitedV = visited.has(p.label); + const isCurrent = current === p.label; + return ( + + {isCurrent && ( + + )} + + + {p.label} + + + ); + })} + + ) : ( +
+ Add a vertex to begin +
+ )} +
+ +
+ + + Unvisited + + + + Finalized + + + + Currently finalized / edge relaxed + + + + Shortest path + +
+
+
+
+ ); +}; + +export default DijkstraVisualizer; diff --git a/app/visualizer/graph/algorithms/dijkstra/code.js b/app/visualizer/graph/algorithms/dijkstra/code.js new file mode 100755 index 0000000..b0b4c14 --- /dev/null +++ b/app/visualizer/graph/algorithms/dijkstra/code.js @@ -0,0 +1,215 @@ +const codeExamples = { + javascript: `// Greedy relaxation: since all weights are non-negative, always finalizing +// the closest unvisited vertex guarantees its distance can never improve. +function dijkstra(vertices, adjList, start) { + const dist = {}; + const prev = {}; + const visited = new Set(); + vertices.forEach((v) => (dist[v] = Infinity)); + dist[start] = 0; + + while (visited.size < vertices.length) { + // Pick the unvisited vertex with the smallest tentative distance + let u = null; + let best = Infinity; + for (const v of vertices) { + if (!visited.has(v) && dist[v] < best) { + best = dist[v]; + u = v; + } + } + if (u === null) break; // remaining vertices are unreachable + + visited.add(u); + + for (const { to, weight } of adjList[u] || []) { + if (visited.has(to)) continue; + const candidate = dist[u] + weight; + if (candidate < dist[to]) { + dist[to] = candidate; // relax the edge + prev[to] = u; + } + } + } + + return { dist, prev }; +} + +function reconstructPath(prev, start, target) { + const path = []; + let current = target; + while (current !== undefined && current !== start) { + path.unshift(current); + current = prev[current]; + } + if (current !== start) return null; // unreachable + path.unshift(start); + return path; +} + +// Usage example +const adjList = { + A: [{ to: "B", weight: 4 }, { to: "C", weight: 1 }], + B: [{ to: "A", weight: 4 }, { to: "C", weight: 2 }, { to: "D", weight: 5 }], + C: [{ to: "A", weight: 1 }, { to: "B", weight: 2 }, { to: "D", weight: 8 }], + D: [{ to: "B", weight: 5 }, { to: "C", weight: 8 }], +}; +const { dist, prev } = dijkstra(["A", "B", "C", "D"], adjList, "A"); +reconstructPath(prev, "A", "D"); // ["A", "C", "B", "D"]`, + + python: `import math + +# Greedy relaxation: since all weights are non-negative, always finalizing +# the closest unvisited vertex guarantees its distance can never improve. +def dijkstra(vertices, adj_list, start): + dist = {v: math.inf for v in vertices} + prev = {} + visited = set() + dist[start] = 0 + + while len(visited) < len(vertices): + # Pick the unvisited vertex with the smallest tentative distance + u, best = None, math.inf + for v in vertices: + if v not in visited and dist[v] < best: + best, u = dist[v], v + if u is None: + break # remaining vertices are unreachable + + visited.add(u) + + for to, weight in adj_list.get(u, []): + if to in visited: + continue + candidate = dist[u] + weight + if candidate < dist[to]: + dist[to] = candidate # relax the edge + prev[to] = u + + return dist, prev + +def reconstruct_path(prev, start, target): + path = [] + current = target + while current is not None and current != start: + path.insert(0, current) + current = prev.get(current) + if current != start: + return None # unreachable + path.insert(0, start) + return path + +# Usage example +adj_list = { + "A": [("B", 4), ("C", 1)], + "B": [("A", 4), ("C", 2), ("D", 5)], + "C": [("A", 1), ("B", 2), ("D", 8)], + "D": [("B", 5), ("C", 8)], +} +dist, prev = dijkstra(["A", "B", "C", "D"], adj_list, "A") +reconstruct_path(prev, "A", "D") # ["A", "C", "B", "D"]`, + + c: `#include +#include +#include + +#define MAX_V 26 +#define INF INT_MAX + +int graph[MAX_V][MAX_V]; // graph[i][j] = weight, or 0 for no edge +int dist[MAX_V]; +bool visited[MAX_V]; + +// Greedy relaxation: since all weights are non-negative, always finalizing +// the closest unvisited vertex guarantees its distance can never improve. +void dijkstra(int n, int start) { + for (int i = 0; i < n; i++) { dist[i] = INF; visited[i] = false; } + dist[start] = 0; + + for (int count = 0; count < n; count++) { + int u = -1, best = INF; + for (int v = 0; v < n; v++) { + if (!visited[v] && dist[v] < best) { best = dist[v]; u = v; } + } + if (u == -1) break; // remaining vertices are unreachable + + visited[u] = true; + + for (int v = 0; v < n; v++) { + if (graph[u][v] != 0 && !visited[v] && dist[u] != INF) { + int candidate = dist[u] + graph[u][v]; + if (candidate < dist[v]) dist[v] = candidate; // relax the edge + } + } + } +} + +int main() { + int n = 4; // A=0, B=1, C=2, D=3 + graph[0][1] = graph[1][0] = 4; + graph[0][2] = graph[2][0] = 1; + graph[1][2] = graph[2][1] = 2; + graph[1][3] = graph[3][1] = 5; + graph[2][3] = graph[3][2] = 8; + + dijkstra(n, 0); + for (int i = 0; i < n; i++) printf("dist[%d] = %d\\n", i, dist[i]); + return 0; +}`, + + java: `import java.util.*; + +public class Dijkstra { + static class Edge { + char to; + int weight; + Edge(char to, int weight) { this.to = to; this.weight = weight; } + } + + // Greedy relaxation: since all weights are non-negative, always finalizing + // the closest unvisited vertex guarantees its distance can never improve. + static Map dijkstra(List vertices, Map> adjList, char start) { + Map dist = new HashMap<>(); + Set visited = new HashSet<>(); + for (char v : vertices) dist.put(v, Integer.MAX_VALUE); + dist.put(start, 0); + + while (visited.size() < vertices.size()) { + char u = 0; + int best = Integer.MAX_VALUE; + boolean found = false; + for (char v : vertices) { + if (!visited.contains(v) && dist.get(v) < best) { + best = dist.get(v); + u = v; + found = true; + } + } + if (!found) break; // remaining vertices are unreachable + + visited.add(u); + + for (Edge edge : adjList.getOrDefault(u, List.of())) { + if (visited.contains(edge.to)) continue; + int candidate = dist.get(u) + edge.weight; + if (candidate < dist.get(edge.to)) { + dist.put(edge.to, candidate); // relax the edge + } + } + } + return dist; + } + + public static void main(String[] args) { + Map> adjList = new HashMap<>(); + adjList.put('A', List.of(new Edge('B', 4), new Edge('C', 1))); + adjList.put('B', List.of(new Edge('A', 4), new Edge('C', 2), new Edge('D', 5))); + adjList.put('C', List.of(new Edge('A', 1), new Edge('B', 2), new Edge('D', 8))); + adjList.put('D', List.of(new Edge('B', 5), new Edge('C', 8))); + + System.out.println(dijkstra(List.of('A', 'B', 'C', 'D'), adjList, 'A')); + } +}`, +}; + +export default codeExamples; diff --git a/app/visualizer/graph/algorithms/dijkstra/content.jsx b/app/visualizer/graph/algorithms/dijkstra/content.jsx new file mode 100755 index 0000000..d40ed67 --- /dev/null +++ b/app/visualizer/graph/algorithms/dijkstra/content.jsx @@ -0,0 +1,218 @@ +"use client"; +import ComplexityGraph from "@/app/components/ui/graph"; +import { useTheme } from "@/app/contexts/ThemeContext"; +import DailyDSAEmbed from "@/app/components/ui/DailyDSAEmbed"; +import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; +import InContentAd from "@/app/components/ads/InContentAd"; +import { motion } from "framer-motion"; + +const WalkthroughDiagram = () => { + const vertices = [ + { id: "A", x: 20, y: 75, dist: 0 }, + { id: "B", x: 100, y: 20, dist: 3 }, + { id: "C", x: 100, y: 130, dist: 1 }, + { id: "D", x: 180, y: 75, dist: 6 }, + ]; + const edges = [ + ["A", "B", 3], + ["A", "C", 1], + ["C", "B", 1], + ["B", "D", 3], + ["C", "D", 8], + ]; + const byId = Object.fromEntries(vertices.map((v) => [v.id, v])); + const shortestEdges = new Set(["A-C", "C-B", "B-D"]); + + return ( + + {edges.map(([from, to, w], i) => { + const onPath = shortestEdges.has(`${from}-${to}`) || shortestEdges.has(`${to}-${from}`); + const midX = (byId[from].x + byId[to].x) / 2; + const midY = (byId[from].y + byId[to].y) / 2; + return ( + + + + + {w} + + + ); + })} + {vertices.map((v, i) => ( + + + + {v.id} + + + {v.dist} + + + ))} + + ); +}; + +const Content = () => { + const { theme } = useTheme(); + + const paragraphs = [ + `Dijkstra's algorithm finds the shortest-distance path from a single start vertex to every other vertex in a weighted graph — "shortest" meaning the smallest total edge weight along the path, not the fewest edges (which is what plain BFS finds on an unweighted graph). It requires every edge weight to be non-negative; a single negative weight can break its core assumption and produce wrong answers.`, + `The algorithm keeps a tentative distance for every vertex, starting at 0 for the source and infinity for everything else. At each step, it finalizes whichever unvisited vertex currently has the smallest tentative distance — once a vertex is finalized, its distance is guaranteed correct and will never be revised again. Then it "relaxes" every edge out of that vertex: for each neighbor, if going through the just-finalized vertex would produce a shorter distance than what's currently recorded, the neighbor's distance is updated.`, + `The key insight behind why picking the smallest unvisited distance is always safe: since every edge weight is non-negative, any path to that vertex through a still-unvisited (and therefore farther-or-equal) vertex could only be equal or longer. There's no way a shortcut could still be waiting to be discovered. That guarantee is exactly what breaks down if a negative edge weight is allowed — a path through a vertex that currently looks farther away could later turn out shorter, and algorithms like Bellman-Ford exist specifically to handle that case.`, + `Dijkstra's algorithm (typically implemented with a min-priority-queue for efficiency) is the standard tool behind GPS and mapping route-finding, network routing protocols that pick the cheapest path between routers, and any scenario where "cheapest route through a weighted network" needs an exact answer rather than an approximation.`, + ]; + + const algorithm = [ + { points: "Set the start vertex's distance to 0, and every other vertex's distance to infinity" }, + { + points: "While unvisited vertices remain, repeat:", + subpoints: [ + "Pick the unvisited vertex with the smallest tentative distance and mark it finalized", + "For each of its neighbors, if the path through this vertex is shorter than the neighbor's current recorded distance, update it (this is a \"relaxation\")", + ], + }, + { points: "Once every reachable vertex is finalized, each vertex's recorded distance is its true shortest distance from the start" }, + { points: "To reconstruct the actual shortest path to any vertex, follow the chain of \"came from\" pointers recorded during relaxation, back to the start" }, + ]; + + const complexity = [ + { points: "Time Complexity: O((V + E) log V) with a binary heap priority queue — each vertex is extracted once and each edge triggers at most one relaxation, both at logarithmic cost." }, + { points: "Space Complexity: O(V) — for the distance array, the previous-vertex pointers, and the priority queue." }, + ]; + + return ( +
+
+ + +
+
+ {/* What is it */} +
+

+ + What is Dijkstra's Algorithm? +

+
+

+ {paragraphs[0]} +

+
+
+ + {/* How it works */} +
+

+ + How Does It Work? +

+
+

+ {paragraphs[1]} +

+
+
+

+ {paragraphs[2]} +

+
+ +
+ Shortest distances from A — the path A→C→B→D (1+1+3=5) beats A→B→D directly (3+3=6) +
+ +
+ + {/* Algorithm Steps */} +
+

+ + Algorithm Steps +

+
+
    + {algorithm.map((item, index) => ( +
  1. + {item.points} + {item.subpoints && ( +
      + {item.subpoints.map((subitem, subindex) => ( +
    • + {subitem} +
    • + ))} +
    + )} +
  2. + ))} +
+
+
+ + {/* Time Complexity */} +
+

+ + Time Complexity +

+
+
    + {complexity.map((item, index) => ( +
  • + + {item.points.split(":")[0]}: + + {item.points.split(":")[1]} +
  • + ))} +
+
+ +
+ n * Math.log2(n)} + averageCase={(n) => (n + n) * Math.log2(n)} + worstCase={(n) => (n + n) * Math.log2(n)} + maxN={25} + /> +
+ + +
+ + {/* Additional Info */} +
+
+
+

+ {paragraphs[3]} +

+
+
+
+
+ + +
+ ); +}; + +export default Content; diff --git a/app/visualizer/graph/algorithms/dijkstra/page.jsx b/app/visualizer/graph/algorithms/dijkstra/page.jsx new file mode 100755 index 0000000..4d0c4bd --- /dev/null +++ b/app/visualizer/graph/algorithms/dijkstra/page.jsx @@ -0,0 +1,116 @@ +import Animation from "@/app/visualizer/graph/algorithms/dijkstra/animation"; +import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTop from "@/app/components/ui/backtotop"; +import ExploreOther from "@/app/components/ui/exploreOther"; +import CodeBlock from "@/app/components/modules/CodeBlock"; +import codeExamples from "./code"; +import Quiz from "@/app/visualizer/graph/algorithms/dijkstra/quiz"; +import Content from "@/app/visualizer/graph/algorithms/dijkstra/content"; +import ModuleCard from "@/app/components/ui/ModuleCard"; +import { MODULE_MAPS } from "@/lib/modulesMap"; + +export const metadata = { + title: "Dijkstra's Algorithm | Animation and Explanation", + description: + "Learn how Dijkstra's algorithm finds the shortest weighted-distance path from a start vertex to every other vertex by greedily finalizing the closest unvisited vertex, with an interactive visualizer, code examples in JavaScript, C, Python, and Java, and a quiz.", + keywords: [ + "Dijkstra's Algorithm", + "Dijkstra Algorithm", + "Dijkstra's Shortest Path", + "Dijkstra Algorithm Visualization", + "Shortest Path Algorithm", + "Weighted Graph Shortest Path", + "Single Source Shortest Path", + "Priority Queue Shortest Path", + "Dijkstra's Algorithm in JavaScript", + "Dijkstra Algorithm in JavaScript", + "Dijkstra's Algorithm in C", + "Dijkstra Algorithm in C", + "Dijkstra's Algorithm in Python", + "Dijkstra Algorithm in Python", + "Dijkstra's Algorithm in Java", + "Dijkstra Algorithm in Java", + "Graph Algorithms", + "DSA Graphs", + "Learn Graphs", + "Graph Quiz", + ], + robots: "index, follow", + openGraph: { + images: [ + { + url: "/og.png", + width: 1200, + height: 630, + alt: "Dijkstra's Algorithm Visualization", + }, + ], + }, +}; + +export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Graph : Dijkstra's Algorithm", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+ + +
+ +
+ +
+ +
+

+ Test Your Knowledge before moving forward! +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ + +