Lecture 9 : Graphs of DSA in Python | DSA in Python

Graphs in Python help developers represent relationships between data points using nodes and edges. This article explains graph basics, common representations, traversal methods like BFS and DFS, and key algorithms such as Dijkstra’s, Prim’s, and topological sorting with simple Python examples.
authorImageVarun Saharawat17 Jun, 2026
Graphs in Python

Graphs are one of the most important non-linear data structures in programming and are used to solve real-world problems like network connections, maps, social media relationships, and data modelling. Unlike linear structures such as arrays or lists, graphs allow multiple connections between different elements.

Graphs in Python means learning how to store relationships efficiently, explore connected data, and apply algorithms to find paths, optimize networks, and process complex information. This article covers the fundamentals of graphs, their representations, traversal techniques, and essential graph algorithms with practical Python implementations.

Overview of Graphs in Python

When navigating daily life using digital maps, interacting on social networks, or receiving recommendations on e-commerce sites, you interact with a specific data structure behind the scenes. Storing structured data like arrays or linear lists fails when entities have complex, multi-way interconnections.

The dominant problem that any student studying advanced data structures has to face is abandoning sequential thinking and learning non-linear modeling. The answer is to learn about graphs in Python, which is a powerful data structure that shows nodes and their connections in a clean way. This article explains everything in plain, simple English, from basic terminology to complex routing algorithms.

What is a Graph Data Structure in Python?

A graph is a non-linear data structure that maps a finite collection of points called vertices (or nodes) and the connections between them, known as edges. Unlike hierarchical trees, graphs have no fixed root node, no parent-child restrictions, and can form cyclic loops freely.

Graphs serve as the foundational backbone for mapping real-world networks. To help visualize how these components look, consider the table below outlining real-world systems modeled as graphs:

Real-World Application

What the Node Represents

What the Edge Represents

Google Maps

Intersections / Cities / Locations

Roads / Highways

Instagram Network

User Profiles / Accounts

Follower / Following Relations

Logistics & Delivery

Warehouses / Drop points

Shipping routes / Flight paths

Important Terminologies for Graphs in Python

Before writing graph algorithms, you must become familiar with the foundational terms used across technical interviews and text tutorials.

  • Vertices (Nodes): The discrete data points containing values within your network.

  • Edges: The lines or links connecting any two vertices in the system.

  • Adjacency: Two nodes are considered adjacent if they share a direct connecting edge.

  • Path: A continuous sequence of edges that lets you travel from a starting node to a destination node.

  • Degree: The total count of edges connected directly to a specific node.

  • In-Degree / Out-Degree: Used exclusively in directed networks; in-degree counts incoming edges, while out-degree tracks outgoing paths.

Classifying Graph Variants

Graphs can change structural properties depending on the rules applied to their connections. The two primary categories include:

  • Directed vs Undirected: In an undirected network, paths move bidirectionally (like a two-way street). In a directed graph, edges indicate a specific direction (like a one-way street), restricting traversal to the path arrow.

  • Weighted vs Unweighted: Weighted networks assign a numerical value (cost, distance, or time delay) directly to each edge, which is essential for computing optimal pathways.

How to Represent Graphs in Python?

Computers do not naturally know what points and lines look like. These elements need to be translated to structured memory formats for processing a graph configuration in code. In programming there are three common ways to represent graph data structures.

1. Edge List Representation

An edge list stores data as a collection of all individual connections, often grouped as pairs within a simple Python list or set of tuples. While highly intuitive to write out manually, searching an edge list to check if two specific nodes are connected forces your script to look through every single connection row.

2. Adjacency Matrix

An adjacency matrix is a two-dimensional grid of size $V \times V$ (where $V$ is the total number of vertices) that represents connections. It traces relations via explicit boolean indicators.

  • If a row-to-column link exists, the cell displays 1 (or the specific edge weight).

  • If no connection exists between nodes, the cell evaluates to 0 or -1.

An adjacency matrix offers instant lookup times when checking for edges but demands significant memory, making it inefficient for sparse networks.

3. Adjacency List

An adjacency list is an implementation of a collection that has an array index or dictionary key for each node. Each node has a list of all the neighbouring points, the list size is dynamic. It is the standard format for building structural traversal logic and space optimisation.

BFS and DFS Graphs in Python with Examples

To run updates or extract insights from a network, you need a deterministic method to look at every single node exactly once. Graph tracking relies on two core foundational operations: Breadth-First Search and Depth-First Search.

Breadth-First Search (BFS)

BFS traverses networks horizontally layer by layer, starting from an index and expanding from there. It is just like level order traversal of a tree, using a queue data structure (First-In, First-Out) with tracking lookup, to avoid visiting the same item multiple times. For unweighted graphs, BFS guarantees to find the shortest structural distance.

Depth-First Search (DFS)

DFS is a vertical network explorer. It goes deep down one single path until it hits a dead-end, then backtracks. This depth-first strategy is highly dependent on the Stack (Last-In, First-Out) framework or recursive function stacks. The baseline logic for internal graph loop detection and sub-network splitting is DFS.

How is Graphs in Python Used for Problem Solving?

Understanding graph tracking structures allows you to solve classic computer science problems. Two standard pipeline evaluations include structural cycle checks and structural island analysis.

Checking for Structural Cycles

Detecting a cycle determines whether a traversal path can loop back to a previously visited node. When doing recursive DFS over an undirected network, you'll want to check if you've seen a node before, but not the immediate parent node in your current step of execution.

Counting Distinct Connected Components

Real-world networks can be fractured or broken into isolated islands. To find the total number of independent connected components inside a dataset, use this systematic approach:

  1. Initialize a tracked tracking structure holding default False statuses.

  2. Set up an integer counter tracking variable starting at zero.

  3. Loop through every single vertex point in the dataset sequence.

  4. If a vertex displays an unvisited status, trigger a full recursive DFS path sweep across its neighbors, and then increment your component counter by one.

  5. Repeat until all structural components match a true visited status.

What is Dijkstra's Shortest Path Algorithm for Graphs in Python?

When edge lines contain unique structural weights (representing physical distance or time metrics), simple level-order lookups fail to find the most efficient pathways.

Dijkstra’s algorithm calculates the definitive single-source shortest path, locating the absolute lowest cumulative cost to get from one source position to every other node in the network.

Dijkstra’s algorithm uses a greedy paradigm supported by a priority queue (Min-Heap structural sorting) to systematically find paths:

  1. Create a tracking list mapping all node locations to an initial distance of positive infinity, setting your starting source index value directly to 0.

  2. Push your initial source state token (0, source_node) inside the sorting Min-Heap.

  3. Pop the node possessing the absolute lowest cumulative distance value from the heap structure.

  4. Examine all neighbor paths radiating from this current node. Calculate the new tentative edge weight by adding the current path cost to the adjacent link weight.

  5. If this new path calculation is cheaper than the target node's currently recorded minimum cost, update its distance metric and push this updated token configuration into your priority heap.

  6. Repeat these structural updates until the heap evaluates completely empty.

What is Minimum Spanning Trees (MST) in Graphs in Python?

A Minimum Spanning Tree represents a sub-graph selection that successfully links all original nodes together without forming a single cyclic loop, while maintaining the absolute lowest collective edge-weight sum.

Engineers rely heavily on MST tracking principles to design physically optimized cable infrastructure, water networks, and telecommunications routing layouts.

Prim’s Algorithm

Prim’s strategy builds out an MST framework starting from a single node, expanding its path outward dynamically. It actively checks the boundary lines of your active node set and picks the lowest-weight edge that connects a visited node to an unvisited node. This process loops until every node joins the spanning structure.

Kruskal’s Algorithm

Kruskal’s approach builds an MST by focusing on edges rather than nodes. The execution sorts every edge in the entire graph by weight in ascending order. It loops through this sorted collection, adding edges to the MST one by one, skipping any connections that would form a closed cycle.

FAQs

1. Can you run topological sorting on an undirected graph configuration?

No. Topological sorting requires clear directionality to establish a valid linear ordering and is designed strictly for Directed Acyclic Graphs (DAGs).

2. Why does Dijkstra algorithm fail when encountering negative edge weights?

Dijkstra's algorithm uses a greedy approach, assuming that adding an edge will never decrease the total path distance. Negative weights break this logic, requiring alternatives like the Bellman-Ford algorithm instead.

3. What is the standard time complexity for basic graph traversals like BFS and DFS?

Both BFS and DFS have a time complexity of O(V + E), where: V = total number of vertices (nodes) E = total number of edges

4. What is the core difference between a Tree and a Graph data structure?

A tree is a connected graph with no cycles and contains exactly V − 1 edges for V nodes.

5. When should I select an adjacency matrix over an adjacency list?

For dense graphs, where the number of edges is close to V², an adjacency matrix is preferred. For sparse graphs, an adjacency list is better because it uses O(V + E) space.
Popup Close ImagePopup Open Image
Talk to a counsellorHave doubts? Our support team will be happy to assist you!
Popup Image
avatar

Get Free Counselling Today

and Clear up all your Doubts

Talk to Our Counsellor just by filling out the form.
Student Name
Phone Number
IN
+91
OTP
Email Id
Join 15 Million students on the app today!
Point IconLive & recorded classes available at ease
Point IconDashboard for progress tracking
Point IconLakhs of practice questions
Download ButtonDownload Button
Banner Image
Banner Image