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

Abstract Data Type of 7.1.2 Diagram

Storage structure of 7.2 diagrams

Adjacent Matrix

  • 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
  • Weighted adjacency table representation
  • 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
  • breadth-first search
  • 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)

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
   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
   PostVisit(G,v)   //Post-access to vertex v

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

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
    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
   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
       D[i].index=i;D[i].length=INFINITE ; D[i].pre = s;
    D[s].length = 0;
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
   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))) {

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
Using adjacent matrix adj to represent weighted directed graph
Initialize adj as adjacent matrix
Do n iterations on the matrix adj(0) to produce a matrix adj(!),adj(2),...adj(n)
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
         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)) {
          }  //Update those shortened path lengths after adding new nodes
                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

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

7.5 Minimum Spanning Tree

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
       D[i].index=i;D[i].length=INFINITE ; D[i].pre = s;
    D[s].length = 0;
    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)) {
    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
    AddEdgetoMST(edge,MST,MSTtag++);  //Add Edge to MST
//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
   int EquNum = G.VerticesNum();   //Start with n independent vertex equivalents
   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;
       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
           AddEdgetoMST(e,MST,MSTtag++);         //Add e Edge to MST
           EquNum--;    //Number of equivalent classes minus 1

The time cost of Kruskal algorithm is close to O(Nloge)

34 original articles published, 3 praised, 9389 visits
Private letter follow

Topics: less