Вы находитесь на странице: 1из 68

Graphs

• All tree structures are hierarchical. This means that each node
can only have one parent node(only parent to child path).
Trees can be used to store data which has a definite hierarchy;
for example a family tree or a computer file system.

• Some data need to have connections between items which do


not fit into a hierarchy like this. Graph data structures can be
useful in these situations.

• A graph consists of a number of data items, each of which is


called a vertex. Any vertex may be connected to any other,
and these connections are called edges.
Graphs
• Extremely useful tool in modelling flight ,train reservation etc
systems.
• Consist of:
– Vertices
– Edges Vertices can be
D
considered “sites”
E
or locations.
C
A
Edges represent
F
B connections.
Vertex
Edge
Definition
• Undirected graph
– An undirected graph is specified by an ordered pair (V,E), where V is
the set of vertices and E is the set of edges

{a,b} {a,c}

{b,d} {c,d}

{b,e} {c,f}

{e,f}
Terminology
• If v1 and v2 are connected, they are said to be adjacent
vertices
• v1 and v2 are endpoints of the edge {v1, v2}

• If an edge e is connected to v, then v is said to be incident


on e. Also, the edge e is said to be incident on v.

• {v1, v2} = {v2, v1}*

*Later, we will talk about “directed graphs”, where edges have direction. This
means that {v1,v2} ≠ {v2,v1} . Directed graphs are drawn with arrows (called arcs)
between edges. A B This means {A,B} only, not {B,A}
Path between vertices
• A path is a sequence of vertices (v0, v1, v2,…
vk) such that:

– For 0 ≤ i < k, {vi, vi+1} is an edge

– For 0 ≤ i < k-1, vi ≠ vi+2


That is, the edge {vi, vi+1} ≠ {vi+1, vi+2}

Note: a path is allowed to go through the same vertex or the same edge any
number of times!

• The length of a path is the number of edges


on the path
Types of paths
• A path is simple if and only if it does not
contain a vertex more than once.

• A path is a cycle if and only if v0= vk


• The beginning and end are the same vertex!

• A path contains a cycle if some vertex


appears twice or more
Directed Graph
• A graph is directed if direction is assigned to
each edge. We call the directed edges arcs.
– An edge is denoted as an ordered pair (u, v)

• Recall: for an undirected graph


– An edge is denoted {u,v}, which actually
corresponds to two arcs (u,v) and (v,u)
• A path in a directed graph must follow the direction of
the arrows.
• A directed graph is connected if, for any pair of
vertices, there is a path between them.

D C

A E

Is the above graph connected?


Applications
Air flight system

• Each vertex represents a city.


• Each edge represents a direct flight between two cities.
• A query on direct flights becomes a query on whether an edge exists.
• A query on how to get to a location is “does a path exist from A to B”.
• We can even associate costs to edges (weighted graphs(discussed later)), then
ask “what is the cheapest path from A to B”.
Another application
• Wireless communication

• Can be represented by a weighted complete graph (every two vertices are


connected by an edge).
• Each edge represents the Euclidean distance dij between two stations.
• Each station uses a certain power i to transmit messages. Given this power i,
only a few nodes can be reached (bold edges). A station reachable by i then
use its own power to relay the message to other stations not reachable by i.
• A typical wireless communication problem is: how to broadcast between all
stations such that they are all connected and the power consumption
is minimized.
Some other applications:
• Electronic circuits:
To find the least resistance between two nodes.
• Computer networks:
To find the smallest path(low traffic) between 2
computers.
• Databases:
To draw the entity relationship(ER) diagram.
Graph Representation
• Two popular computer representations of a
graph. Both represent the vertex set and the
edge set, but in different ways.

1. Adjacency Matrix
Use a 2D matrix to represent the graph

2. Adjacency List
Use a 1D array of linked lists
Adjacency Matrix

• 2D array A[0..n-1, 0..n-1], where n is the number of vertices in the graph


• Each row and column is indexed by the vertex id.
- e,g a=0, b=1, c=2, d=3, e=4
• An array entry A [i] [j] is equal to 1 if there is an edge connecting
vertices i and j. Otherwise, A [i] [j] is 0.
• The storage requirement is Θ(n2). Not efficient if the graph has few edges.
• We can detect in O(1) time whether two vertices are connected.
Adjacency list

• The adjacency list is an array A[0..n-1] of lists, where n is the


number of vertices in the graph.
Each array entry is indexed by the vertex id (as with adjacency
matrix)
• The list A[i] stores the ids of the vertices adjacent to i.
Examples

0 1 2 3 4 5 6 7 8 9
0
0 0 0 0 0 0 0 0 0 1 0
8
1 0 0 1 1 0 0 0 1 0 1

2 0 1 0 0 1 0 0 0 1 0
2 9
3 0 1 0 0 1 1 0 0 0 0
1
4 0 0 1 1 0 0 0 0 0 0
3 7
5 0 0 0 1 0 0 1 0 0 0
6
4 6 0 0 0 0 0 1 0 1 0 0
5
7 0 1 0 0 0 0 1 0 0 0

8 1 0 1 0 0 0 0 0 0 1

9 0 1 0 0 0 0 0 0 1 0
Examples

0 8
0
1 2 3 7 9
8
2 1 4 8

2 3 1 4 5
9
1 4 2 3
5 3 6
3 7
6 5 7
6
4 7 1 6
5
8 0 2 9

9 1 8
Algorithm:-
Step-1: Make the list that holds the graph, having all the
vertices in the graph
Step-2: For every vertex in that list do the following -
a. find the adjacent vertices, if any
b. add that vertex in the adjacency list for this
current vertex
struct adj_node /*the NODE which forms
the part of the adjacency
list; look at figure [B]*/
{
char vertex_val;
struct adj_node *adj_next; /*red pointer*/
};
struct node /*the NODE which forms
the part of the Graph; look
at figure [A]*/
{
char vertex_val;
struct adj_node *down;
struct node *next; /*black pointer*/
};
struct node *graph;
LinkListrepresentation()
{
struct node *cur_vertex, *aux_ptr;
struct adj_node *adj_cur, *new;

/*Step-1 of the algorithm is expected from you or refer linked LISTS*/


/*Step-1 gives you a list, being pointed by 'graph' */

cur_vertex = graph; /*first node of the graph in


consideration*/
/*Step-2 starts here*/
while ( cur_vertex != NULL)
{
aux_ptr = graph; /*an auxiliary pointer to the graph*/
adj_cur = NULL; /*an auxiliary pointer to keep track
of the adjacency lists*/
cur_vertex->down = adj_cur;
while (aux_ptr != NULL)
{
printf("Is there any edge between %c and %c
",aux_ptr->vertex_val, cur_vertex->vertex_val);
scanf("%d", &edge); /*step-2: part-A*/

if( edge == 1) /*step-2: part - B*/


if( adj_cur == NULL)
{
adj_cur = (struct adj_node
*)malloc(sizeof(adj_node));
adj_cur ->vertex_val = aux_ptr->vertex_val;
adj_cur -> adj_next = NULL;
}
else
{
new = (struct adj_node
*)malloc(sizeof(adj_node));
new -> vertex_val = aux_ptr ->vertex_val;

adj_cur ->adj_next = new;


adj_cur = new;
adj_cur ->adj_next = NULL;
}

aux_ptr = aux_ptr ->next;


} /end 2nd while*/
cur_vertex = cur_vertex ->next;
} /*end 1st while*/
} /*end function*/
Representing a graph using array of pointers and linked list

• Adjacency list can be made more simpler by replacing horizontal


linked list with array of pointers.
• Array of pointers contain entries for each node in the graph(indexed
by vertex id).
• Linked list contains entries for adjacent nodes for each node.

Implementation:
• Head[]( array of pointers) is set to NULL in main().
• Creategraph() is a function to create graph(array of pointers and
linked list).
• Creategraph() asks the user for number of nodes in graph and builds
the list by asking user to enter the adjacent vertices for node.
• For each adjacent vertex a node is created and inserted at rear.
//creating a graph using array of pointers and linked list
void Creategraph(NODEPTR head[])
{
int i,v;
printf(“enter no of vertices”);
scanf(“%d”,&n);
for(i=0;i<n;i++){
do{
printf(“enter next adjacent vertex for %d”, i);
scanf(“%d”, &v);
if(v==-1) break; // no more adjacent vertex
head[i]=insert_rear(head[i],v);
} while(1);
}// end for
}end function
//insert rear function
NODEPTR insert_rear(NODEPTR h, int v)
{
NODEPTR temp=getnode();
NODEPTR t=h;
tempvertex_value=v;
tempnext=NULL;
if(h==NULL)
return temp;
while(tnext!=NULL)
t=tnext;
tnext=temp;
return h;
}
//function for displaying graph
Void displaygraph(NODEPTR head[ ])
{
NODEPTR t;
for(int i=0;i<n;i++)
{
cout<<i;
t=h[i];
while(t!=NULL)
{
cout<<tvertex_value;
t=tnext;
}
}
}
//main function
Struct node
{
int vertex_value;
struct node *next;
};
Int n;
Void main()
{
NODEPTR head[20]={NULL};
creategraph(head);
displaygraph(head);
}
Representations
Adjacency Lists vs. Matrix
• Adjacency Lists
– More compact than adjacency matrices if graph has few edges
– Requires more time to find if an edge exists

• Adjacency Matrix
– Always require n2 space
• This can waste a lot of space if the number of edges are
sparse
– Can quickly find if an edge exists
Directed Acyclic Graph
• A directed path is a sequence of vertices
(v0, v1, . . . , vk)
– Such that (vi, vi+1) is an arc

• A directed cycle is a directed path such that the first and last
vertices are the same.

• A directed graph is acyclic if it does not contain any directed


cycles
Example
Indeg(2)?
6 3
8 Indeg(8)?

Outdeg(0)?
0 7
2 9
1 Num of Edges?

Total OutDeg?
5 Total Indeg?
4
Directed Graphs Usage
• Directed graphs are often used to represent order-dependent
tasks
• That is we cannot start a task before another task finishes
• We can model this task dependent constraint using arcs
• An arc (i,j) means task j cannot start until task i is finished

i j

Task j cannot start


until task i is finished
• Clearly, for the system not to hang, the graph must be acyclic.
Graph Traversals

• Depth-First Traversals.
– Algorithms.
– Example.
– Implementation.

• Breadth-First Traversal.
– The Algorithm.
– Example.
– Implementation.

• Review Questions.
Depth-First Traversal Algorithm
• In this method, After visiting a vertex v, which is adjacent to w1, w2, w3, ...;
Next we visit one of v's adjacent vertices, w1 say. Next, we visit all vertices
adjacent to w1 before coming back to w2, etc.

• Must keep track of vertices already visited to avoid cycles.

Algorithm:-
Step-1: Set the starting point of traversal and push it inside the stack.
Step-2: Pop the stack and add the popped vertex to the list of visited
vertices.
Step-3: Find the adjacent vertices for the most recently visited
vertex( from the Adjacency Matrix).
Step-4: Push these adjacent vertices inside the stack if they are not
visited and not there in the stack already.
Step-5: Go to step-2 if the stack is not empty.

• Note: Adjacent vertices can be pushed in any order; but to obtain a unique traversal,
we will push them in reverse alphabetical order.
Example
• Demonstrates depth-first traversal using an explicit stack.

A B C F E G D H I Stack
//depth first search
Void dfs( NODEPTR h[], int v)
{
NODEPTR w;
int visit[20]={FALSE};
cout<<v;
visit[v]=TRUE; //mark node as visited
for(w=h[v] ;w!=NULL; w=wnext){
if(!visit[wvertex_value]){
dfs(h,wvertex_value);
}
}

}
Breadth-First Traversal Algorithm
• In this method, After visiting a vertex v, we must visit all its adjacent
vertices w1, w2, w3, ..., before going down next level to visit vertices
adjacent to w1 etc.

• The method can be implemented using a queue.

• A boolean array is used to ensure that a vertex is enqueued only once.

1 enqueue the starting vertex


2 while(queue is not empty){
3 dequeue a vertex v from the queue;
4 visit v.
5 enqueue vertices adjacent to v that were never enqueued;
6 }

• Note: Adjacent vertices can be enqueued in any order; but to obtain a unique
traversal, we will enqueue them in alphabetical order.
BSF algorithm

Why use queue? Need FIFO


//breadth first search
Void dfs( NODEPTR h[], int v)
{
NODEPTR w;
int visit[20]={FALSE}, queue[20], front=0,rear=-1;
cout<<v;
visit[v]=TRUE;
queue[++rear]=v;
while(front<=rear)
{
v=queue[front++];
for(w=h[v] ;w!=NULL; w=wnext){
if(!visit[wvertex_value]){
cout<<wvertex;
queue[++rear]=wvertex_value;
visit[wvertex_value]=TRUE;
}
}
}
}
Example
• Demonstrating breadth-first traversal using a queue.

Queue front

Order of
Traversal A B D E C G F H IQueue rear
Example
Adjacency List Visited Table (T/F)
0 F

1 F
0
2 F
8 3 F

4 F
source 2 9 5 F

6
1 F

7 F

3 7 8 F
6 9 F
4
5
Initialize visited
table (all False)

Q= { }

Initialize Q to be empty
Example
Adjacency List Visited Table (T/F)
0 F

1 F
0
2 T
8 3 F

4 F
source 2 9 5 F

6
1 F

7 F

3 7 8 F
6 9 F
4
5
Flag that 2 has
been visited.

Q= { 2 }

Place source 2 on the queue.


Example
Adjacency List Visited Table (T/F)
0 F

1 T
0
2 T
Neighbors
8 3 F

4 T
source 2 9 5 F

6
1 F

7 F

3 7 8 T
6 9 F
4
5
Mark neighbors
as visited.

Q = {2} → { 8, 1, 4 }
Dequeue 2.
Place all unvisited neighbors of 2 on the queue
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 F

4 T
source 2 9 5 F

6
1 F

7 F

3 7 8 T
Neighbors
6 9 T
4
5
Mark new visited
Neighbors.

Q = { 8, 1, 4 } → { 1, 4, 0, 9 }

Dequeue 8.
-- Place all unvisited neighbors of 8 on the queue.
-- Notice that 2 is not placed on the queue again, it has been visited!
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0 Neighbors
2 T
8 3 T

4 T
source 2 9 5 F

6
1 F

7 T

3 7 8 T
6 9 T
4
5
Mark new visited
Neighbors.

Q = { 1, 4, 0, 9 } → { 4, 0, 9, 3, 7 }

Dequeue 1.
-- Place all unvisited neighbors of 1 on the queue.
-- Only nodes 3 and 7 haven’t been visited yet.
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
Neighbors
source 2 9 5 F

6
1 F

7 T

3 7 8 T
6 9 T
4
5

Q = { 4, 0, 9, 3, 7 } → { 0, 9, 3, 7 }

Dequeue 4.
-- 4 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T
Neighbors
1 T
0
2 T
8 3 T

4 T
source 2 9 5 F

6
1 F

7 T

3 7 8 T
6 9 T
4
5

Q = { 0, 9, 3, 7 } → { 9, 3, 7 }

Dequeue 0.
-- 0 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
source 2 9 5 F

6
1 F

7 T

3 7 8 T
6 Neighbors 9 T
4
5

Q = { 9, 3, 7 } → { 3, 7 }

Dequeue 9.
-- 9 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T
Neighbors
4 T
source 2 9 5 T

6
1 F

7 T

3 7 8 T
6 9 T
4
5
Mark new visited
Vertex 5.

Q = { 3, 7 } → { 7, 5 }

Dequeue 3.
-- place neighbor 5 on the queue.
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
source 2 9 5 T

6
1 T

Neighbors 7 T

3 7 8 T
6 9 T
4
5
Mark new visited
Vertex 6.

Q = { 7, 5 } → { 5, 6 }

Dequeue 7.
-- place neighbor 6 on the queue.
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
source 2 9 Neighbors
5 T

6
1 T

7 T

3 7 8 T
6 9 T
4
5

Q = { 5, 6} → { 6 }

Dequeue 5.
-- no unvisited neighbors of 5.
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
source 2 9 5 T

1 Neighbors 6 T

7 T
3 7
8 T
6
4 9 T
5

Q= {6}→{ }

Dequeue 6.
-- no unvisited neighbors of 6.
Example
Adjacency List Visited Table (T/F)
0 T

1 T
0
2 T
8 3 T

4 T
source 2 9 5 T

6
1 T

7 T

3 7 8 T
6 9 T
4
5

What did we discover?

Look at “visited” tables.


Q= { } STOP!!! Q is empty!!!
There exists a path from source
vertex 2 to all vertices in the graph.
Shortest Path Recording
• BFS we saw only tells us whether a path exists from source
s, to other vertices v.
– It doesn’t tell us the path!
– We need to modify the algorithm to record the path.

• How can we do that?


– Note: we do not know which vertices lie on this path until we
reach v!
– Efficient solution:
• Use an additional array pred[0..n-1]
• Pred[w] = v means that vertex w was visited from v
BFS + Path Finding

initialize all pred[v] to -1

Record where you


came from
Example
Adjacency List Visited Table (T/F)
0 F -

1 F -
0
2 F -
8 3 F -

4 F -
source 2 9 5 F -

6
1 F -

7 F -

3 7 8 F -
6 9 F -
4
5 Pred
Initialize visited
table (all False)

Q= { } Initialize Pred to -1

Initialize Q to be empty
Example
Adjacency List Visited Table (T/F)
0 F -

1 F -
0
2 T -
8 3 F -

4 F -
source 2 9 5 F -

6
1 F -

7 F -

3 7 8 F -
6 9 F -
4
5 Pred
Flag that 2 has
been visited.

Q= { 2 }

Place source 2 on the queue.


Example
Adjacency List Visited Table (T/F)
0 F -

1 T 2
0
2 T -
Neighbors
8 3 F -

4 T 2

source 2 9 5 F -

6 -
1 F

7 F -

3 7 8 T 2
6 9 F -
4
5 Pred
Mark neighbors
as visited.

Q = {2} → { 8, 1, 4 } Record in Pred


that we came
Dequeue 2.
from 2.
Place all unvisited neighbors of 2 on the queue
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 F -

4 T 2
source 2 9 5 F -

6
1 F -

7 F -

3 7 Neighbors 8 T 2
6 9 T 8
4
5 Pred
Mark new visited
Neighbors.

Q = { 8, 1, 4 } → { 1, 4, 0, 9 } Record in Pred
that we came
Dequeue 8.
from 8.
-- Place all unvisited neighbors of 8 on the queue.
-- Notice that 2 is not placed on the queue again, it has been visited!
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0 Neighbors
2 T -

8 3 T 1

4 T 2

source 2 9 5 F -

6 -
1 F

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred
Mark new visited
Neighbors.

Q = { 1, 4, 0, 9 } → { 4, 0, 9, 3, 7 } Record in Pred
that we came
Dequeue 1.
from 1.
-- Place all unvisited neighbors of 1 on the queue.
-- Only nodes 3 and 7 haven’t been visited yet.
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
Neighbors
source 2 9 5 F -

6
1 F -

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred

Q = { 4, 0, 9, 3, 7 } → { 0, 9, 3, 7 }

Dequeue 4.
-- 4 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T 8
Neighbors
1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 5 F -

6
1 F -

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred

Q = { 0, 9, 3, 7 } → { 9, 3, 7 }

Dequeue 0.
-- 0 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 5 F -

6
1 F -

7 T 1

3 7 8 T 2
6 Neighbors 9 T 8
4
5 Pred

Q = { 9, 3, 7 } → { 3, 7 }

Dequeue 9.
-- 9 has no unvisited neighbors!
Example
Adjacency List Visited Table (T/F)
0 T
8
1 T
0 2
2 T
-
8 3 T
Neighbors 1
4 T
2
source 2 9 5 T
3
6
1 F
-
7 T
1
3 7 8 T
2
6 9 T
4 8
5
Pred
Mark new visited
Vertex 5.
Q = { 3, 7 } → { 7, 5 }
Record in Pred
Dequeue 3. that we came
-- place neighbor 5 on the queue. from 3.
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 5 T 3

6
1 T 7

Neighbors 7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred
Mark new visited
Vertex 6.
Q = { 7, 5 } → { 5, 6 }
Record in Pred
Dequeue 7. that we came
-- place neighbor 6 on the queue. from 7.
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 Neighbors
5 T 3

6
1 T 7

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred

Q = { 5, 6} → { 6 }

Dequeue 5.
-- no unvisited neighbors of 5.
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 5 T 3

6
1 Neighbors T 7

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred

Q= {6}→{ }

Dequeue 6.
-- no unvisited neighbors of 6.
Example
Adjacency List Visited Table (T/F)
0 T 8

1 T 2
0
2 T -
8 3 T 1

4 T 2
source 2 9 5 T 3

6
1 T 7

7 T 1

3 7 8 T 2
6 9 T 8
4
5 Pred

Pred now can be traced backward


Q= { } STOP!!! Q is empty!!! to report the path!
Path reporting
nodes visited from
0 8

1 2

2 -

3 1

4 2

5 3

6 7

7 1

8 2

9 8

Try some examples, report path from s to v:


Path(0) ->
Path(6) ->
Path(1) ->
The path returned is the shortest from s to v
(minimum number of edges).

Вам также может понравиться