Introduction to Graph Data Structure

What is a Graph?

A graph is a non-linear data structure that consists of a set of vertices (or nodes) and a set of edges (or arcs) that connect pairs of vertices. Graphs are used to represent networks of connected objects, such as computer networks, social networks, transportation systems, and many other real-world systems.

Representation of a Graph Data Structure

plaintext

Graph G:
Vertices: {A, B, C, D, E}
Edges: {(A, B), (A, C), (B, D), (C, D), (D, E)}

    A
   / \
  B   C
   \ /
    D
    |
    E

In the above graph:

  • Vertices: A, B, C, D, E
  • Edges: (A, B), (A, C), (B, D), (C, D), (D, E)

Types of Graphs

  1. Undirected Graph: A graph in which edges have no direction. The edge (A, B) is the same as the edge (B, A).
  2. Directed Graph (Digraph): A graph in which edges have a direction. The edge (A, B) is different from the edge (B, A).
  3. Weighted Graph: A graph in which edges have weights (or costs) associated with them.
  4. Unweighted Graph: A graph in which edges do not have weights.
  5. Connected Graph: A graph in which there is a path between every pair of vertices.
  6. Disconnected Graph: A graph in which some vertices are not connected by a path.
  7. Cyclic Graph: A graph that contains at least one cycle (a path that starts and ends at the same vertex).
  8. Acyclic Graph: A graph that does not contain any cycles.
  9. Complete Graph: A graph in which there is an edge between every pair of vertices.

Key Operations on Graphs

  1. Traversal: Visiting all the vertices in the graph.
    • Breadth-First Search (BFS): Visits vertices level by level.
    • Depth-First Search (DFS): Visits vertices by going as deep as possible along each branch before backtracking.
  2. Shortest Path: Finding the shortest path between two vertices.
    • Dijkstra's Algorithm: Finds the shortest path in a weighted graph with non-negative weights.
    • Bellman-Ford Algorithm: Finds the shortest path in a graph with negative weights.
  3. Minimum Spanning Tree (MST): Finding a subset of edges that connects all vertices with the minimum total edge weight.
    • Kruskal's Algorithm: Finds the MST by sorting edges by weight and adding them one by one.
    • Prim's Algorithm: Finds the MST by growing a single tree from an initial vertex.
  4. Connectivity: Checking if the graph is connected or finding connected components.

Here are some basic implementations of a graph in C++, Java, and Python without using classes.

C++ Program to implement Graph

cpp
#include <iostream>
#include <vector>
using namespace std;

void addEdge(vector<int> adj[], int u, int v) {
    adj[u].push_back(v); // Add v to u's list
    adj[v].push_back(u); // Add u to v's list (for undirected graph)
}

void printGraph(vector<int> adj[], int V) {
    for (int v = 0; v < V; ++v) {
        cout << "Adjacency list of vertex " << v << "\n head ";
        for (auto x : adj[v])
           cout << "-> " << x;
        printf("\n");
    }
}

int main() {
    int V = 5;
    vector<int> adj[V];
    
    addEdge(adj, 0, 1);
    addEdge(adj, 0, 4);
    addEdge(adj, 1, 2);
    addEdge(adj, 1, 3);
    addEdge(adj, 1, 4);
    addEdge(adj, 2, 3);
    addEdge(adj, 3, 4);

    printGraph(adj, V);

    return 0;
}

Java Program to implement Graph

java
import java.util.LinkedList;

public class Main {
    private int V; // Number of vertices
    private LinkedList<Integer> adj[]; // Adjacency lists

    // Constructor
    Main(int v) {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; ++i)
            adj[i] = new LinkedList();
    }

    // Function to add an edge into the graph
    void addEdge(int v, int w) {
        adj[v].add(w); // Add w to v's list
        adj[w].add(v); // Add v to w's list (for undirected graph)
    }

    // Function to print the graph
    void printGraph() {
        for (int v = 0; v < V; ++v) {
            System.out.println("Adjacency list of vertex " + v);
            System.out.print("head");
            for (Integer pCrawl : adj[v]) {
                System.out.print(" -> " + pCrawl);
            }
            System.out.println("\n");
        }
    }

    public static void main(String args[]) {
        Main g = new Main(5);

        g.addEdge(0, 1);
        g.addEdge(0, 4);
        g.addEdge(1, 2);
        g.addEdge(1, 3);
        g.addEdge(1, 4);
        g.addEdge(2, 3);
        g.addEdge(3, 4);

        g.printGraph();
    }
}

Python Program to implement Graph

python
from collections import defaultdict

# Function to add an edge to the graph
def add_edge(graph, u, v):
    graph[u].append(v)
    graph[v].append(u)  # For undirected graph

# Function to print the graph
def print_graph(graph):
    for node in graph:
        print(f"Adjacency list of vertex {node}\n head", end="")
        for neighbor in graph[node]:
            print(f" -> {neighbor}", end="")
        print("\n")

# Main function
if __name__ == "__main__":
    graph = defaultdict(list)

    add_edge(graph, 0, 1)
    add_edge(graph, 0, 4)
    add_edge(graph, 1, 2)
    add_edge(graph, 1, 3)
    add_edge(graph, 1, 4)
    add_edge(graph, 2, 3)
    add_edge(graph, 3, 4)

    print_graph(graph)

Advantages of Graphs

  1. Model Real-World Systems: Graphs can model complex relationships and networks.
  2. Flexibility: Can represent various types of data and relationships.

Disadvantages of Graphs

  1. Complex Implementation: More complex to implement and manage compared to linear data structures.
  2. Memory Overhead: Requires additional memory for storing edges and vertices.

When to Use Graphs

Graphs are preferred when:

  • You need to model relationships or networks.
  • You need to perform searches, find paths, or manage connections between objects.
  • You need to solve problems like shortest path, network flow, or connectivity.

Practice Problems on Graphs

  1. Find the Shortest Path in an Unweighted Graph
    • Problem: Given an unweighted graph and a source vertex, find the shortest path from the source to all vertices using BFS.
    • Example: Input: Graph with edges [(0, 1), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (3, 4)], source = 0, Output: [0, 1, 1, 2, 1]
  2. Check if a Graph is Bipartite
    • Problem: Determine if a given graph is bipartite using BFS or DFS.
    • Example: Input: Graph with edges [(0, 1), (0, 3), (1, 2), (2, 3)], Output: True
  3. Detect a Cycle in an Undirected Graph
    • Problem: Detect if there is a cycle in an undirected graph using DFS.
    • Example: Input: Graph with edges [(0, 1), (1, 2), (2, 0), (1, 3)], Output: True
  4. Topological Sort
    • Problem: Perform a topological sort on a directed acyclic graph (DAG) using DFS.
    • Example: Input: Graph with edges [(5, 2), (5, 0), (4, 0), (4, 1), (2, 3), (3, 1)], Output: [5, 4, 2, 3, 1, 0]
  5. Find Bridges in a Graph
    • Problem: Find all the bridges in an undirected graph using DFS.
    • Example: Input: Graph with edges [(0, 1), (1, 2), (2, 3), (3, 4), (2, 5), (5, 6)], Output: [(3, 4), (2, 3)]

Frequently Asked Questions (FAQs) on Graphs

Q1: What is the difference between a graph and a tree?

  • A: A tree is a special type of graph that is connected and acyclic. In contrast, a graph can have cycles and does not need to be connected.

Q2: How is memory managed for graphs?

  • A: In most programming languages, graphs are managed by dynamically allocating memory for vertices and edges using adjacency lists or matrices.

Q3: Can graphs be directed or undirected?

  • A: Yes, graphs can be either directed (edges have a direction) or undirected (edges do not have a direction).

Q4: What are some common applications of graphs?

  • A: Common applications include social networks, computer networks, transportation systems, and algorithms like shortest path and network flow.

Q5: How do you traverse a graph?

  • A: Graph traversal can be done using algorithms like Breadth-First Search (BFS) and Depth-First Search (DFS).

Q6: What is the difference between an adjacency list and an adjacency matrix?

  • A: An adjacency list represents a graph using lists to store neighbors for each vertex, while an adjacency matrix uses a 2D array to represent connections between vertices.

Q7: What is a connected graph?

  • A: A connected graph is a graph in which there is a path between every pair of vertices.

DSA

4847

457

Related Articles