ग्राफ़ (Graphs)
शीर्ष (vertices) और किनारे (edges) — सार्वभौमिक अमूर्तन
Graph · algorithms lab
Click any node to set start, then run BFS or DFS. The frontier panel renders as a queue for BFS and a stack for DFS — that single difference is what makes the two visit orders diverge.
click a node, then bfs or dfs
Weighted edges, real shortest-path search. Click a node to set start (green); click another to set goal (red). Dijkstra explores by cost-so-far; A* uses Euclidean distance to the goal as a heuristic and visibly skips dead-end directions.
click two nodes to pick start and goal
A robot on a discrete map. Click cells to paint walls (toggle). Use the mode buttons to drop the start or goal. BFS finds the shortest path through free space — the gradient shows distance-from-start.
paint some walls, then run BFS
Directed acyclic graph — a robot boot sequence. Topological sort gives a valid order to run things so every dependency is satisfied. Toggle a cycle and watch the algorithm refuse to produce an order.
press run to compute boot order
The robot drove in a square but its odometry drifted. Each edge is a measurement constraint (relative dx, dy). The thick edge is the loop closure: "I'm back where I started." Iterate to relax the graph — every pose shifts to better satisfy the constraints.
press iterate to relax the graph
Multi-source BFS — drop "anchors" (charging stations, robot agents, sensors) and each non-anchor node is colored by its nearest anchor. That's a discrete Voronoi diagram. Used for territory assignment and coverage planning.
click nodes to add or remove anchors
खुद आज़माएँ: छह मोड, एक डेमो। traverse: BFS बनाम DFS, जहाँ frontier एक क़तार बनाम एक स्टैक के रूप में दिखता है — शुरुआत तय करने के लिए किसी भी नोड पर क्लिक कीजिए, फिर दोनों को एक साथ दौड़ाइए। shortest path: शुरुआत + लक्ष्य चुनिए, और किसी भारित (weighted) ग्राफ़ पर Dijkstra की A* से तुलना कीजिए। grid: दीवारें रंगिए, और देखिए कि BFS उनके इर्द-गिर्द कैसे योजना बनाता है। dag · topo: किसी रोबोट के boot क्रम को व्यवस्थित कीजिए; एक चक्र (cycle) डालिए और देखिए कैसे एल्गोरिथ्म मना कर देता है। pose graph: किसी बहक चुके पथ को एक loop-closure बाधा का इस्तेमाल कर सीधा कीजिए (खिलौना SLAM)। coverage: anchor छोड़िए, और एक असंतत (discrete) Voronoi आरेख पाइए।
यह क्यों मायने रखता है
ग्राफ़ संबंधों को मॉडल करते हैं: सामाजिक नेटवर्क, सड़क-नक़्शे, निर्भरताएँ (dependencies), स्टेट मशीन। BFS सबसे छोटे पथ ढूँढता है, DFS सारी संभावनाओं को खँगालता है। ग्राफ़ जुड़े हुए डेटा की सार्वभौमिक भाषा हैं।
मूल विचार
सड़कों से जुड़े शहरों के एक नक़्शे को सोचिए। हर शहर एक शीर्ष (vertex) (नोड) है, हर सड़क एक किनारा (edge) (जोड़) है।
ग्राफ़ ऐसे हो सकते हैं:
- Directed: एकतरफ़ा गलियाँ (Twitter follow)
- Undirected: दोतरफ़ा सड़कें (Facebook दोस्त)
- Weighted (भारित): दूरियों वाली सड़कें
दो निरूपण (representations):
- Adjacency matrix: 2D ऐरे जहाँ किनारा होने पर matrix[i][j] = 1। Lookup तेज़ O(1), पर जगह O(V^2)।
- Adjacency list: हर शीर्ष अपने पड़ोसियों की एक सूची रखता है। जगह के लिहाज़ से कुशल O(V+E)।
दो traversal:
- BFS: स्तर-दर-स्तर खोजना, तालाब में लहरों की तरह। सबसे छोटा पथ ढूँढता है (अभारित)।
- DFS: जितना गहरा हो सके जाओ, फिर backtrack करो। चक्र पहचानता है, topological sort।
मुख्य बातें
- शीर्ष (नोड) + किनारे (जोड़)
- Adjacency list आम तौर पर जगह के लिहाज़ से ज़्यादा कुशल है
- BFS सबसे छोटा पथ ढूँढता है, एक क़तार इस्तेमाल करता है
- DFS गहराई में खोजता है, एक स्टैक (या रिकर्शन) इस्तेमाल करता है
और गहराई में
Topological sort — Kahn का एल्गोरिथ्म और DFS-finish-time
एक DAG (directed acyclic graph) निर्भरताओं को दर्शाता है। Topological sort DAG को इस तरह रैखिक करता है कि हर किनारे u → v के लिए आउटपुट में u, v से पहले आए — यानी हर निर्भरता अपने आश्रितों से पहले आए। दो एल्गोरिथ्म, दोनों O(V + E):
Kahn का एल्गोरिथ्म (डेमो के dag · topo मोड में इस्तेमाल):
1. Compute in-degree for every node.
2. Enqueue all nodes with in-degree 0 (no dependencies).
3. While the queue is non-empty:
u = dequeue. emit(u).
For each edge u → v:
in-degree[v] -= 1
if in-degree[v] == 0: enqueue(v).
4. If emitted fewer than V nodes → the graph contains a cycle.
DFS-finish-time वाला रूप: हर बिना-देखे नोड से DFS चलाओ; जब कोई नोड पूरा हो जाए (उसके सारे वंशज खोज लिए जाएँ), तो उसे एक स्टैक पर push कर दो। topological क्रम पाने के लिए स्टैक को उल्टा pop कीजिए। यह रूप स्वाभाविक रूप से strongly connected components ढूँढने तक फैलता है (Kosaraju का, Tarjan का) — उपयोगों में सामाजिक ग्राफ़ों में गुच्छे ढूँढना और प्रोग्राम control flow का विश्लेषण शामिल है।
रोबोटिक्स उपयोग: ROS launch फ़ाइलें एक DAG बनाती हैं (हर नोड के पूर्वापेक्षित नोड होते हैं जिन्हें पहले शुरू होना चाहिए); launch सिस्टम परदे के पीछे topological sort करता है। Behavior tree और Make/Bazel build ग्राफ़ भी वही आकार हैं।
Bellman-Ford — Dijkstra का ऋण-भार वाला चचेरा भाई
Dijkstra ऋणेतर (non-negative) किनारा भार मान लेता है। इसकी शुद्धता का प्रमाण इस तथ्य पर टिका है कि जैसे ही आप priority queue से सबसे कम अब-तक-की-लागत वाले नोड को pop करते हैं, बाद में कोई छोटा पथ आ ही नहीं सकता। ऋण किनारे इस मान्यता को तोड़ देते हैं — एक लंबा पर सस्ता चक्कर किसी "तय" पथ को छोटा कर सकता है।
Bellman-Ford रफ़्तार के बदले ऋण भार सँभालने की क्षमता लेता है:
For each of V−1 iterations:
For each edge (u, v, w):
if dist[u] + w < dist[v]: dist[v] = dist[u] + w
यह O(V·E) है — एक हीप के साथ Dijkstra के O((V+E) log V) से कहीं धीमा। बदले में मिलती है ऋण भार के तहत शुद्धता, और ऋण चक्रों को पहचानने की क्षमता (V-वाँ iteration जो अब भी किसी किनारे को relax करे, तो इसका मतलब है कुल ऋण भार वाला एक चक्र मौजूद है — आपका सबसे छोटा पथ हमेशा घूमता ही रहेगा)।
कब चाहिए: मुद्रा arbitrage पहचान, टोल वापसी / सब्सिडी वाला मार्ग-नियोजन, जहाँ भी किनारे "छूट" हो सकते हों। ज़्यादातर रोबोटिक्स navigation सिर्फ़ ऋणेतर लागतें इस्तेमाल करता है (दूरी, ऊर्जा, समय), इसलिए वहाँ Dijkstra और A* हावी रहते हैं।
न्यूनतम विस्तार वृक्ष (MST)
किसी जुड़े, अदिशात्मक (undirected), भारित ग्राफ़ के लिए, एक MST उन V − 1 किनारों का उपसमुच्चय है जो सारे शीर्षों को न्यूनतम कुल भार के साथ जोड़ता है। दो चिर-परिचित एल्गोरिथ्म, दोनों O(E log V):
- Kruskal का: सारे किनारों को भार के आरोही क्रम में sort कीजिए; हर किनारे को तब लालची होकर जोड़िए जब वह कोई चक्र न बनाए। चक्र-जाँच एक union-find / disjoint-set संरचना इस्तेमाल करती है (प्रति क्वेरी
O(α(n)), असल मेंO(1))। - Prim का: Dijkstra जैसा। किसी भी शीर्ष से शुरू कीजिए; बार-बार "पेड़ के अंदर" से "पेड़ के बाहर" को पार करते न्यूनतम-भार किनारे को निकालिए। किनारा भार से keyed priority queue।
कब चाहिए: सड़क / केबल / पाइपलाइन बिछावट, गुच्छन (single-link clustering = MST बनाकर सबसे बड़े किनारे काटना), नेटवर्क डिज़ाइन। रोबोटिक्स में बहु-एजेंट समन्वय के लिए, MST सारे रोबोटों को घेरता न्यूनतम-संचार पेड़ देता है।
निरूपण के चुनाव
Adjacency-matrix बनाम adjacency-list सिर्फ़ जगह का मामला नहीं। इनके अलग-अलग उपयुक्त मौक़े हैं:
- Matrix:
O(V²)जगह परO(1)किनारा-अस्तित्व जाँच। घने (dense) ग्राफ़ों (E ≈ V²) के लिए या जब आप बार-बार पूछें "क्या u-v एक किनारा है?" — घने ग्रिड में भौतिकी adjacency, all-pairs सबसे छोटे पथ (Floyd-Warshall)। - List:
O(V + E)जगह परO(degree)किनारा जाँच। विरल (sparse) ग्राफ़ों (सड़क-नेटवर्क, सामाजिक नेटवर्क, असल दुनिया के ज़्यादातर ग्राफ़) के लिए।
ज़्यादातर प्रोडक्शन ग्राफ़ लाइब्रेरियाँ list को डिफ़ॉल्ट रखती हैं। ऊपर के shortest-path डेमो में Graph struct नोड id से keyed adjacency list इस्तेमाल करता है।
गणितीय ब्यौरा
- Space Complexity
Adjacency Matrix: O(V^2)Adjacency List: O(V + E)- Time Complexity
BFS/DFS: O(V + E)Check edge (matrix): O(1)Check edge (list): O(degree)
क्रियान्वयन (Implementation)
ग्राफ़ निरूपण
// Adjacency List
let mut graph: Vec<Vec<usize>> = vec![vec![]; n];
graph[0].push(1); // Edge 0 -> 1
graph[1].push(0); // Edge 1 -> 0 (undirected)
// BFS from vertex 0
let mut visited = vec![false; n];
let mut queue = VecDeque::from([0]);
while let Some(v) = queue.pop_front() {
if visited[v] { continue; }
visited[v] = true;
for &neighbor in &graph[v] {
queue.push_back(neighbor);
}
}
चिर-परिचित एल्गोरिथ्म
- BFS: सबसे छोटा पथ (अभारित)
- DFS: चक्र पहचान, topological sort
- Dijkstra: सबसे छोटा पथ (भारित)
- Kruskal/Prim: न्यूनतम विस्तार वृक्ष
अभ्यास
तीन सबसे ज़्यादा पूछे जाने वाले ग्राफ़ मुहावरों को समेटते तीन सवाल:
- Number of Islands — मध्यम · ग्रिड को ग्राफ़ की तरह, flood-fill, connected components
- Course Schedule — मध्यम · Kahn के topological sort से DAG जाँच; हर build सिस्टम के पीछे का एल्गोरिथ्म
- Shortest Path in a Maze — मध्यम · wavefront विस्तार के रूप में BFS; हर रोबोट path planner की बुनियाद