数据结构之图:简介

2018-11-08  本文已影响17人  jdzhangxin

1. 概念

图是一种复杂的非线性结构。图G由两个集合V(顶点Vertex)和E(边Edge)组成,定义为G=(V,E)

2. 分类

图的种类

2.1 按照边的类型分类

图的边有两种类型:

No. 边的类型 说明
1 无向边(Undirected Edge) 顶点V1到顶点V2的边没有方向。用无序偶对(V1,V2)表示。
2 有向边/弧(Directed Edge)/(Arc) 顶点V1到顶点V2的边有方向。用有序偶对<V1,V2>表示。

按照边的类型,图可以分为三类:

  1. 无向图(Undigraph):任意两顶点之间的边都是无向边

    • 无向图表示:G=(V,E)
    • 顶点集合:V(G)=\{V1,V2,V3,V4,V5\}
    • 边集:E(G)=\{(V1,V2),(V1,V4),(V2,V3),(V2,V5),(V3,V4),(V3,V5),(V4,V5)\}
  2. 有向图(Digraph):任意两顶点之间的边都是有向边

    • 无向图表示:G=(V,E)
    • 顶点集合:V(G)=\{V1,V2,V3\}
    • 边集:E(G)=\{<V1,V2>,<V2,V3>,<V3,V1>,<V1,V3>\}
  3. 混合图(Mixed Graph):有向边与无向边同时存在的图。

2.2 按照边数多少分类

  1. 稀疏图(Sparse Graph)
    有很少条边或弧(边数E远小于顶点数平方V^2)
  2. 稠密图(Dense Graph)
    有很多条边或弧(边数E接近顶点数平方V^2)

2.3 按照边上是否带有数值

3. 表示法

3.1 对象顶点和边关系

图由顶点和边构成,这样就存在两种关系。

  1. 邻接关系(Adjacency):顶点与顶点的关系
  2. 关联关系(Incidence):顶点以及与它相关的边的关系

3.2 表示法

图的表示法有以下三种

  1. 邻接表(Adjacency List)
  2. 邻接矩阵(Adjacency Matrix)
  3. 关联矩阵(Incidence Matrix)
图的表示法

说明

  1. 无向图边数组是对称矩阵。
  2. 邻接矩阵和关联矩阵合适稠密图;邻接表合适稀疏图。
  3. 邻接矩阵和关联矩阵使用数值1表示顶点存在边,数值0表示顶点不存在边;网(Network)使用权值表示存在边,使用表示不存在边。

3.3 存储方式

No. 类型 C++表示方式
1 邻接表(Adjacency List) vector<顶点数据类型>[顶点数]
2 邻接矩阵(Adjacency Matrix) 顶点数据类型 [顶点数][顶点数]
3 关联矩阵(Incidence Matrix) 顶点数据类型 [顶点数][边数]

在笔试中,通常使用邻接表存储图。

#include <bits/stdc++.h>
using namespace std;

int main(){
   int n = 0; // 顶点数
   int m = 0; // 边数
   scanf("%d%d",&n,&m);
   vector<int> vec[n+1]; // 邻接表,下标表示顶点
   for(int i=0;i<m;++i){
       int u = 0;
       int v = 0;
       scanf("%d%d",&u,&v);
       vec[u].push_back(v);
       vec[v].push_back(u);// 无向图两个顶点要各记录一次
   }
   return 0;
}
#include <bits/stdc++.h>
using namespace std;

int main(){
   int n = 0; // 顶点数
   int m = 0; // 边数
   scanf("%d%d",&n,&m);
   vector<int> vec[n+1]; // 邻接表,下标表示顶点
   for(int i=0;i<m;++i){
       int u = 0;
       int v = 0;
       scanf("%d%d",&u,&v);
       vec[u].push_back(v);
   }
   return 0;
}

4. 图的遍历(Traversing Graph)


4.1 基本原理

  1. 深度优先遍历(DFS:Depth First Search)
  1. 广度优先遍历(BFS:Breadth First Search)

4.2 基本框架

遍历 技术
DFS 栈/递归(LIFO,先进先出)
BFS 队列(FIFO,先进先出)
DFS基本流程
BFS基本流程

应用

获取图DFS和BFS后的元素序列。把二维网状结构转变成一维线性结构

vector<int> bfs(vector<int>* vec, int v){
    vector<int> res;
    queue<int> q; // 使用队列
    res.push_back(v);
    q.push(v);
    while(!q.empty()){
        int now = q.front();
        q.pop();
        for(int i=0;i<vec[now].size();++i){
            int post = vec[now][i];
            if(find(res.begin(),res.end(),post) == res.end()){
                res.push_back(post); // 入队时记录已被访问
                q.push(post);
            }
        }
    }
    return res;
}
vector<int> dfs(vector<int>* vec, int v){
    vector<int> res;
    stack<int> s; // 使用栈
    s.push(v);
    while(!s.empty()){
        int now = s.top();
        res.push_back(now);// 出栈时记录已被访问
        s.pop();
        for(int i=0;i<vec[now].size();++i){
            int post = vec[now][i];
            if(find(res.begin(),res.end(),post) == res.end()){
                s.push(post);
            }
        }
    }
    return res;
}
上一篇 下一篇

猜你喜欢

热点阅读