| Introduction to Graph Theory
● What’s a graph?
○ A graph is a pictorial representation of a set of objects where some pairs
of objects are connected by links.
● Why do we use graphs?
○ Graphs are mainly used to express and visualize relationships
(connections) between objects.
Examples:
○ Relationships between a group of people.
○ Network of PCs.
○ Roads between cities.
● Graph Components:
○ Any graph has two major components:
■ Nodes (Vertices):
● The objects that we want
to describe a connection
between them.
● Vanya, Alex, Sam and
Jan are considered
nodes.
■ Edges:
● The links that connect nodes.
● Represented by an arrow or a line.
● Presence of an edge between two nodes implies that a
connection exists between them.
● There are three types of edges:
○ Undirected Edge.
○ Directed Edge.
○ Weighted Edge.
● Types of Edges:
Undirected Directed Weighted
Representation Represented by a Represented by an A descriptive
line. arrow. number (cost) is
added on the edge.
Meaning If an undirected If a directed edge -A weight is added
edge connects connects between to the edge to
between node A and node A and node B, describe the cost,
node B, we can go we can go from distance, time, etc,
from node A to node node A to node B, between nodes.
B and vice versa. but not vice versa.
-Can be applied to
both undirected and
directed edges.
Examples
-There is a way from -There is a way from -The travel cost
Cairo to Alex, and Cairo to Alex, but from Cairo to Alex
from Alex to Cairo. not from Alex to is 50.
Cairo.
| Special types of graphs
● Complete Graph
A complete graph is a simple undirected
graph where each pair of vertices is
connected by a unique edge. If the graph is
directed it would be called a complete
digraph.
If a complete graph contains vertices, then
it has edges.
● Tree
A tree is an undirected graph where any two vertices are connected by exactly
one path.
There are some conditions that should be
satisfied for a graph G in-order to be “tree” :
1. G must contain no cycle (acyclic).
2. G would be cyclic if any additional
edge is added to it.
3. G is connected.
4. G contains n-1 edges, where n is the
number of nodes.
● Directed acyclic graph (DAG):
A directed acyclic graph is a directed graph
with no directed cycles. In other words, it is a
graph that consists of vertices and edges,
each edge is directed from one vertex to
another such that following these directed
edges will never form a cycle.
| Graph representation:
Two methods can represent the graph:
1) Adjacency Matrix.
2) Adjacency List.
● Adjacency matrix:
It is a 2D array of size (V x V) where V is the number of the graph’s vertices. Let
the adjacency matrix be graph[Number of vertices][Number of vertices].
1) If graph[node1][node2] = 1 this means that there is an edge between
node1 and node2 .
2) If graph[node1][node2]= 0 this means that there is no edge between
them.
Adjacency matrix for an undirected graph is always symmetric.
We can also use adjacency matrix in representing the weighted graphs where If
graph[node1][node2] = W this means that there is an edge between node1 and node2
with weight W.
● Adjacency list:
An adjacency list represents a graph as an array of lists. The index of the array
represents a vertex and each element in its list represents the other vertices that
form an edge with the vertex.
We can also use adjacency list in representing the weighted graphs.
● Adjacency matrix VS Adjacency list:
Adjacency matrix Adjacency list
Space complexity
Searching for an edge You will just check if You have to iterate over
graph[node1][node2]=1 all the components of
or not so it takes O(1) graph[node] so it takes
O(|E|)
Visiting all edges
Efficiency for dense Efficient Not efficient
graphs
Efficiency for sparse Not efficient Efficient
graphs
| Depth First Search (DFS):
The DFS is a recursive algorithm that uses the idea of backtracking. It goes as
deep into the graph as possible and backtracks once there are no unvisited
vertices left.
How does it work?
First, we choose a vertex to start from it, then the steps go:
● Mark the current vertex as visited.
● Search for an unvisited vertex from its neighbors.
● If we didn’t find any unvisited vertex from its neighbors, we backtrack.
Otherwise, we perform DFS from this vertex and repeat the same steps
we did above.
This way, we visit all vertices that are reachable from the starting vertex.
Time Complexity: where V is the number of vertices and E is the
number of edges.
You can find the implementation here: Graphs Cheat Sheet
| Breadth-First Search (BFS):
BFS is a traversing algorithm where you should traverse the graph as levels
where you move horizontally and visit all the nodes of the current level, then you
move to the next layer and so on.
How does it work?
First, we choose a vertex to start from, add it to a queue, and mark it as a visited
vertex. Note that the starting vertex is in level 0.
The BFS steps go:
● Every time our current vertex will be at the front of the queue, search for
an unvisited vertex from its neighbors.
● If we didn’t find any unvisited neighbor, we do nothing otherwise; we mark
it as a visited vertex, then we add it to the queue. (this step is repeated till
all the unvisited neighbors are added to the queue)
● The new vertex added to the queue is at the next level of the current
vertex, so its level will be the current vertex level incremented by 1.
● Pop the queue’s front and repeat the same steps we did above until the
queue becomes empty.
Time Complexity: where V is the number of vertices and E is the
number of edges.
You can find the implementation here: Graphs Cheat Sheet