[Data Structure] Diagram

graph concept

write picture description here
1. Graph
  A graph is a nonlinear data structure consisting of a set of vertices and the relationship (edge) between vertices; G=(V, E), where the vertex set V is a finite non-empty set; E={(x,y) | x, y属于V}或E={<x,y> | x, y属于V}it is a relationship between vertices. A finite set, also known as a set of edges; the first type of parentheses represents a bidirectional path from x to y, that is: (x,y)and (y,x)is an edge, and the graph formed by such edges and vertices is called an undirected graph; the second type of angle brackets Represents a one-way path from x to y, that is to say: <x, y>an edge from x to y is <y,x>not the same, and the graph composed of such edges and vertices is called a directed graph.
  
2. Complete graph
  In an undirected graph, if there is and only one edge between any two vertices, that is, if there are n vertices, there are n*(n-1)/2 edges, then the graph is called An undirected complete graph;
  in a directed graph, if there are only opposite edges between any two vertices, then the graph is called a directed complete graph; if there are n edges, then there are n*(n- 1) The edge.
  
3. Adjacent vertices
  In an undirected graph, if it (x,y)is an edge in the graph, then x and y are called adjacent vertices, and the edge (x, y) is attached to vertices x and y;
  in a directed graph, if it <x,y>is a graph An edge in the vertex x is said to be adjacent to y, y is adjacent to x, and the edge (x, y) is associated with vertices x, y.
  
4. Degree of a vertex: The degree of a vertex is the number of edges associated with the vertex. In an undirected graph, we call the number of edges with vertex v as the end point as the in-degree, and the number of edges with the vertex v as the starting point as the out-degree. The sum of the out degrees.

5. Weight: data information attached to the edge
For example :
write picture description here
6. Path and path length
  If there is a set of edges from vertex x that can reach vertex y, this set of edges is called the path from vertex x to vertex y.
  For an unweighted graph: the path length is the number of edges on the path; for a weighted graph, the path length is the sum of the weights of each edge on the path.
  
7. Subgraph: Let graph G={V, E} and graph G1={V1, E1}, if V1 belongs to V and E1 belongs to E, then G1 is called a subgraph of G.

8. Connected and strongly connected graphs
  In an undirected graph , if there is a path between any two vertices, the graph is called a connected graph; a connected graph with n vertices has at least n-1 edges.
  In a directed graph , if there is a path from v1 to v2 and from v2 to v1 between any two vertices v1 and v2, then this graph is called a strongly connected graph.
  
9. Spanning tree: The minimal connected subgraph of a connected graph is called the spanning tree of the graph. Spanning tree is not unique.
write picture description here

storage of graphs

adjacency matrix

  We will use an array to represent the set of vertices, and a matrix to represent the relationship between the vertices .
For example:
write picture description here
you can see that if it is an undirected graph , the adjacency matrix we get is symmetric.
code show as below:

#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
template <class V, class W, bool IsDirect = false>//false表示为无向图
class Graph
{
public:
     Graph(const V* arr, size_t size)
          : _v(arr, arr + size)
     {
          _edges.resize(size);
          for (size_t i = 0; i < size; i++)
               _edges[i].resize(size);
     }
     int GetIndex(const V& v)
     {
          for (size_t i = 0; i < _v.size(); i++)
          {
               if (_v[i] == v)
                    return i;
          }
          assert(false);
          return -1;
     }
     void AddEdges(const V v1, const V v2, const W& weight)//存储边
     {
          size_t index1 = GetIndex(v1);
          size_t index2 = GetIndex(v2);
          _edges[index1][index2] = weight;
          if (!IsDirect)//无向图需要两次,有向图只需要一次  false为无向图
               _edges[index2][index1] = weight;
     }
     void Print()//打印矩阵
     {
          for (size_t i = 0; i < _v.size(); i++)
          {
               printf("%c ", _v[i]);
               for (size_t j = 0; j < _v.size(); j++)
               {
                    printf("%2d  ", _edges[i][j]);
               }
               cout << endl;
          }
     }
     size_t Dev(const V& v)//计算顶点的度
     {
          size_t index = GetIndex(v);
          size_t count = 0;//false表示无向图,无向图度的计算是遍历一行,
                           //true是有向图,有向图度的计算:出度+入度
          for (size_t i = 0; i < _v.size(); i++)
          {
               if (_edges[index][i] > 0)
                    count++;
               if (IsDirect && _edges[i][index] > 0)
                    count++;
          }
          return count;
     }
private:
     vector<V> _v;
     vector<vector<W>> _edges;
};

  For a weighted graph , we can change 1 to the weight; if there is no edge, we can change 0 to infinity; the edge on the diagonal from itself to itself is still 0.
  Using the adjacency matrix to store the graph structure, there may be many vertices but few edges. At this time, there will be a large number of 0 elements, resulting in a waste of space.

adjacency list

  Use an array to represent a collection of vertices, and use a linked list to represent the relationship of edges . Store the index of the vertex in the array into the data field of the linked list.
  For undirected graphs, each edge appears twice in the adjacency list; to calculate the degree of a node , just traverse the linked list corresponding to vi once. For example, in the figure below, the degree of A is 2, and the degree of D is 1.
  For a directed graph, each edge appears only once in the adjacency list; pairing with vertex vi gives you an adjacency list, the number of its nodes is out-degree; the edge linked list corresponding to all other vertices is detected, and the number of dst i in the node is the in-degree. For example: the out-degree of A is 1 and the in-degree is 1, so the degree of A is 2.
  For a directed graph, we can choose an out-degree table or an in-degree table . The out-degree table, in short, means that the subscript corresponding to the vertex pointed to by the arrow is stored in the linked list node; the in-degree table, the vertex corresponding to the root of the arrow subscript. As shown in the figure below:
For example:
write picture description here
look at the code below:

#include <vector>
#include <iostream>
using namespace std;
template <class W>
struct Node
{
     Node(const W& weight, size_t src, size_t dst)
     : _weight(weight)
     , _src(src)
     , _dst(dst)
     , _pNext(NULL)
     {}
     W _weight;
     size_t _src;
     size_t _dst;
     Node* _pNext;
};
template <class V, class W, bool IsDirect = false>//无向图为false;有向图为true
class Graph
{
     typedef Node<W> Node;
     typedef Node* pNode;
public:
     Graph(const V* arr, size_t size)
          : _v(arr, arr + size)
     {
          _linkEdges.resize(size);
     }
     int GetIndex(const V& v)
     {
          for (size_t i = 0; i < _v.size(); i++)
          {
               if (_v[i] == v)
                    return i;
          }
          return -1;
     }
     void AddEdges(const V& v1, const V& v2, const W& weight)
     {
          size_t srcIndex = GetIndex(v1);
          size_t dstIndex = GetIndex(v2);
          _Add(srcIndex, dstIndex, weight);
          if (!IsDirect)//false 无向图
               _Add(dstIndex, srcIndex, weight);
     }
     size_t Dev(const V& v)
     {
          size_t count = 0;
          size_t index = GetIndex(v);
          pNode pCur = _linkEdges[index];
          while (pCur)//如果是无向图,直接计算度,如果是有向图先计算出度
          {
               count++;
               pCur = pCur->_pNext;
          }
          if (IsDirect)
          {
               for (size_t i = 0; i < _v.size(); i++)//计算有向图的入度
               {
                    if (i != index)
                    {
                         pCur = _linkEdges[i];
                         while (pCur)
                         {
                              if (pCur->_dst == index)
                                   count++;
                              pCur = pCur->_pNext;
                         }
                    }
               }
          }
          return count;
     }
private:
     void _Add(const size_t src, const size_t dst, const W& weight)
     {
          pNode pNew = new Node(weight, src, dst);
          pNode pCur = _linkEdges[src];
          while (pCur)
          {
               if(pCur->_weight == weight)
                    return;
               pCur = pCur->_pNext;
          }
          pNew->_pNext = _linkEdges[src];
          _linkEdges[src] = pNew;
     }
private:
     vector<V> _v;
     vector<pNode> _linkEdges;
};

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324689928&siteId=291194637