Python Tutorial

Graphs

A set of vertices connected by edges — the model behind maps, social networks, and dependencies.

Vertices and Edges

A graph is a collection of vertices (nodes) joined by edges. Unlike a tree, a graph can have cycles, multiple paths between nodes, and disconnected parts. Edges may be:

  • Directed (one-way, like Twitter follows) or undirected (mutual, like Facebook friends).
  • Weighted (edges carry a cost/distance) or unweighted.

Two Ways to Represent a Graph

Adjacency list (a dict of neighbors) is compact for sparse graphs. Adjacency matrix (a 2-D grid) gives O(1) edge lookup but uses O(V²) memory.

from collections import defaultdict

# adjacency list for an undirected graph
graph = defaultdict(list)

def add_edge(u, v):
    graph[u].append(v)
    graph[v].append(u)      # omit this line for a directed graph

for u, v in [("A", "B"), ("A", "C"), ("B", "D"), ("C", "D")]:
    add_edge(u, v)

print(dict(graph))
# {'A': ['B', 'C'], 'B': ['A', 'D'], 'C': ['A', 'D'], 'D': ['B', 'C']}

Breadth-First Search (BFS)

BFS explores level by level using a queue. In an unweighted graph it finds the shortest path (fewest edges) from the start.

from collections import deque

def bfs(graph, start):
    visited = {start}
    order = []
    q = deque([start])
    while q:
        node = q.popleft()
        order.append(node)
        for nb in graph[node]:
            if nb not in visited:
                visited.add(nb)   # mark on enqueue to avoid duplicates
                q.append(nb)
    return order

print(bfs(graph, "A"))   # ['A', 'B', 'C', 'D']

Depth-First Search (DFS)

def dfs(graph, start, visited=None):
    if visited is None:
        visited = set()
    visited.add(start)
    print(start, end=" ")
    for nb in graph[start]:
        if nb not in visited:
            dfs(graph, nb, visited)

dfs(graph, "A")   # A B D C  (order depends on edge insertion)

Always track visited nodes. Without it, cycles cause infinite loops — the key difference from tree traversal.

Weighted Shortest Path: Dijkstra

For weighted graphs with non-negative edges, Dijkstra's algorithm finds the cheapest path using a priority queue.

import heapq

def dijkstra(weighted, start):
    dist = {start: 0}
    pq = [(0, start)]
    while pq:
        d, node = heapq.heappop(pq)
        if d > dist.get(node, float("inf")):
            continue
        for nb, w in weighted[node]:
            nd = d + w
            if nd < dist.get(nb, float("inf")):
                dist[nb] = nd
                heapq.heappush(pq, (nd, nb))
    return dist

wg = {"A": [("B", 1), ("C", 4)], "B": [("C", 2)], "C": []}
print(dijkstra(wg, "A"))   # {'A': 0, 'B': 1, 'C': 3}

Where Graphs Appear

  • Maps and GPS routing (weighted shortest path).
  • Social networks, recommendation systems.
  • Dependency resolution and build order (topological sort on a DAG).
  • Web crawling and network analysis.

Best Practices

  • Use adjacency lists for sparse graphs, matrices for dense ones.
  • BFS for shortest path in unweighted graphs; Dijkstra for weighted (non-negative).
  • Always mark visited nodes to handle cycles.
  • For real projects use the networkx library instead of reimplementing algorithms.

Try It Yourself

Exercise 1: For an unweighted graph, which traversal finds the shortest path (fewest edges)?

Show solution

Breadth-first search (BFS) — it explores nodes in order of distance from the start.

Exercise 2: Why must graph traversals track visited nodes when tree traversals do not?

Show solution

Graphs can contain cycles; without a visited set, traversal would loop forever. Trees are acyclic, so no such tracking is needed.

📘 Real-World Deep Dive

Knowing <strong>DSA Graphs (algorithms & data structures)</strong> well is what turns algorithms & data structures from a curiosity into a daily tool — you'll reach for it in nearly every real project.

Real-Life Scenario

An end-to-end usage of DSA Graphs that you'd actually see in a data pipeline or analytics notebook.

Real-Life Example

from collections import defaultdict, deque

def bfs(adj, src):
    seen, q = {src}, deque([src])
    order = []
    while q:
        u = q.popleft(); order.append(u)
        for v in adj[u]:
            if v not in seen:
                seen.add(v); q.append(v)
    return order

adj = defaultdict(list)
for u, v in [("a","b"),("a","c"),("b","d"),("c","e"),("d","e")]:
    adj[u].append(v)
print(bfs(adj, "a"))

Expected Output

(see source)

Common mistakes

  • Off-by-one errors in binary-search: the standard idiom is while lo <= hi with mid = (lo + hi) // 2.
  • Recursive algorithms blow the stack for n > ~10⁴; convert to iterative with an explicit stack.
  • Comparison algorithms (sorted(iterable)) are stable by default in Python — surprising for Java/C++ users.
  • Treating DSA Graphs as a black box without reading the docs — the API has subtle defaults that bite when you scale.

🚀 Performance & Best Practices

  • Use bisect.bisect_left / bisect_right instead of writing your own binary search.
  • Convert a sorted search into a tuple-access pattern with numpy.searchsorted for huge arrays.
  • Use heapq for priority queues instead of maintaining a sorted list manually.
  • When working with algorithms & data structures, prefer vectorised / batched operations over Python loops.

🧪 Try It Yourself

  1. Reproduce the snippet on a representative slice of your own data.
  2. Profile the snippet with cProfile or timeit and find the single biggest improvement.
  3. Generalise the snippet into a small, reusable function you can drop into future projects.

FAQ: Graphs

Common questions about this page.

What is Graphs?

Graphs is a DSA lesson that explains graphs in Python. A set of vertices connected by edges — the model behind maps, social networks, and dependencies. Copy the samples and run them in the Python editor. It is written for beginners who want a clear definition and working examples.

Should I run graphs examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn graphs in this DSA Python lesson (Graphs).

How do I use graphs in Python?

To use graphs in Python, follow the examples on this StudyGrid page. Copy a snippet, run it in the browser, then Download and run it locally for better learning. Change the values and compare the output.

What is the syntax of graphs?

This Graphs tutorial shows graphs syntax with short Python examples. Use the code blocks in this lesson for the exact statements, then try them in your editor.

Graphs example for beginners

Yes. This page includes a beginner graphs example you can copy and run. It is designed for searches such as "graphs for beginners", "graphs example", and "how to use graphs".

What are common mistakes with graphs?

Common graphs mistakes include wrong syntax, mixing types, and skipping practice. Work through this DSA chapter in order, run every example, and check the output before moving on.

Why should I learn graphs?

Graphs is used in real Python work. Learning graphs helps you write clearer programs and continue the DSA tutorial on StudyGrid.

Is Graphs free to learn online?

Yes. You can learn graphs free on StudyGrid (studygrid.in). This chapter is part of the DSA path and includes examples, syntax, and next-step links.