Chapter 9 Graphs Some concepts A graph consists of a set of - - PowerPoint PPT Presentation
Chapter 9 Graphs Some concepts A graph consists of a set of - - PowerPoint PPT Presentation
CS 2412 Data Structures Chapter 9 Graphs Some concepts A graph consists of a set of vertices and a set of lines (edges, arcs). A directed graph, or digraph, is a graph in which each line has a direction. Usually, the lines are called
Some concepts
- A graph consists of a set of vertices and a set of lines (edges,
arcs).
- A directed graph, or digraph, is a graph in which each line has
a direction. Usually, the lines are called arcs.
- A path is a sequence of vertices in which each vertex is
adjacent to the next one, where adjacent means that there is an line from one to the next one.
- A cycle is a path consisting of at least three vertices that starts
and ends with the same vertex.
- A loop is a single arc from a vertex to itself.
- A connected graph is a graph in which any pair of vertices has
a path between them.
Data Structure 2016
- R. Wei
2
For a directed graph:
- Strong connected if there is a path from each vertex to every
- ther vertex.
- Weakly connected if there is a path from each vertex to every
- ther vertex when the direction of the arc is ignored, but at
least two vertices are not connected when we consider the direction of the path.
- The outdegree of a vertex is the number of arcs leaving the
vertex.
- The indegree is the number of arcs entering the vertex.
Data Structure 2016
- R. Wei
3
Data Structure 2016
- R. Wei
4
Data Structure 2016
- R. Wei
5
Data Structure 2016
- R. Wei
6
Operations
- Inset a vertex: add a new vertex to the graph.
- Delete a vertex: removed a vertex from the graph and all edges
connected to that vertex are also removed.
- Add an edge: two vertices must be specified to add an edge.
For a digraph, one vertex must be specified as the source and
- ther one as the destination.
- Delete an edge: remove an edge from the graph.
Data Structure 2016
- R. Wei
7
Traverse graph:
- Depth-first traversal: Suppose the traversal has just visited a
vertex v which is adjacent to vertices w1, w2, · · · , wk. Then the traversal visit w1 and traverse all the vertices to which it is adjacent before returning to traverse w2, · · · , wk.
- Breadth-first traversal: Suppose the traversal has just visited a
vertex v. Then it next visits all the vertices adjacent to v.
Data Structure 2016
- R. Wei
8
We can use a recursive method to implement graph traverse. But we also can use a stack to implement. Depth-first traversal:
- 1. Push the first vertex into the stack.
- 2. Loop:
pop a vertex from the stack process the vertex push all of the adjacent vertices into the stack.
- 3. When the stack is empty, the traversal is complete.
Data Structure 2016
- R. Wei
9
Data Structure 2016
- R. Wei
10
Use a queue to implement the breadth-first traversal:
- 1. Enqueue the first vertex into the queue.
- 2. Loop:
dequeue a vertex from the Process the vertex. place all of its adjacent vertices into the queue.
- 3. When the queue is empty, the traversal is complete.
Data Structure 2016
- R. Wei
11
Data Structure 2016
- R. Wei
12
Graph representation
- Adjacency matrix: a 0-1 matrix its rows and columns are
indexed by vertices. The cell i, j is 1 if and only if the ith vertex and the jth vertex is adjacent. The matrix of a non-directed graph must be symmetric to its main diagonal.
- Adjacency list: a list of vertices that are adjacent to the vertex.
Each vertex has a adjacent list (unless it is isolated).
Data Structure 2016
- R. Wei
13
Data Structure 2016
- R. Wei
14
There are different methods to implement graphs. The following implementation are based on the adjacent list.
Data Structure 2016
- R. Wei
15
Data Structure 2016
- R. Wei
16
typedef struct { int count; struct vertex* first; int (*compare) (void* argu1, void* argu2); } GRAPH; typedef struct vertex { struct vertex* pNextVertex; void* dataPtr; int inDegree; int
- utDegree;
short processed; struct arc* pArc; } VERTEX; typedef struct arc { struct vertex* destination; struct arc* pNextArc; } ARC;
Data Structure 2016
- R. Wei
17
To create a graph is simple.
Data Structure 2016
- R. Wei
18
GRAPH* graphCreate (int (*compare) (void* argu1, void* argu2)) { GRAPH* graph; graph = (GRAPH*) malloc (sizeof (GRAPH)); if (graph) { graph->first = NULL; graph->count = 0; graph->compare = compare; } // if return graph; } // graphCreate
Data Structure 2016
- R. Wei
19
For the insertion and deletion of vertex in a graph with adjacency list implementation:
- The vertex list is arranged in order (usually in the increasing
- rder corresponding to the keys).
- For insertion, first insert the vertex to the vertex list according
to the order of key. Then insert the related edges.
- For deletion, first delete the edges connected to the vertex that
will be deleted. Then delete the vertex.
- We only consider the graph here. But the implementation of
digraph is similar.
Data Structure 2016
- R. Wei
20
Data Structure 2016
- R. Wei
21
void graphInsVrtx (GRAPH* graph, void* dataInPtr) { VERTEX* newPtr; VERTEX* locPtr; VERTEX* predPtr; newPtr = (VERTEX*)malloc(sizeof (VERTEX)); if (newPtr) { newPtr->pNextVertex = NULL; newPtr->dataPtr = dataInPtr; newPtr->inDegree = 0; newPtr->outDegree = 0; newPtr->processed = 0; newPtr->pArc = NULL; (graph->count)++; } // if malloc else printf("Overflow error 100\a\n"), exit (100); locPtr = graph->first;// Now find insertion point if (!locPtr)
Data Structure 2016
- R. Wei
22
graph->first = newPtr; else { predPtr = NULL; while (locPtr && (graph->compare (dataInPtr, locPtr->dataPtr) > 0)) { predPtr = locPtr; locPtr = locPtr->pNextVertex; } // while if (!predPtr) graph->first = newPtr; else predPtr->pNextVertex = newPtr; newPtr->pNextVertex = locPtr; } // else return; } // graphInsVrtx
Data Structure 2016
- R. Wei
23
Data Structure 2016
- R. Wei
24
int graphDltVrtx (GRAPH* graph, void* dltKey) { VERTEX* predPtr; VERTEX* walkPtr; if (!graph->first) return -2; predPtr = NULL; walkPtr = graph->first; while (walkPtr && (graph->compare(dltKey, walkPtr->dataPtr) > 0)) { predPtr = walkPtr; walkPtr = walkPtr->pNextVertex; } // walkPtr && if (!walkPtr || graph->compare(dltKey, walkPtr->dataPtr) != 0)
Data Structure 2016
- R. Wei
25
return -2; // then found vertex. Test degree if ((walkPtr->inDegree > 0) || (walkPtr->outDegree > 0)) return -1; if (!predPtr) //delete graph->first = walkPtr->pNextVertex; else predPtr->pNextVertex = walkPtr->pNextVertex;
- -graph->count;
free(walkPtr); return 1; } // graphDltVrtx
Data Structure 2016
- R. Wei
26
Data Structure 2016
- R. Wei
27
Data Structure 2016
- R. Wei
28
int graphInsArc (GRAPH* graph, void* pFromKey, void* pToKey) { ARC* newPtr; ARC* arcPredPtr; ARC* arcWalkPtr; VERTEX* vertFromPtr; VERTEX* vertToPtr; newPtr = (ARC*)malloc(sizeof(ARC)); if (!newPtr) return (-1); //locate source vertex vertFromPtr = graph->first; while (vertFromPtr && (graph->compare(pFromKey, vertFromPtr->dataPtr) > 0)) { vertFromPtr = vertFromPtr->pNextVertex; } if (!vertFromPtr || (graph->compare(pFromKey, vertFromPtr->dataPtr) != 0))
Data Structure 2016
- R. Wei
29
return (-2); vertToPtr = graph->first; while (vertToPtr && graph->compare(pToKey, vertToPtr->dataPtr) > 0) { vertToPtr = vertToPtr->pNextVertex; } if (!vertToPtr || (graph->compare(pToKey, vertToPtr->dataPtr) != 0)) return (-3); // From and to vertices located. Insert new arc ++vertFromPtr->outDegree; ++vertToPtr
- >inDegree;
newPtr->destination = vertToPtr; if (!vertFromPtr->pArc) { // Inserting first arc for this vertex vertFromPtr->pArc = newPtr; newPtr-> pNextArc = NULL; return 1;
Data Structure 2016
- R. Wei
30
} // Find insertion point in adjacency (arc) list arcPredPtr = NULL; arcWalkPtr = vertFromPtr->pArc; while (arcWalkPtr && graph->compare(pToKey, arcWalkPtr->destination->dataPtr) >= 0) { arcPredPtr = arcWalkPtr; arcWalkPtr = arcWalkPtr->pNextArc; } // arcWalkPtr && if (!arcPredPtr) // Insertion before first arc vertFromPtr->pArc = newPtr; else arcPredPtr->pNextArc = newPtr; newPtr->pNextArc = arcWalkPtr; return 1; } // graphInsArc
Data Structure 2016
- R. Wei
31
Data Structure 2016
- R. Wei
32
Data Structure 2016
- R. Wei
33
int graphDltArc (GRAPH* graph, void* fromKey, void* toKey) { VERTEX* fromVertexPtr; VERTEX* toVertexPtr; ARC* preArcPtr; ARC* arcWalkPtr; if (!graph->first) return -2; // Locate source vertex fromVertexPtr = graph->first; while (fromVertexPtr && (graph->compare(fromKey, fromVertexPtr->dataPtr) > 0)) fromVertexPtr = fromVertexPtr->pNextVertex; if (!fromVertexPtr || graph->compare(fromKey, fromVertexPtr->dataPtr) != 0) return -2; // Locate destination vertex in adjacency list if (!fromVertexPtr->pArc) return -3; preArcPtr = NULL; arcWalkPtr = fromVertexPtr->pArc; while (arcWalkPtr && (graph->compare(toKey,
Data Structure 2016
- R. Wei
34
arcWalkPtr->destination->dataPtr) > 0)) { preArcPtr = arcWalkPtr; arcWalkPtr = arcWalkPtr->pNextArc; } // while arcWalkPtr && if (!arcWalkPtr || (graph->compare(toKey, arcWalkPtr->destination->dataPtr) != 0)) return -3; toVertexPtr = arcWalkPtr->destination; // from, toVertex & arcPtr located. Delete arc
- -fromVertexPtr->outDegree;
- -toVertexPtr -> inDegree;
if (!preArcPtr) // Deleting first arc fromVertexPtr->pArc = arcWalkPtr->pNextArc; else preArcPtr->pNextArc = arcWalkPtr->pNextArc; free (arcWalkPtr); return 1; } // graphDltArc
Data Structure 2016
- R. Wei
35
Data Structure 2016
- R. Wei
36
int graphRetrVrtx (GRAPH* graph, void* keyPtr, void** pDataOut) { VERTEX* walkPtr; if (!graph->first) return -2; walkPtr = graph->first; while (walkPtr && (graph->compare (keyPtr, walkPtr->dataPtr) > 0)) walkPtr = walkPtr->pNextVertex; if (graph->compare(keyPtr, walkPtr->dataPtr) == 0) { *pDataOut = walkPtr->dataPtr; return 1; } // if else return -2; } // graphRetrVrtx
Data Structure 2016
- R. Wei
37
Data Structure 2016
- R. Wei
38
Data Structure 2016
- R. Wei
39
void graphDpthFrst (GRAPH* graph, void (*process) (void* dataPtr)) { bool success; VERTEX* walkPtr; VERTEX* vertexPtr; VERTEX* vertToPtr; STACK * stack; ARC* arcWalkPtr; if (!graph->first) return; // Set processed flags to not processed walkPtr = graph->first; while (walkPtr) { walkPtr->processed = 0; walkPtr = walkPtr->pNextVertex; } // while // Process each vertex in list stack = createStack (); walkPtr = graph->first;
Data Structure 2016
- R. Wei
40
while (walkPtr) { if (walkPtr->processed < 2) { if (walkPtr->processed < 1) { // Push & set flag to pushed success = pushStack (stack, walkPtr); if (!success) printf("\aStack overflow 100\a\n"), exit (100); walkPtr->processed = 1; } // if processed < 1 } // if processed < 2 // Process descendents of vertex at stack top while (!emptyStack (stack)) { vertexPtr = popStack(stack); process (vertexPtr->dataPtr); vertexPtr->processed = 2; // Push all vertices from adjacency list
Data Structure 2016
- R. Wei
41
arcWalkPtr = vertexPtr->pArc; while (arcWalkPtr) { vertToPtr = arcWalkPtr->destination; if (vertToPtr->processed == 0) { success = pushStack(stack, vertToPtr); if (!success) printf("\aStack overflow 101\a\n"), exit (101); vertToPtr->processed = 1; } // if vertToPtr arcWalkPtr = arcWalkPtr->pNextArc; } // while pWalkArc } // while !emptyStack walkPtr = walkPtr->pNextVertex; } // while walkPtr destroyStack(stack); return; } // graphDpthFrst
Data Structure 2016
- R. Wei
42
void graphBrdthFrst (GRAPH* graph, void (*process) (void* dataPtr)) { bool success; VERTEX* walkPtr; VERTEX* vertexPtr; VERTEX* vertToPtr; QUEUE* queue; ARC* arcWalkPtr; if (!graph->first) return; // Set processed flags to not processed walkPtr = graph->first; while (walkPtr) { walkPtr->processed = 0; walkPtr = walkPtr->pNextVertex; } // while // Process each vertex in list queue = createQueue (); walkPtr = graph->first;
Data Structure 2016
- R. Wei
43
while (walkPtr) { if (walkPtr->processed < 2) { if (walkPtr->processed < 1) { // Enqueue & set flag to queue success = enqueue(queue, walkPtr); if (!success) printf("\aQueue overflow 100\a\n"), exit (100); walkPtr->processed = 1; } // if processed < 1 } // if processed < 2 // Process descendents of vertex at que frnt while (!emptyQueue (queue)) { dequeue(queue, (void**)&vertexPtr); process (vertexPtr->dataPtr); vertexPtr->processed = 2; // Enqueue vertices from adjacency list
Data Structure 2016
- R. Wei
44
arcWalkPtr = vertexPtr->pArc; while (arcWalkPtr) { vertToPtr = arcWalkPtr->destination; if (vertToPtr->processed == 0) { success = enqueue(queue, vertToPtr); if (!success) printf("\aQueue overflow 101\a\n"), exit (101); vertToPtr->processed = 1; } // if vertToPtr arcWalkPtr = arcWalkPtr->pNextArc; } // while pWalkArc } // while !emptyQueue walkPtr = walkPtr->pNextVertex; } // while walkPtr destroyQueue(queue); return; } // graphBrdthFrst
Data Structure 2016
- R. Wei
45
Data Structure 2016
- R. Wei
46
Weighted graph Weighted graph is a graph whose edges are weighted. The meaning
- f the weights depends on the applications.
Sometimes, a weighted graph is also called a network. Example:
Data Structure 2016
- R. Wei
47
Two methods can be used to store a weighted graph:
Data Structure 2016
- R. Wei
48
Minimum spanning tree A spanning tree contains all of the vertices in a connected graph. A minimum spanning tree is a spanning tree in which the total weight
- f the edges is the minimum of all possible spanning trees in the
graph. Example: Find a minimum spanning tree for the network:
Data Structure 2016
- R. Wei
49
The main idea: Start from any vertex, say A. Put A into the set S. Consider all the edges connected to A and find out the minimum weight edge, say the edge connect to C. Put C in S and put edge AC to the tree T. In general, consider all the edges connected to a vertex in S, but the vertex of the other end of the edge is not in S. Select the minimum weight edge which is then put in the tree T. The vertex
- f the other end of the edge is also put in S.
If S contains all the vertices of the graph, output T.
Data Structure 2016
- R. Wei
50
Data Structure 2016
- R. Wei
51
Data structure for spanning tree of graph: We use adjacency list implementation which is similar to the previous implementation of graphs. The main differences are:
- For graph vertex, inTree are used instead of processed.
inTree is a indicator to indicate if the vertex is included in the spanning tree.
- For graph edge, weight and inTree are added. The weight
is used to record the weight of the edge and inTree is used to indicate if the edge is included in the spanning tree.
Data Structure 2016
- R. Wei
52
Data Structure 2016
- R. Wei
53
Data Structure 2016
- R. Wei
54
Shortest path: Dijkstra algorithm A shortest path between two vertices in a network is a path with minimum weights. Dijkstra algorithm is used to find the shortest path between any two nodes in a graph:
- Insert the first vertex into the tree.
- From every vertex already in the tree, check the total path to
all adjacent vertices not in the tree. Select the edge with the minimum total path weight and insert it into the tree.
- Repeat above step until all vertices are in the tree.
Data Structure 2016
- R. Wei
55
Data Structure 2016
- R. Wei
56
Data Structure 2016
- R. Wei
57
Algorithm shortestPath (graph)
Data Structure 2016
- R. Wei
58
Data Structure 2016
- R. Wei
59
The above algorithm is based on adjacency list. We also can use the adjacency matrix to find about the shortest path.
Data Structure 2016
- R. Wei
60