# Data Structure and Algorithms collation-diagram

Posted by cullouch on Sun, 15 Mar 2020 04:22:50 +0100

Collate Zhang Ming's Notes on Data Structure and Algorithms

## 7. Diagram

### 7.1 Diagram concepts and abstract data types

#### Definitions and terminology of 7.1.1 diagrams

1.G=(V,E) Representation

• V is the set of vertices
• E is a set of edges
2. Complete Diagram
3. Sparse Map
• Sparsity (Sparsity Factor)
• The number of edges is less than 5% of the complete graph
4. Dense Map
5. undirected graph
• Pairwise disorder of edges involving vertices
• Actually, it's two-way
6. Directed Graph
• Even pairs of edges involving vertices are ordered
7. Labels
8. Weighted Map
9. Degree of vertex
• Number of edges associated with a vertex, degrees in and out
10. Subgraph
11. Loop

### Storage structure of 7.2 diagrams

• For a graph with n vertices, the spatial cost of the adjacent matrix is O(n2), independent of the number of edges.
• Sparsity factor
If there are t non-zero elements in the m*n matrix, the sparse factor is t/m+n
If the sparse factor is less than 0.05, it is the sparse factor

Contiguity table representation

• An undirected graph has the same edge appearing twice in the adjacency table
• Adjacency Table for Directed Graphs (Out Edge Table)
• Inverse Adjacency Table for Directed Graphs (Entry Table)

Cost of adjacency table space for Graphs

• Undirected graph with n vertices e edges, requires (n+2e) storage units
• Directed graph with n vertices e edges, requires (n+e) storage units

### Traversal of 7.3 Graph

Given a graph G and any of its vertices V0, from V0 all vertices in G are accessed systematically, each vertex accessed only once

• dfs
• Topological Sorting

Graph Traversal Question: 1) Disconnected Graphs?2) Circuit?
Solution: Sign Location

```//A framework of traversal algorithms for Graphs
void graph_traverse(Graph&G)  {
//  Initialize the flag bits of all vertices of the graph
for (int i=0;i<G.VerticesNum();i++)
G.Mark[i] = UNVISITED;
//Check that all vertices of the graph have been marked, and if not, continue traversing from the unmarked vertex
//do_traverse function takes depth first or breadth first
for (int i=0;i<G.VerticesNum();i++)
if(G.Mark[i] = UNVISITED)
do_traverse(G,i)
```

#### 7.3.1 Depth-first traversal

• Select an inaccessible point V0 as the source point, visit vertex v0, recursively and deeply search for other vertices adjacent to v0, repeat the above process until all the vertices that are pathable from V0 have been visited
• Then select another unvisited vertex as the source point for a deep search until all vertices are visited.
```void DFS(Graph& G,int v) {  //Recursive implementation of depth-first search
G.Mark[v]=VISITED;  //Set Tag Bit to VISITED
Visit(G,v);
for(Edge e= G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e))
if(G.Mark[G.ToVertex(e)]==UNVISITED)  //Is the end point of the return edge not accessed
DFS(G,G.ToVertex(e));
}
```

#### 7.3.2 Width-first Traversal

• Starting from a vertex v0 in the graph, after the vertex v0 is visited and marked, all the adjacent points of v0 are searched horizontally one level at a time, and horizontally one level at a time for all the adjacent points until all the vertices reached by v0 with a path have been visited
• Select another unvisited vertex as the source point for a wide search until all points have been visited
```void BFS(Graph& G,int v) {
using std::queue;queue<int>Q;   //Using queues in STL
Visit(G,v);  //Access vertex v
G.Mark[v]=VISITED;  //Set Tag Bit to VISITED
Q.pop();     //Queue Top Element Queued
while(!Q.empty()) {  //If the queue is not empty
int u = Q.front();  //Get the top element of the queue
Q.pop();
for(Edge e= G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e)) //All unreached adjacent points enqueued
if(G.Mark[G.ToVertex(e)]==UNVISITED)  //Is the end point of the return edge not accessed
Visit(G,G.ToVertex(e));
G.Mark[G.ToVertex(e)]=VISITED;
Q.push(G.ToVertex(e));
}
}}
```

Time complexity of graph search
DFS and BFS access each vertex once and process each edge once (each edge of undirected graph is processed in two directions)

• Using adjacency table, directed graph cost O(n+e), undirected graph cost O(n+2e)
• Using adjacent matrix representation, total cost O(n2)

#### 7.3.3 Topological Sorting

For directed acyclic graph G=(V, E), the linear sequence of vertices in V is called a topological sequence, which satisfies:
If there is a path from vertex vi to vj in directed acyclic graph G, vertex vi must precede vertex vj in the sequence
Topological sorting refers to the process of arranging all vertices in a directed acyclic graph into a linear sequence without violating the prerequisite relationships.

```//Graph Topology Sorting by Queue
void TopsortbyQueue(Graph&G)  {
for (int i=0;i<G.VerticesNum();;i++) G.Mark[i]=UNVISITED;//Initialization
using std::queue;queue<int>Q;
for(i=0;i<G.VerticesdNum();i++) //0 vertices queued
if (G.Indegree[i]==0) Q.push(i);
while (!Q.empty()) { //Queue is not empty
int v=Q.front();Q.pop();  //Get the top element of the queue, queue
Visit(G,v);  G.Mark[v]=VISITED;   //Set marker position to VISITED
for(Edge e = G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e)) {
G.Indegree[G.ToVertex(e)]--;    //Adjacent vertex entry minus 1
if(G.Indegree[G.ToVertex(e)]==0)  //Vertex Entry Reduced to 0 Entry
Q.push(G.ToVertex(e));
}}
for(i =0;i<G.VerticesNum(); i++) //Determine if there are rings in the graph
if(G.Mark[i]==UNVISITED) {
cout<<"This graph has rings" ;  break;
}}
```

### 7.4 Shortest Path

#### 7.4.1 Single Source Shortest Path-Dijkstra Algorithm

Given a weighted graph G=<V, E>, where the weighted W[vi,vj] on each edge (vi,vj) is a non-negative real number.Calculate the shortest path from any given source point s to all other nodes

```class Dist  { //Dist class, which holds the shortest path information
public:
int index;  //Index Value of Node
int length;   //Current shortest path length
int pre;  //The last node of the path
};
void Dijkstra(Graph&G,int s,Dist*&D)  //s is the source point
D=new Dist[G.VerticesNum()]; //Record Shortest Path
for (int i=0;i<G.VerticesNum();i++) { // Initialization
G.Mark[i]=UNVISITED;
D[i].index=i;D[i].length=INFINITE ; D[i].pre = s;
}
D[s].length = 0;
MinHeap<Dist>H(G.EdgesNum());
H.Insert(D[s]);
for (i=0;i<G.VerticesNum();i++) {
bool FOUND=false;
Dist d;
while(!H.isEmpty()) {
d=H.RemoveMin();   //Obtain the node with the smallest s-path length
if(G.Mark[d.index]==UNVISITED) {  //Jump out of the loop if not accessed
FOUND=true;break;
}}
if(!FOUND) break;//Jump out of the loop if there is no shortest path that meets the criteria
int v =d.index;
G.Mark[v]=VISITED; //Set Tag Bit to VISITED
for (Edge e=G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e))//Refresh Shortest Path
if (D[G.ToVertex(e)].length>(D(e).length+G.Weight(e))) {
D[G.ToVertex(e)].length=(D(e).length+G.Weight(e))
D[G.ToVertex(e)].pre=v;
H.Insert(D[G.ToVertex(e)]);
}}
}

```

Time cost of Dijkstra algorithm
Each time you change D[i].length, do not delete it, and add a new value (smaller) as a new element in the heap.When the old value is found, the node must be marked VISITED and thus ignored; at worst, it will increase the number of elements in the heap from O(V) to O(|E|), at an overall time cost of O(|V|+|E|) log|E|).
The Dijkstra algorithm supports loops, but does not support negative weighted loops.

#### 7.4.2 Shortest path between each pair of nodes

Floyd algorithm for finding the shortest path between each pair of nodes
basic thought
After the kth iteration, the value of adj(k)[i,j] is equal to the shortest path length of the path from node vi to node vj whose sequence number is not greater than k
Analysis of Shortest Path Combination

```void Floyed(Graph& G,Dist**&D) {
int i,j,v;
D=new Dist*[G.VerticesNum()];  //Request Space
for(i=0;i<G.VerticesNum();i++)
D[i]=new Dist[G.VerticesNum()];
for(i=0;i<G.VerticesNum();i++)    //Initialization Array D
for(j=0;j<G.VerticesNum();j++)    {
if(i==j) {
D[i][j].length = 0;
D[i][j].pre = i; }
else  {
D[i][j].length = INFINITE;
D[i][j].pre = -1; }
}
for (v=0;v<G.VerticesNum();v++)
for(Edge e = G.FirstEdge(v);G.IsEdge(e);e = G.NextEdge(e)) {
D[v][G.ToVertex(e)].length=G.Weight(e);
D[v][G.ToVertex(e)].pre=v;
}  //Update those shortened path lengths after adding new nodes
for(v=0；v<G.VerticesNum();v++)
for(i=0；i<G.VerticesNum();i++)
for(j=0；j<G.VerticesNum();j++)
if(D[i][j].length > (D[i][v].length + D[v][j].length)) {
D[i][j].length = D[i][v].length + D[v][j].length
D[i][j].pre=D[v][j].pre;
}
}
```

Time complexity of Floyd algorithm
Triple for cycle O(n3)

### 7.5 Minimum Spanning Tree

concept
The spanning tree of graph G is a tree containing all the vertices of graph G. The sum of all the values in the tree represents the cost. The spanning tree with the least cost among all the spanning trees of graph G is called the minimum spanning tree of graph G (MST).

#### 7.5.1 Prim algorithm

Similar to the Dijkstra algorithm - also greedy
Start with any vertex in the graph (e.g. v0), first include this vertex in MST, U=(V*,E*), initial V*={v0}, E*={}, then look for the least weighted edge (vp), where one of its endpoints is already in the MST and the other is not yet in the MST.vq) and include vq in the MST, so proceed, adding one vertex and one edge with the least weight to the MST each time until all vertices are included in the MST. At the end of the algorithm, V*=V, E* includes n-1 edges in G.

```void Prim(Graph&G,int s,Edge*&MST)  //s is the source point, MST saves edges
int MSTtag=0;
MST=new Edge[G.VerticesNum()-1];  //Request space for array MST
Dist *D;
D=new Dist[G.VerticesNum()]; //Request space for Array D
for (int i=0;i<G.VerticesNum();i++) { // Initialization
G.Mark[i]=UNVISITED;
D[i].index=i;D[i].length=INFINITE ; D[i].pre = s;
}
D[s].length = 0;
G.Mark[s]=VISITED;
int v=s;
for (i=0;i<G.VerticesNum()-1;i++) {
for (Edge e=G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e))//Refresh Shortest Path
if (G.Mark[G.ToVertex((e)]!=VISITED && (D[G.ToVertex(e)].length > e.weight)) {
D[G.ToVertex(e)].length=G.Weight(e);
D[G.ToVertex(e)].pre=v;}
v = minVertex(G,D);  //Find the minimum value in the D array and mark it as v
if(v==-1) return;  //Disconnected with unreachable vertices
G.Mark[v]=VISITED;  //Tag Accessed
Edge edge(D[v].pre,D[v].index,D[v].length);  //Save Edge
}
}
```
```//Find Minimum in Dist Array
int minVertex(Graph &G, Dist *&D)  {
int i,v=-1;
int MinDist = INFINITY;
for (i=0;i<G.VerticesNum();i++)
if ((G.Mark[i] == UNVISITED) && (D[i]<MinDist))  {
v=i;   //Save the currently discovered minimum distance vertex
MinDist = D[i];
}
return v;
}
```

Time complexity of Prim algorithm
The Prim algorithm framework is similar to the Dijkstra algorithm in that the distance values in the Prim algorithm do not need to be accumulated and use the smallest edge directly
By directly comparing D array elements, this algorithm determines the total time O(n2) required for the least expensive edge; after removing the vertex with the least weight, it takes O(e) time to modify the D array, so it takes O(n2) time. The algorithm is suitable for dense graphs, and for sparse graphs, it can store distance values in heap as Dijkstra does.

#### 7.5.2 Kruskal algorithm

First, consider n vertices in G as independent n connected components, then the state is a forest with n vertices and no edges, which can be recorded as T=<V, {}>. Then, select the least expensive edge in E. If the edge is dependent on two different connected branches, then add it to T, otherwise, discard it and choose the next one with the least cost.By analogy, until all the vertices in T are in the same connected component, a minimum spanning tree of graph G is obtained.

```void Kruskal(Graph &G,Edge*&MST)  //MST Stores Edges of Minimum Spanning Tree
ParTree <int> A(G.VerticesNum());  //Equivalent Classes
MST=new Edge[G.VerticesNum()-1];  //Request space for array MST
int MSTtag = 0;
for (v=0;v<G.VerticesNum();v++)  //Insert all edges into minimum heap H
for(Edge e = G.FirstEdge(v);G.IsEdge(e);e = G.NextEdge(e)) {
if(G.FromVertex(e)<G.ToVertex(e))  //Anti-Repeat Edge
H.insert(e);
while(EquNum > 1)  {   //Merge equivalence classes when the number of equivalent classes is greater than 1
if(H.isEmpty())  {
cout<<"No minimum spanning tree exists." <<endl;
delete []MST;
MST = NULL;
return;
}
Edge e=H.RemoveMin();  //Minimum weight edge
int from =G.FromVertex(e);   //Record information for this edge
int to =G.ToVertex(e);
if (A.Different(from,to))  { //The two vertices of edge e are not in an equivalent class
A.Union(from,to);  //Equivalent class where the two vertices of a merged edge are located