0% found this document useful (0 votes)
3 views

Algorithm CH 7graph

Uploaded by

tamirat birhanu
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Algorithm CH 7graph

Uploaded by

tamirat birhanu
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 21

Chapter Eight: Topic One

Graph
A graph is a mathematical structure consisting of a set of vertices and a set of edges connecting
the vertices.

Formally: G = (V,E), where V is a set and E is subset of V X V .

We can choose between two standard ways to represent a graph G = (V,E):

 as a collection of adjacency lists or


 as an adjacency matrix.

Either way applies to both directed and undirected graphs.

Because the adjacency-list representation provides a compact way to represent sparse graphs,


those for which |E| is much less than |V|2, it is usually the method of choice.

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.

For example, two of the all-pairs:

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.

Chapter Eight: Topic Two


Directed and Undirected Graph
G = (V,E) undirected if for all v,w € V : (v,w) € E < == > (w, v) € E. Otherwise directed.

A directed graph:

G = (V,E) with vertex set V = {0,1,2,3,4,5, 6} and edge set.

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)}

Figure 3. directed graph


Figure 4. An undirected graph

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.

Example of adjacency matrix data structure


Examples of the adjacency list data structure Array with one entry for each vertex v, which is a
list of all vertices adjacent to v.

Chapter Eight: Topic Three


Sparse and dense graphs

Chapter Eight: Topic Four


Weighted Graph and Unweighted Graph

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.

Chapter Eight: Topic Five


Breadth-first search

Breadth-first search is one of the simplest algorithms for searching a graph and the archetype for
many important graph algorithms.

Prim’s minimum-spanning tree algorithm and Dijkstra’s single-source shortest-paths algorithm


use ideas similar to those in breadth-first search.

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.

Example of Breadth first search

Chapter Eight: Topic Six


The algorithm works on both directed and undirected graphs
The procedure BFS works as follows:

With the exception of the source vertex s, lines 1–4 paint every vertex white,

set u.d to be infinity for each vertex u, and

set the parent of every vertex to be NIL.

Line 5 paints s gray, since we consider it to be discovered as the procedure begins.

Line 6 initializes s.d to 0, and

line 7 sets the predecessor of the source to be NIL.

Lines 8–9 initialize Q to the queue containing just the vertex s.

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.

This while loop maintains the following invariant:

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.

Chapter Eight: Topic Seven


Shortest paths
At the beginning of this section, we claimed that breadth-first search finds the distance to each
reachable vertex in a graph G = (V, E) from a given source vertex s ε V. Define the shortest-path
distance σ (s, v) from s to v as the minimum number of edges in any path from vertex s to vertex
v if there is no path from s to v, then σ (s, v) = infinity. We call a path of length σ (s, v) from s to
v a shortest path from s to v. Before showing that breadth-first search correctly computes shortest
path distances, we investigate an important property of shortest-path distances.
Chapter Eight: Topic Eight
Implementation of Breadth-first search
1. #include <iostream>

2. using namespace std;

3. #define MAX_NODE 50

4. struct node

5. {

6. int vertex;

7. node *next;

8. };

9. node *adj[MAX_NODE]; //For storing Adjacency list of nodes.

10. int totNodes; //No. of Nodes in Graph.

11. ////////////Queue Operation\\\\\\\\\\\\\

12. int queue[MAX_NODE], f=-1, r=-1;


13. int main()

14. {

15. cout << "*****Breadth First Search Traversal*****\n";

16. createGraph();

17. cout << "\n===BFS traversal is as under===\n";

18. BFS_traversal();

19.

20. return 0;

21. }

Chapter Eight: Topic Nine


Enqueue an Item into a graph of the BFS
void q_insert(int item)

r = r+1;

queue[r]=item;

if(f==-1)

f=0;

Chapter Eight: Topic Ten


Dequeue an item from the graph of BFS
int q_delete()

int delitem=queue[f];

if(f==r)

f=r=-1;

else f=f+1;
return(delitem);

Chapter Eight: Topic Eleven


Check if the graph of BFS has no any element
int is_q_empty()

if(f==-1)

return(1);

else

return(0);

Chapter Eight: Topic Twelve


Create a graph BFS
////////////Queue Operation\\\\\\\\\\\\\

1. void createGraph()

2. {

3. node *newl,*last;

4. int neighbours,neighbour_value;

5. cout << "\n\n---Graph Creation---\n\n";

6. cout << "Enter total nodes in graph : ";

7. cin>>totNodes;

8. for(int i=1; i<=totNodes; i++)

9. {

10. last=NULL;

11. cout << "\nEnter no. of nodes in the adjacency list of node\n";

12. cin>>neighbours;

13. for(int j=1; j<=neighbours; j++)


14. {

15. cout << "Enter neighbour #" << j << " : ";

16. cin>>neighbour_value; newl=new node;

17. newl->vertex=neighbour_value;

18. newl->next=NULL;

19. if(adj[i]==NULL)

20. adj[i]=last=newl;

21. else

22. {

23. last->next = newl;

24. last = newl;

25. }

26. }

27. }

28. }

Chapter Eight: Topic Thirteen


Traversing the graph of a breadth first search
1. void BFS_traversal()

2. {

3. node *tmp;

4. int N, v, start_node, status[MAX_NODE];//status arr for maintaing status.

5. const int white=1, gray=2, black=3; //status of node.

6. cout << "Enter starting node : ";

7. cin>>start_node;

8. //step 1 : Initialize all nodes to ready state.

9. for(int i=1; i <= totNodes; i++)

10. status[i] = white;

11. //step 2 : put the start node in queue and change status.
12. q_insert(start_node); //Put starting node into queue.

13. status[start_node] = gray; //change it status to wait state.

14. //step 3 : Repeat until queue is empty.

15. while(is_q_empty() != 1)

16. {

17. //step 4 : Remove the front node N of queue.

18. //process N and change the status of N to

19. //be processed state.

20. N = q_delete(); //remove front node of queue.

21. status[N] = black; //status of N to processed.

22. cout << " " << N; //displaying processed node.

23. //step 5 : Add to rear of queue all the neighbours of N,

24. //that are in ready state and change their status to wait state.

25. tmp = adj[N];

26. //for status updation.

27. while(tmp != NULL)

28. {

29. v = tmp->vertex;

30. if(status[v] == white)

31. {

32. //check status of N's neighbour.

33. q_insert(v); //insert N's neighbour who are in ready state.

34. status[v] = gray; //and make their status to wait state.

35. }

36. tmp = tmp->next;

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.

Chapter Eight: Topic Fifteen


pseudocode of depth-first-search algorithm
The following pseudocode is the basic depth-first-search algorithm. The input graph G may be
undirected or directed. The variable time is a global variable that we use for timestamping.

Chapter Eight: Topic Sixteen


Implementation of Depth First Search Algorithm

1. #include <iostream>

2. using namespace std;

3. #define MAX_NODE 50

4. struct node{

5. int vertex;

6. node *next;

7. };

8. node *adj[MAX_NODE]; //For storing Adjacency list of nodes.

9. int totNodes; //No. of Nodes in Graph.

10.

11. ////////////Stack Operation\\\\\\\\\\\\\

12. int top=-1;

13. int stack[MAX_NODE];

14.

15. int main()

16. {

17. cout <<"*****Depth First Search Traversal*****\n";


18. createGraph();

19. cout <<"\n===DFS traversal is as under===\n";

20. DFS_traversal();

21.

22. return 0;

23. }

Chapter Eight: Topic Seventeen


Pushing an Item into a graph of the DFS

1. void push(int item)

2. {

3. top=top+1;

4. stack[top]=item;

5. }

Chapter Eight: Topic Eighteen


Popping an item from the graph of DFS

1. int pop()

2. {

3. int deldata=stack[top];

4. top=top-1;

5. return(deldata);

6. }

Chapter Eight: Topic Nineteen


Check if the Graph of a Depth First Search is Empty

1. int is_stk_empty()

2. {

3. if(top==-1)

4. return(1);

5. else
6. return(0);

7. }

Chapter Eight: Topic Twenty


Creating a Depth First Search Graph

1. ////////////Stack Operation\\\\\\\\\\\\\

2. void createGraph()

3. {

4. node *newl,*last;

5. int neighbours, neighbour_value;

6. cout <<"\n\n---Graph Creation---\n\n";

7. cout <<"Enter total nodes in graph : ";

8. cin>>totNodes;

9. for(inti=1; i<=totNodes; i++)

10. {

11. last=NULL;

12. cout <<"\nEnter no. of nodes in the adjacency list of node "<<i<<"\n";</i<<

13. cout <<"--> That is Total Neighbours of "<<i<<" : ";</i<<

14. cin>>neighbours;

15. for(int j=1;j<=neighbours;j++)

16. {

17. cout <<"Enter neighbour #"<<j<<" : ";</j<<

18. cin>>neighbour_value;

19. newl=new node;

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;

26. last = newl;

27. }

28. }

29. }

30. }

Chapter Eight: Topic Twenty One


Traversing in a Graph of Depth First Search

1. void DFS_traversal()

2. {

3. node *tmp;

4. int N, v, start_node, status[MAX_NODE];//status arr for maintaing status.

5. const int ready=1, wait=2, processed=3; //status of node.

6. cout <<"Enter starting node : ";

7. cin>>start_node;

8. //step 1 : Initialize all nodes to ready state.

9. for(int i=1; i <= totNodes; i++)

10. status[i] = ready;

11. //step 2 : push the start node in stack and change status.

12. push(start_node); //Push starting node into stack.

13. status[start_node]=wait; //change it status to wait state.

14. //step 3 : Repeat until stack is empty.

15. while(is_stk_empty()!=1){

16. //step 4 : pop the node N of stack.

17. //process N and change the status of N to //be processed state.

18. N = pop(); //pop the node from stack.

19. status[N]=processed; //status of N to processed.

20. cout << " " << N; //displaying processed node.


21.

22. //step 5 : push onto stack all the neighbours of N,

23. //that are in ready state and change their status to

24. //wait state.

25. tmp = adj[N]; //for status updation.

26. while(tmp!=NULL)

27. {

28. v = tmp->vertex;

29. if(status[v]==ready)

30. {

31. //check status of N's neighbour.

32. push(v); //push N's neighbour who are in ready state.

33. status[v]=wait; //and make their status to wait state.

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

the total cost of executing lines 4–7 of DFS-VISIT is θ(E).

The running time of DFS is there fore ‚θ(V + E).

You might also like