数据结构:图及其邻接矩阵与邻接表表示
2017-12-14 18:34
381 查看
图
六度空间理论
图中两个顶点若要联系,最多通过6个结点便可以完成 。基本概念
图用于表示“多对多”的关系。包含
一组顶点:通常用V (Vertex) 表示顶点集合
一组边:通常用E (Edge) 表示边的集合
边是顶点对:(v, w) E ,其中v, w V
有向边< v, w> 表示从v指向w的边(单行线)
不考虑重边和自回路
重边:两个顶点之间有两条边。
自回路:一个顶点的边指向自己。
抽象数据类型定义
类型名称:图(Graph)数据对象集:G(V,E)由一个非空的有限顶点集合V和一个有限边集合E组成。
操作集:对于任意图G Graph,以及v V, e E
Graph Create():建立并返回空图;
Graph InsertVertex(Graph G, Vertex v):将v插入G;
Graph InsertEdge(Graph G, Edge e):将e插入G;
void DFS(Graph G, Vertex v):从顶点v出发深度优先遍历图G;
void BFS(Graph G, Vertex v):从顶点v出发宽度优先遍历图G;
void ShortestPath(Graph G, Vertex v, int Dist[]):计
算图G中顶点v到任意其他顶点的最短距离;
void MST(Graph G):计算图G的最小生成树;
怎么在程序中表示一个图
对顶点进行编号。顶点序号所对应在邻接矩阵中的值为1。
因为没有自回路,所以对角线全为0。
无向图为对称矩阵。
问题:对于无向图的存储,怎样可以省一半空间?
用一个长度为N(N+1)/2的1维数组A存储{G00,G10,G11,……,Gn-1 0,…,Gn-1 n-1},则Gij在A中对应的下标是:(i*(i+1)/2+j)。-对于网络,只要把G[i][j]的值定义为边
邻接矩阵—— 有什么好处?
直观、简单、好理解方便检查任意一对顶点间是否存在边
方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
方便计算任一顶点的“度”(从该点发出的边数为“出
度”,指向该点的边数为“入度”)
无向图:对应行(或列)非0元素的个数
有向图:对应行非0元素的个数是“出度”;对应列非0元素的
个数是“入度”
邻接矩阵—— 有什么不好?
浪费空间—— 存稀疏图(点很多而边很少)有大量无效元素对稠密图(特别是完全图)还是很合算的
浪费时间—— 统计稀疏图中一共有多少条边
邻接表
G为指针数组,对应矩阵每行一个链表,只存非0元素
邻接矩阵—— 有什么好处?
方便找任一顶点的所有“邻接点”节约稀疏图的空间:需要N个头指针+2E(每个节点至少两个域)
方便计算任一顶点的“度”?:对无向图:是的,对又想吐只能计算出度,需要构造“逆邻接表”计算入度。
邻接矩阵—— 有什么不好?
不方便检查任意一对顶点间是否存在边。代码实现
设定初始参数,最大值和权值顶点数设定边结点,用于连接顶点。
设定图结点,建立顶点数,边数,表示关系的邻接矩阵。
设定插入函数,把边插入到图当中。
设定参数
设定INFINITY为最大值,便于权值的比较。```
define MaxVertexNum 100 /* 最大顶点数设为100 */
define INFINITY 65535 /* ∞设为双字节无符号整数的最大值65535/
typedef int Vertex; / 用顶点下标表示顶点,为整型 /
typedef int WeightType; / 边的权值设为整型 /
typedef char DataType; / 顶点存储的数据类型设为字符型 */
### 设定边结点 - 包括边结点、边结点的指针、边连接的两个顶点和边的权重。
/* 边的定义 /
typedef struct ENode PtrToENode;
struct ENode{
Vertex V1, V2; /* 有向边
### 设定图结点 - 包括图结点、图结点的指针、包含的顶点数、边数、图的邻接矩阵、顶点存储的数据。
/* 图结点的定义 /
typedef struct GNode PtrToGNode;
struct GNode{
int Nv; /* 顶点数 /
int Ne; / 边数 /
WeightType G[MaxVertexNum][MaxVertexNum]; / 邻接矩阵 /
DataType Data[MaxVertexNum]; / 存顶点的数据 /
/ 注意:很多情况下,顶点无数据,此时Data[]可以不用出现 /
};
typedef PtrToGNode MGraph; / 以邻接矩阵存储的图类型 */
### 创建一个图 - 创建一个图结点并将顶点初始化,返回指针。
MGraph CreateGraph( int VertexNum )
{ /* 初始化一个有VertexNum个顶点但没有边的图 */
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */ Graph->Nv = VertexNum; Graph->Ne = 0; /* 初始化邻接矩阵 */ /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */ for (V=0; V<Graph->Nv; V++) for (W=0; W<Graph->Nv; W++) Graph->G[V][W] = INFINITY; return Graph;
}
### 将边插入到顶点当中 - 接受一个边结点,把对应值的关系储存。 - 若是无向图要储存两次。
void InsertEdge( MGraph Graph, Edge E )
{
/* 插入边
### 建立图
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv, i;
scanf("%d", &Nv); /* 读入顶点个数 */ Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ scanf("%d", &(Graph->Ne)); /* 读入边数 */ if ( Graph->Ne != 0 ) { /* 如果有边 */ E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */ for (i=0; i<Graph->Ne; i++) { scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); /* 注意:如果权重不是整型,Weight的读入格式要改 */ InsertEdge( Graph, E ); } } /* 如果顶点有数据的话,读入数据 */ for (V=0; V<Graph->Nv; V++) scanf(" %c", &(Graph->Data[V])); return Graph;
}
```
相关文章推荐
- 第十一周 项目一 数据结构之自建算法库——图及其存储结构(邻接矩阵、邻接表)
- 再回首,数据结构——以邻接矩阵、邻接表表示的图的深度、广度优先搜索
- 数据结构之自建算法库——图及其存储结构(邻接矩阵、邻接表)
- 数据结构之图的存储表示(邻接矩阵、邻接表和边集数组)
- 数据结构之---C语言实现图的邻接表存储表示
- 【数据结构】图的存储方式:邻接矩阵和邻接表
- 第十一周——项目一—图及其存储结构(邻接矩阵、邻接表)算法库
- 【数据结构】图的邻接表表示(GNU C++实现)
- 数据结构之---C语言实现图的数组(邻接矩阵)存储表示
- 数据结构之自建算法库——图及其存储结构(邻接矩阵、邻接表)
- 【数据结构】图的存储方式:邻接矩阵和邻接表
- (编程训练)再回首,数据结构——无向图的邻接矩阵表示、DFS、BFS
- 看数据结构写代码(35) 图的邻接矩阵表示法
- 图(网)的存储结构(数组存储表示即邻接矩阵、邻接表)
- 【数据结构】图Graph的邻接矩阵,邻接表及深度、广度遍历
- 数据结构——图的数组实现(邻接矩阵表示法)
- js 数据结构中邻接矩阵的图的直观表示
- 第十一周-项目1-图及其存储结构(邻接矩阵、邻接表)
- 【数据结构】图的存储方式:邻接矩阵和邻接表
- 数据结构—图的存储—邻接表和邻接矩阵