图
图
图的定义
什么是图? 图是由顶点和边组成的,表示为G(V,E),G表示一个图,V是顶点的集合,E是边的集合。
多对多
- 线性表中的数据元素叫元素,树中的叫结点,图中的叫顶点
- 图的结构中不允许没有顶点(至少一个顶点)
- 图中顶点之间的逻辑关系我们用边来表示,边集可以是空的。
相关定义
无向边:两个顶点之间的边没有方向,用’()‘表示。
有向边:两个顶点之间的边是有方向的,用’<>‘表示,<a,b>和<b,a>不一样。
简单图:不存在顶点到自身的边,且任意两顶点之间只有一条边的图。
无完全向图:任意两个顶点之间都存在边的无向图
有向完全图:任意两个顶点之间都存在方向互为相反的两条弧。
权:图的边或弧的一些相关数字。
带权的图我们一般称为网。
子图:图G=(V,{E}),图G’=(V’,{E’})。 如果V’包含于V且E’包含于E。则称G’为G的子图。
图的顶点和边之间的关系
无向图的度:在无向图中,顶点v和v’之间存在边e,则v和v’为邻接点,我们说e与顶点v,v’相关联。顶点v的度是和v相关联的边的个数。边数=顶点度数和/2.
有向图的出度入度: 在有向图G=(V,{E})中,如果弧<v,v’>∈E.则v’邻接自顶点v.弧<v,v’>和顶点v,v’相关联。终点指向v的弧的数目称为v的入度,起点是v的弧的数目称为v的出度。在整个图中,∑出度=∑入度。
图的路径: 从顶点v到另一个顶点v’的路径是一个顶点序列。(注意有向图的单向性),路径的长度是路径上的边或弧的数目
环(回路):如果一条路径的第一个顶点和最后一个顶点相同,这个路径我们称为环,在这个环中其余顶点不重复出现,则为简单环。
连通图相关术语:
- 无向图的连通图:图中的任意两个顶点都是连通的。(什么是连通?顶点v到顶点v’有路径,我们就称v和v’是连通的)
- 无向图的极大连通子图(又称为连通分量):强调子图且连通,极大顶点数,包含依附于这些顶点的所有边。
- 有向图的强连通图:图G中,对每一对vi,vj,vi到vj和vj到vi都存在路径,则G为强连通图。 有向图的极大连通子图称为有向图的强连通分量。
- 连通图的生成树:是这个连通图的极小生成子图,含有图中的全部n个顶点,但是只有足已构成一棵树的n-1条边。
小总结:
图的存储结构
邻接矩阵
定义
用两个数组表示图,一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。
用邻接矩阵可以较为方便的知道两个顶点是否有边:arc[i][j]!=0,某个顶点i的度:∑j arc[i][j] ,顶点i的所有邻接点:arc[i][j]!=0的j。
无向图:
有向图:arc[i][j]表示从i到j的弧。
网图:用权值来代替原先的0/1.
代码
typedef struct{
char vex[100]; //顶点表
int arc[100][100];// 边表
int numVer,numEdge; //顶点个数和边数。
}MGraph;
邻接表(较邻接矩阵节省空间)
定义
可以类比树中的孩子表示法。所有的顶点用一维数组存储,但声明一个指针域指向边表的第一个邻接顶点。之后依次指向所有的该顶点的邻接顶点。
无向图:
有向图中,我们一般认为指针域指向的顶点作为弧终点。(也可以反过来,自己定义)
带权图就是声明一个权值域就可以。
代码
#include <stdio.h>
#include <malloc.h>
typedef char VertexType;
typedef int EdgeType;
//边表
typedef struct EdgeNode{
int adjvex; //邻接点,存储该顶点对应下标
EdgeType weight; //权值,不带权图可以不需要
struct EdgeNode *next; //链域,指向下一个邻接点
}EdgeNode;
// 顶点表
typedef struct VertexNode {
VertexType data; //顶点域
EdgeNode *firstEdge; //表头指针。
}VertexNode,AdjList[100];
struct GraphAdjList{
AdjList adjList;
int numVertex,numEdges; //顶点数和边数。
};
//无向图的邻接表创建
void CreateALGraph(GraphAdjList *G){
int i,j,k;
EdgeNode *e;
//printf("输入边数和点数:\n");
scanf("%d,%d",&G->numVertex,&G->numEdges); //读入顶点数和边数
//读入顶点的信息,建立顶点表
for(i=0;i<G->numVertex;i++){