数据结构之图的基本概念

图的基本概念

1、图的定义

G G G由顶点集 V V V和边集 E E E组成,记为 G = ( V , E ) G=(V,E) G=(V,E),其中 V ( G ) V(G) V(G)表示图 G G G中顶点的有限非空集; E ( G ) E(G) E(G)表示图 G G G中顶点之间的关系(边)集合。若 V = { v 1 , v 2 , . . . , v n } V=\{v_1,v_2,...,v_n\} V={v1,v2,...,vn},则用 ∣ V ∣ |V| V表示图 G G G中顶点的个数,也称图 G G G的阶, E = { ( u , v ) ∣ u ∣ ∈ V , v ∈ V } E=\{(u,v)|u|\in V,v \in V\} E={(u,v)uV,vV},用 ∣ E ∣ |E| E表示图 G G G中边的条数。

注:线性表可以是空表,树可以是空树,但图不可以是空,即V一定是非空集。

2、无向图、有向图

3、简单图、多重图

4、顶点的度、入度、出度

  • 无向图:顶点 v v v的度是指依附于该顶点的边的条数,记为 T D ( v ) TD(v) TD(v)
  • 有向图:入度是以顶点 v v v为终点的有向边的数目,记为 I D ( v ) ID(v) ID(v);出度是以顶点 v v v为起点的有向边的数目,记为 O D ( v ) OD(v) OD(v)

5、顶点—顶点的关系描述

  • 路径:顶点 v p v_p vp到顶点 v q v_q vq之间的一条路径是指顶点序列。
  • 回路:第一个顶点和最后一个顶点相同的路径。
  • 简单路径:顶点不重复出现的路径。
  • 简单回路:除第一个顶点和最后一个顶点外,顶点不重复出现的路径。
  • 路径长度:路径上边的数目。
  • 点到点距离:最短路径的长度;若不存在,记为无穷。
  • 无向图的连通,有向图的强连通。

6、连通图、强连通图

  • 对于n个顶点的无向图G,若G是连通图,则最少有n-1条边;若G是非连通图,则最多可能有
  • 对于n个顶点的有向图G,若G是强连通图,则最少有n-1条边

7、子图

8、连通分量:无向图中的极大连通子图。

9、强连通分量:有向图的极大强连通子图。

10、边的权、带权图

  • 边的权:在一个图中,每条边都可以标上具有某种含义的数值。
  • 带权图:边上带有权值的图。
  • 带权路径长度:带权图上的一条路径上所有边的权值之和。

图的存储

邻接矩阵法

  • 不带权的图
#define MaxVertexNum 100                  //顶点数目的最大值
typedef struct {                          
    char vex[MaxVertexNum];               //顶点表
    int edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表
    int vexNum, arcNum;                   //图的当前顶点数和边数
}MGraph;
  • 带权图
#define MaxVertexNum 100                          //顶点数目的最大值
#define INFINITY INT_MAX                          //宏定义常量“无穷”
typedef char VertexType;                          //顶点的数据类型
typedef int EdgeType;                             //带权图中边上权值的数据类型
typedef struct {
    VertexType vex[MaxVertexNum];                 //顶点表
    EdgeType edge[MaxVertexNum][MaxVertexNum];    //边表
    int vexNum, arcNum;                           //图的当前顶点数和边数
}Mgraph;

缺点:数组实现的顺序存储,空间复杂度高,不适合存储稀疏图。

邻接表法(顺序+链式存储)

#define MaxVertexNum 100                          //顶点数目的最大值
typedef char VertexType;                          //顶点的数据类型
typedef int InfoType;                             //带权图中边上权值的数据类型
//"边"
typedef struct ArcNode {
    int adjVex;                                   //边指向哪个顶点
    struct ArcNode* next;                         //指向下一条边的指针
    //InfoType info;                              //边权值
}ArcNode;

//"顶点"
typedef struct VNode {
    VertexType data;           //顶点信息
    ArcNode* first;            //第一条边
}VNode, AdjList[MaxVertexNum];

//用邻接表存储的图
typedef struct {
    AdjList vertices;
    int vexNum, arcNum;
}ALGraph;

图的广度优先遍历

BFS要点:

  1. 找到与一个顶点相邻的所有顶点
  2. 标记哪些顶点被访问过
  3. 需要一个辅助队列

伪代码

bool visited[MAX_VERTEX_NUM];      //访问标记数组
void BFSTraverse(Graph G) {        //对图G进行广度优先遍历
    for(int i = 0; i < G.vexNum; i++) {
        visited[i] = FALSE;        //访问标记数组初始化
    }
    InitQueue(Q);        //初始化辅助队列Q                  
    for(int i = 0; i < G.vexNum; i++) { 
        if (!visited[i]) {
            BFS(G, i);
        }
    }
}

void BFS(Graph G, int v) { //从顶点v出发,广度优先遍历图G
    visit(v);              //访问初始顶点v
    visited[v] = TRUE;     //对v做已访问标记
    Enqueque(Q,v);         //顶点v入队列Q
    while(!isEmpty(Q)) {
        DeQueue(Q,v);                 //顶点v出队列
        for (w=FirstNeighbor(G,v); w >= 0; w=NextNeighbor(G,v,w)) {
            //检测v所有邻接点
            if(!visited[w]) {         //w为v的尚未访问的邻接顶点
                visit(w);             //访问顶点w
                visited[w] = TRUE;    //对w做已访问标记
                EnQueue(Q,w);         //顶点w入队列
            }
        }
    }
}

图的深度优先遍历

伪代码

bool visited[MAX_VERTEX_NUM];

void BFSTraverse(Graph G) {       
    for(int i = 0; i < G.vexNum; i++) {
        visited[i] = false;        
    }          
    for(int i = 0; i < G.vexNum; i++) { 
        if (!visited[i]) {
            DFS(G, i);
        }
    }
}

void DFS(Graph G, int v) {
    visit(v);
    visited[v] = true;
    for (int w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w)) {
        if (!visited[w]) {
            DFS(G,w);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值