Algorithm CH 7graph
Algorithm CH 7graph
Graph
A graph is a mathematical structure consisting of a set of vertices and a set of edges connecting
the vertices.
Most of the graph algorithms presented in this lesson assume that an input graph is represented in
adjacency list form. We may prefer an adjacency-matrix representation, however, when the
graph is dense, |E| is close to |V |2 or when we need to be able to tell quickly if there is an edge
connecting two given vertices.
Figure 1Two representations of an undirected graph. (a) An undirected graph G with 5 vertices
and 7 edges. (b) An adjacency-list representation of G. (c) The adjacency-matrix representation
of G.
Figure 2 Two representations of a directed graph. (a) A directed graph G with 6 vertices and 8
edges. (b) An adjacency-list representation of G. (c) The adjacency-matrix representation of G.
A directed graph:
E = {(0, 2), (0, 4), (0, 5), (1, 0), (2, 1), (2, 5), (3, 1), (3, 6), (4, 0), (4, 5), (6, 3), (6, 5)}
Examples:
Computer Networks, Vertices represent computers and edges represent network connections
(cables) between them.
For example:
we might be using a graph to represent a computer network (such as the Internet), and we
might be interested in finding the fastest way to route a data packet between two
computers.
The World Wide Web. Vertices represent web pages, and edges represent hyperlinks.
Flowcharts. Vertices represent boxes and edges represent arrows.
Weighted Graph
A weighted graph is a graph that has a numerical level associated with each edge e, called the
weight of edge e.
Edge weights can be integers, rational numbers, or real numbers, which represent a concept such
as distance, connection costs.
Unweighted Graph
An unweighted graph is a graph that has not a numerical level associated with each edge e.
Breadth-first search is one of the simplest algorithms for searching a graph and the archetype for
many important graph algorithms.
Given a graph G = (V, E) and a distinguished source vertex s, breadth-first search systematically
explores the edges of G to “discover” every vertex that is reachable from s. It computes the
distance (smallest number of edges) from s to each reachable vertex. It also produces a “breadth-
first tree” with root s that contains all reachable vertices.
For any vertex v reachable from s, the simple path in the breadth-first tree from s to v
corresponds to a “shortest path” from s to v in G, that is, a path containing the smallest number
of edges.
With the exception of the source vertex s, lines 1–4 paint every vertex white,
The while loop of lines 10–18 iterates as long as there remain gray vertices, which are
discovered vertices that have not yet had their adjacency lists fully examined.
At the test in line 10, the queue Q consists of the set of gray vertices.
Line 11 determines the gray vertex u at the head of the queue Q and removes it from Q.
The for loop of lines 12–17 considers each vertex v in the adjacency list of u. If v is white, then it
has not yet been discovered, and the procedure discovers it by executing lines 14–17.
The procedure paints vertex v gray, sets its distance v.d to u.d +1, records u as its parent v.ᴫ, and
places it at the tail of the queue Q.
Once the procedure has examined all the vertices on u’s adjacency list, it blackens u in line 18.
The loop invariant is maintained because whenever a vertex is painted gray (in line 14) it is also
enqueued (in line 17), and whenever a vertex is dequeued (in line 11) it is also painted black (in
line 18). The results of breadth-first search may depend upon the order in which the neighbors of
a given vertex are visited in line 12: the breadth-first tree may vary, but the distances d computed
by the algorithm will not.
Analysis
Now, we take on the somewhat easier job of analyzing its running time on an input graph G =
(V, E). We use aggregate analysis, as we saw. After initialization, breadth-first search never
whitens a vertex, and thus the test in line 13 ensures that each vertex is enqueued at most once
and hence dequeued at most once. The operations of enqueuing and dequeuing take O(1) time,
and so the total time devoted to queue operations is O(V ). Because the procedure scans the
adjacency list of each vertex only when the vertex is dequeued, it scans each adjacency list at
most once. Since the sum of the lengths of all the adjacency lists is θ(E), the total time spent in
scanning adjacency lists is O(E). The overhead for initialization is O(V), and thus the total
running time of the BFS procedure is O(V +E). Thus, breadth-first search runs in time linear in
the size of the adjacency-list representation of G.
2. using namespace std;
3. #define MAX_NODE 50
4. struct node
5. {
6. int vertex;
7. node *next;
8. };
14. {
16. createGraph();
18. BFS_traversal();
19.
20. return 0;
21. }
r = r+1;
queue[r]=item;
if(f==-1)
f=0;
int delitem=queue[f];
if(f==r)
f=r=-1;
else f=f+1;
return(delitem);
if(f==-1)
return(1);
else
return(0);
1. void createGraph()
2. {
3. node *newl,*last;
4. int neighbours,neighbour_value;
5. cout << "\n\n---Graph Creation---\n\n";
7. cin>>totNodes;
9. {
10. last=NULL;
12. cin>>neighbours;
17. newl->vertex=neighbour_value;
18. newl->next=NULL;
19. if(adj[i]==NULL)
20. adj[i]=last=newl;
21. else
22. {
25. }
26. }
27. }
28. }
2. {
3. node *tmp;
7. cin>>start_node;
11. //step 2 : put the start node in queue and change status.
12. q_insert(start_node); //Put starting node into queue.
15. while(is_q_empty() != 1)
16. {
24. //that are in ready state and change their status to wait state.
28. {
29. v = tmp->vertex;
31. {
35. }
37. }
38. }
39. }
Chapter Eight: Topic Fourteen
Depth first search
The strategy followed by depth-first search is, as its name implies, to search "deeper" in the
graph whenever possible.
Depth-first search explores edges out of the most recently discovered vertex v that still has
unexplored edges leaving it.
Once all of v's edges have been explored, the search "backtracks" to explore edges leaving the
vertex from which v was discovered.
This process continues until we have discovered all the vertices that are reachable from the
original source vertex.
If any undiscovered vertices remain, then depth-first search selects one of them as a new source,
and it repeats the search from that source.
The algorithm repeats this entire process until it has discovered every vertex.
As in breadth-first search, whenever depth-first search discovers a vertex v during a scan of the
adjacency list of an already discovered vertex u, it records this event by setting v's predecessor
attribute v.π to u.
Unlike breadth-first search, whose predecessor subgraph forms a tree, the predecessor subgraph
produced by a depth-first search may be composed of several trees, because the search may
repeat from multiple sources.
Therefore, we define the predecessor subgraph of a depth-first search slightly differently from
that of a breadth-first search
The predecessor subgraph of a depth-first search forms a depth-first forest comprising several
depth-first trees.
As in breadth-first search, depth-first search colors vertices during the search to indicate their
state.
Each vertex is initially white, is grayed when it is discovered in the search, and is blackened
when it is finished, that is, when its adjacency list has been examined completely.
This technique guarantees that each vertex ends up in exactly one depth-first tree, so that these
trees are disjoint.
Besides creating a depth-first forest, depth-first search also timestamps each vertex. Each vertex
v has two timestamps: the first timestamp v.d records when v is first discovered (and grayed),
and the second timestamp v.f records when the search finishes examining v's adjacency list (and
blackens v).
These timestamps provide important information about the structure of the graph and are
generally helpful in reasoning about the behavior of depth-first search.
The procedure DFS below records when it discovers vertex u in the attribute u:d and when it
finishes vertex u in the attribute u:f . These timestamps are integers between 1 and 2 |V|, since
there is one discovery event and one finishing event for each of the |V | vertices. For every vertex
u, u.d < u.f Vertex u is WHITE before time u.d, GRAY between time u.d and time u.f, and
BLACK thereafter.
1. #include <iostream>
2. using namespace std;
3. #define MAX_NODE 50
4. struct node{
5. int vertex;
6. node *next;
7. };
10.
12. int top=-1;
13. int stack[MAX_NODE];
14.
15. int main()
16. {
20. DFS_traversal();
21.
22. return 0;
23. }
1. void push(int item)
2. {
3. top=top+1;
4. stack[top]=item;
5. }
1. int pop()
2. {
3. int deldata=stack[top];
4. top=top-1;
5. return(deldata);
6. }
1. int is_stk_empty()
2. {
3. if(top==-1)
4. return(1);
5. else
6. return(0);
7. }
1. ////////////Stack Operation\\\\\\\\\\\\\
2. void createGraph()
3. {
4. node *newl,*last;
5. int neighbours, neighbour_value;
6. cout <<"\n\n---Graph Creation---\n\n";
8. cin>>totNodes;
10. {
11. last=NULL;
14. cin>>neighbours;
15. for(int j=1;j<=neighbours;j++)
16. {
18. cin>>neighbour_value;
20. newl->vertex=neighbour_value;
21. newl->next=NULL;
22. if(adj[i]==NULL)
23. adj[i]=last=newl;
24. else{
25. last->next = newl;
27. }
28. }
29. }
30. }
1. void DFS_traversal()
2. {
3. node *tmp;
7. cin>>start_node;
11. //step 2 : push the start node in stack and change status.
15. while(is_stk_empty()!=1){
26. while(tmp!=NULL)
27. {
28. v = tmp->vertex;
29. if(status[v]==ready)
30. {
34. }
35. tmp=tmp->next;
36. }
37. }
}
The figure in the next section illustrates the progress of DFS on the graph shown in Figure
depicted before. Procedure DFS works as follows. Lines 1–3 paint all vertices white and
initialize their ᴫ attributes to NIL. Line 4 resets the global time counter. Lines 5–7 check each
vertex in V in turn and, when a white vertex is found, visit it using DFS-VISIT. Every time DFS-
VISIT (G, u) is called in line 7, vertex u becomes the root of a new tree in the depth-first forest.
When DFS returns, every vertex u has been assigned a discovery time u.d and a finishing time
u.f. In each call DFS-VISIT(G,u), vertex u is initially white. Line 1 increments the global
variable time, line 2 records the new value of time as the discovery time u.d, and line 3 paints u
gray. Lines 4–7 examine each vertex v adjacent to u and recursively visit v if it is white. As each
vertex vε Adj[u]is considered in line 4, we say that edge (u,v) is explored by the depth-first
search.
Finally, after every edge leaving u has been explored, lines 8–10 paint u black, increment time,
and record the finishing time in u.f. Note that the results of depth-first search may depend upon
the order in which line 5 of DFS examines the vertices and upon the order in which line 4 of
DFSVISIT visits the neighbors of a vertex.
These different visitation orders tend not to cause problems in practice, as we can usually use
any depth-first search result effectively, with essentially equivalent results.
Figure The progress of the depth-first-search algorithm DFS on a directed graph. As edges are
explored by the algorithm, they are shown as either shaded (if they are tree edges) or dashed
(otherwise). Nontree edges are labeled B, C, or F according to whether they are back, cross, or
forward edges. Timestamps within vertices indicate discovery time/finishing times. Analysis
What is the running time of DFS? The loops on lines 1–3 and lines 5–7 of DFS take time θ(V ),
exclusive of the time to execute the calls to DFS-VISIT. As we did for breadth-first search, we
use aggregate analysis. The procedure DFS-VISIT is called exactly once for each vertex vε V ,
since the vertex u on which DFS-VISIT is invoked must be white and the first thing DFS-VISIT
does is paint vertex u gray. During an execution of DFS-VISIT(G,v), the loop on lines 4–7
executes |Adj[v]| times.
Since