数据结构复习之图概念及结构

知识点

图的概念

定义

图是由顶点的非空有穷集合(用V表示该集合)与顶点之间的关系(边或弧)的集合(用E表示该集合)构成的结构。
以形式化表示为G=(V,E)
其中,V为顶点的非空有穷集合,E为关系的有穷集合。

有关术语

顶点的度

所谓某个顶点V的度是指依附于该顶点的边或弧的数量,记为D(V)。无向图就是这样。
而对于有向图,要区分顶点的出度与入度的概念。出度记为OD(V),入度记为ID(V)。 D(V)=OD(V)+ID(V)。

结论

① 所有顶点的度之和等于边或弧的条数2倍。脑补:两个顶点一条边的情形。
② 具有n个顶点的无向图中边的数目最多为n(n-1)/2,脑补:三个顶点两条边的情形,三个顶点间,两两有条边相连也就是最多有3条边相连.也就是3*2/2
具有n个顶点的有向图中边(弧)的数目最多为n(n-1)。脑补两个顶点一条边,因为是有向图,所以两个顶点间有2条线

路径

两个顶点之间路径,出发点与终止点相同的路径称为环或回路。序列中顶点不重复出现的路径称为简单路径。
对于不带权的图,两个顶点之间的路径长度是指该路径上所经过的边的数目。
对于带权的图,两个顶点之间的路径长度是指该路径上所经过的边上的权值之和。

子图

边属于一个图,顶点也属于一个图。一个图最大的子图是其自身。

图连通
无向图连通

若图中任意两个顶点之间都有路径,就称该无向图是连通的。

有向图连通

若顶点Vx与Vy之间有路径,并且顶点Vy与Vx之间也有路径,就称Vx与Vy是连通的。记忆:有向图双向连通才是连通
若图中任意两个顶点之间都有连通,就称该有向图是强连通的。

连通分量

无向图中的极大连通子图称为最强连通分量。任何一个连通图的的连通分量只有一个,是它本身。非连通的无向图有多个连通分量。如下图所示:在这里插入图片描述

强连通分量:有向图中的极大强连通子图。
① 强连通图只有一个强连通分量,即是其自身。
② 非强连通的有向图有多个强连分量,如下图所示:在这里插入图片描述

图的存储结构

存储方法有邻接矩阵存储方法与邻接表存储方法。

邻接矩阵表示法

设G=(V,E)是具有n个顶点的图,则
在这里插入图片描述

特点

在这里插入图片描述

① 无向图的邻接矩阵一定是一个对称矩阵。因此,按照压缩存储的思想,在具体存放邻接矩阵时只需存放上(或者下)三角形阵的元素即可。

② 不带权的有向图的邻接矩阵一般来说是一个稀疏矩阵(特别是对于稀疏图),于是可以采用三元组表的方法存储邻接矩阵。

③ 对于无向图,邻接矩阵的第i行(或者第i列)非零元素(或者非∞元素)的个数正好是第i个顶点的度D(Vi)。

④ 对于有向图,邻接矩阵的第i行(或者第i列)非零元素(或者非∞元素)的个数正好是第i个顶点的出度OD(Vi)(或者入度ID(Vi))。

⑤ 对于无向图,邻接矩阵的所有非零元素(或者非∞元素)的个数正好是边数的2倍。

⑥ 对于有向图,邻接矩阵的所有非零元素(或者非∞元素)的个数正好等于弧数。

⑦ 一个图的邻接矩阵表示是唯一的。

邻接矩阵结构表示
#define MaxVertexNum 50  //最大顶点数
typedef Struct {
    vertexTvpe vexs[MaxVertexNum];               //顶点数组,类型假定为char型
    Adjmstrix arcs[MaxVertexNum][MaxVertexNum];  //邻接矩阵,假定为int型
}MGraph;
无向图邻接矩阵算法
#define MaxVertexNum 50  //最大顶点数
typedef Struct {
    vertexTvpe vexs[MaxVertexNum];               //顶点数组,类型假定为char型
    Adjmstrix arcs[MaxVertexNum][MaxVertexNum];  //邻接矩阵,假定为int型
} MGraph;

Void CreateMGraph(MGraph *G, int n, int e)

{  //采用邻接矩阵表示法构造无向网G,n、e表示图的当前顶点数和边数
    int i, j, k, w;
    scanf("%d,%d", &n, &e);  //读入顶点数和边数
    for (i = 0; i < n; i++)  //输入顶点信息
        scanf("%c", &G->vexs[i]);
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++) G->arcs[i][j] = INT_MAX;  //初始化邻接矩阵元素为无穷大,一般填32767
    for (k = 0; k < e; k++)                               //读入e条边,建立邻接矩阵
    //读入一条边的两端顶点序号i、j及边上的权W
    {
        scanf("%d,%d,%d", &i, &j, &w);
        G->arcs[i][j] = w;
        G->arcs[j][i] = w;  //置矩阵对称元素权值
    }
}

邻接表表示

相关软考总结:数据结构与算法基础-图
对于具有n个顶点的图建立n个线性链表。每一个链表最前面都分别设置一个称之为顶点表结点,n个顶点构成一个数组结构。第i个链表中的每一个链结点称之为边表结点。

特点

在这里插入图片描述

① 一个图的邻接表表示法不唯一,这是因为邻接表中各结点的链接次序取决于建立邻接表的算法(前插法还是后插法建链表)及边的输入次序。

② 对于无向图,若它有n个顶点,e条边,则其邻接表中需要2e+n个结点。其中有2e个边表结点,n个顶点表结点。边表结点的个数一定是偶数,为边数的2倍。

③ 对于有向图,若它有n个顶点,e条边,则其邻接表中需要e+n个结点。其中有e个边表结点,n个顶点表结点。

④ 对于无向图,第i个链表中的边表结点的数目是第i个顶点的度。

⑤ 对于有向图,第i个链表中的边表结点的数目是第i个顶点的出度。在其逆邻接表中,第i个链表中的边表结点的数目是第i个顶点的入度。

邻接表结构定义
#define MaxVertexNum 20
typedef char VertexType;
typedef struct node  //边表结点类型
{
    int adjvexj             //顶点的序号
        struct node *next;  //指向下一条边的指针
} EdgeNode;
typedef struct vnode  //顶点表结点
{
    VertexType vertex;           //顶点域
    EdgeNode *link;              //边表头指针
} VNode,Adjlist[MaxVertexNum];  //邻接表
typedef Adjlist ALGraph;         //定义为图类型
无向图邻接表算法
#define MaxVertexNum 20
typedef char VertexType;
typedef struct node  //边表结点类型
{
    int adjvexj             //顶点的序号
        struct node *next;  //指向下一条边的指针
} EdgeNode;
typedef struct vnode  //顶点表结点
{
    VertexType vertex;           //顶点域
    EdgeNode *link;              //边表头指针
} VNode, Adjlist[MaxVertexNum];  //邻接表
typedef Adjlist ALGraph;         //定义为图类型

void CreateGraph(ALGraph GL, int n, int e) {  // n为顶点数,e为图的边数
    int i, j, k;
    EdgeNode *p;
    for (i = 0; i < n; i++)  //建立顶点表
    {
        GL[i].vertex = getchar();  //读入顶点信息
        GL[i].link = NULL;         //边表头指针置空
    }
    for (k = 0; k < e; k++)  //采用头插法建立每个顶点的邻接表
    {
        scanf("%d,%d", &i, &j);                    //读入边(vi,vj)的顶点序号
        p = (EdgeNode *)malloc(sizeof(EdgeNode));  //生成新的边表结点
        p->adjvex = j;                             //将邻接点序号j赋给新结点的邻接点域
        p->next = GL[i].link;
        GL[i].link = p;                            //将新结点插入到顶点vi的边表头部
        p = (EdgeNode *)malloc(sizeof(EdgeNode));  //生成新的边表结点
        p->adj.vex = i;                            //将邻接点序号i赋给新结点的邻接点域
        p->next = GL[j].link;
        GL[j].link = p;  //将新结点插入到顶点vj的边表头部
    }
}
);  //生成新的边表结点
        p->adj.vex = i;                            //将邻接点序号i赋给新结点的邻接点域
        p->next = GL[j].link;
        GL[j].link = p;  //将新结点插入到顶点vj的边表头部
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值