https://faroukibrahim-fii.github.io/reading-notes/
A graph is a non-linear data structure that can be looked at as a collection of vertices (or nodes) potentially connected by line segments named edges.
Here is some common terminology used when working with Graphs:
An Undirected Graph is a graph where each edge is undirected or bi-directional. This means that the undirected graph does not move in any direction.
A Directed Graph also called a Digraph is a graph where every edge is directed.
Unlike an undirected graph, a Digraph has direction. Each node is directed at another node with a specific requirement of what node should be referenced next.
There are many different types of graphs. This depends on how connected the graphs are to other node/vertices.
A complete graph is when all nodes are connected to all other nodes.
A connected graph is graph that has all of vertices/nodes have at least one edge.
A disconnected graph is a graph where some vertices may not have edges.
In addition to undirected and directed graphs, we also have acyclic and cyclic graphs.
An acyclic graph is a directed graph without cycles.
A cycle is when a node can be traversed through and potentially end up back at itself.
A Cyclic graph is a graph that has cycles.
A cycle is defined as a path of a positive length that starts and ends at the same vertex.
We represent graphs through:
An Adjacency matrix is represented through a 2-dimensional array. If there are n vertices, then we are looking at an n x n Boolean matrix
An adjacency list is the most common way to represent graphs.
An adjacency list is a collection of linked lists or array that lists all of the other vertices that are connected.
Thinking about how we will implement this in code? Well, let’s look at what the visual is telling us.
A weighted graph is a graph with numbers assigned to its edges. These numbers are called weights. This is what a weighted graph looks like:
You will be required to traverse through a graph. The traversals itself are like those of trees. Below is a breakdown of how you would traverse a graph.
In a breadth first traversal, you are starting at a specific vertex/node. This node must be specified when calling the BreadthFirst() method. The breadth-first traversal of a graph is like that of a tree, with the exception that graphs can have cycles. Traversing a graph that has cycles will result in an infinite loop….this is bad. To prevent such behavior, we need to have some way to keep track of whether a vertex has been “visited” before. Upon each visit, we’ll add the previously-unvisited vertex to a visited set, so we know not to visit it again as traversal continues.
Here is what the algorithm breadth first traversal looks like:
ALGORITHM BreadthFirst(vertex)
DECLARE nodes <-- new List()
DECLARE breadth <-- new Queue()
DECLARE visited <-- new Set()
breadth.Enqueue(vertex)
visited.Add(vertex)
while (breadth is not empty)
DECLARE front <-- breadth.Dequeue()
nodes.Add(front)
for each child in front.Children
if(child is not visited)
visited.Add(child)
breadth.Enqueue(child)
return nodes;
In a depth first traversal, we approach it a bit different than the way we do when working with a depth first traversal of a tree. Similar to how the breadth-first uses a queue, we are going to use a Stack for our depth-first traversal.
The algorithm for a depth first traversal is as follows:
Graphs are extremely popular when it comes to it’s uses. Here are just a few examples of graphs in use: