====== 3.3Implementing Graph Traversal Using Queues and Stacks ======
A graph can be represented as either an //adjacency matrix// or an //adjacency list//. with a graph G = (V,E), the number of nodes |V| is denoted as **//n//** and the number of edges |E| is denoted as **//m//**. When discussing the representations of graphs, our aim is to get a representation that allows us to implement the graph in a polynomial running time. The number of edges //m// is always less than or equal to n2. Since most of graphs are connected, the graphs considered in the discussion of the representation of graphs have at least m≥ n-1 edges. The goal we have in the implementation of graphs is O(m+n), and is called linear time.\\
\\
\\
**Some Definitions**:
* //Adjacency matrix//: it's an //n X n// matrix A where A[u,v] is equal to 1 if the graph contains the edge (u,v), and 0 otherwise. This representation allows us to represent graphs in O(1) time if a the edge (u,v) is in the graph.
* Disadvantages:
* The representation takes Θ(n2) space.However, when the graph has many fewer edges than n2, more compact (and better) representations are possible
* Many graph algorithms need to examine all edges incident to a given node v. With the adjacency matrix, this operation takes Θ(n) time. More efficient algorithms exist solve this problem.
* //Adjacency list//: With this representation, there is record for each node v, containing a list of the nodes to which v has edges. It used when the graphs have less than n2 edges.
* With this representation we have an array Adj, where Adj[v] contains a record of all nodes adjacent to the node v.
* Comparison of the Adjacency list and the Adjacency matrix:
* Since an Adjacency matrix requires an n X n matrix, it is O(n2) space
* An Adjacency list takes O(m+n) space.
* In the Adjacency list, it takes O(//nv//) time to check if a particular edge (u,v) is in the graph, while the same operation takes O(1) time for an adjacency matrix.
* The degree //nv// of a node v is the number of incident edges it has.
* The length of the list at Adj[v] is //nv//
* The sum of the degrees in a graph = **//2m//**
=== Queues and Stacks===
* With A queue, we use the First in, First Out(FIFO) concept
* The new element is added to the end of the list
* For a stack, we use the Last in, First Out(LIFO) concept
* The new element is added at the front of the list
* In both implementations, the doubly linked lists used maintain a FIRST and a LAST pointers which allows constant time insertions
==Implementation and analysis of the BFS and the DFS ==
* BFS: \\
BFS(s):\\
Discovered[v] = false, for all v\\
Discovered[s] = true\\
L[0] = {s}\\
layer counter i = 0\\
BFS tree T = {}\\
while L[i] != {}\\
>>>>>L[i+1] = {}
>>>>>For each node u ∈ L[i]
>>>>>>>>>Consider each edge (u,v) incident to u
>>>>>>>>>if Discovered[v] == false then
>>>>>>>>>>>>>>Discovered[v] = true
>>>>>>>>>>>>>>Add edge (u, v) to tree T
>>>>>>>>>>>>>>Add v to the list L[i + 1]
>>>>>>>>>>Endif
>>>>>Endfor
end while
This implementation of the BFS takes O(m+n) if the graph is given by the adjacency list representation.\\
* DFS:\\
DFS(s):\\
Initialize S to be a stack with one element s\\
Explored[v] = false, for all v\\
Parent[v] = 0, for all v \\
DFS tree T = {} \\
while S != {}\\
>>>>>>Take a node u from S
>>>>>>if Explored[u] = false
>>>>>>>>>>>Explored[u] = true
>>>>>>>>>>>Add edge (u, Parent[u]) to T (if u ≠ s)
>>>>>>>>>>>for each edge (u, v) incident to u
>>>>>>>>>>>>>>>>Add v to the stack S
>>>>>>>>>>>>>>>>Parent[v] = u
>>>>>>>>>>>Endfor
>>>>>>Endif
end while
This implementation of the DFS takes O(m+n) if the graph is given by the adjacency list representation.\\
Thus when using a DFS or a BFS, one can easily implement graph traversals in linear time(O(m+n)).\\
This section was interesting too, I give it an 8/10.