【数据结构】图的存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)及实现(C语言)
目录
- 1. 邻接矩阵表示法
- 1.1 图的邻接矩阵
- 1.2 创建有向网的邻接矩阵
- 2. 邻接表表示法
- 2.1 图的邻接表存储结构
- 2.2 创建有向图的邻接表
- 3. 十字链表表示法
- 3.1 图的十字链表存储结构
- 3.2 创建有向图的十字链表
- 4. 邻接多重表
- 4.1 邻接多重表的存储结构
- 4.2 创建无向图的邻接多重表
1. 邻接矩阵表示法
1.1 图的邻接矩阵
图的邻接矩阵表示法(Adjacency Matrix)也称作数组表示法。它采用两个数组来表示图:一个是用于存储顶点信息的一维数组,另一个是用于存储图中顶点之间关联关系的二维数组,这个关联关系数组被称为邻接矩阵。
有向图的邻接矩阵可以指示弧的方向;无向图的邻接矩阵没有方向,所以是对称矩阵;
稀疏图不适于用邻接矩阵来存储,会造成空间浪费。
1.2 创建有向网的邻接矩阵
# include<stdio.h>
# define MAX_VERTEX_NUM 20 //最多顶点个数
# define INFINITY 32768 //表示极大值,即∞/*图的邻接矩阵表示法*/
typedef int AdjType;
typedef char VertexData;
typedef struct ArcNode {AdjType adj; //无权图用1或0表示是否相邻,带权图则为权值类型
}ArcNode;
typedef struct {VertexData vertex[MAX_VERTEX_NUM]; //顶点向量ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵int vexnum, arcnum; //图的顶点数和弧数
}AdjMatrix;/*采用邻接矩阵表示法创建有向网*/
/*求顶点位置*/
int LocateVertex(AdjMatrix* G, VertexData v) {int k;for (k = 0; k < G->vexnum; k++) {if (G->vertex[k] == v)break;}return k;
}/*创建有向网*/
int CreateDN(AdjMatrix* G) {int i, j, k, weight;VertexData v1, v2;printf("输入图的顶点数和弧数:"); //输入图的顶点数和弧数scanf("%d%d", &G->vexnum, &G->arcnum);for (i = 0; i < G->vexnum; i++) { //初始化邻接矩阵for (j = 0; j < G->vexnum; j++)G->arcs[i][j].adj = INFINITY;}printf("输入图的顶点:");for (i = 0; i < G->vexnum; i++) //输入图的顶点scanf(" %c", &G->vertex[i]);for (k = 0; k < G->arcnum; k++) {printf("输入第%d条弧的两个顶点及权值:", k + 1);scanf(" %c %c %d", &v1, &v2, &weight); //输入一条弧的两个顶点及权值i = LocateVertex(G, v1);j = LocateVertex(G, v2);G->arcs[i][j].adj = weight; //建立弧}
}/*邻接矩阵的输出*/
void AdjMatrixDisplay(AdjMatrix* G) {printf("图的邻接矩阵输出:\n");int i, j;for (i = 0; i < G->vexnum; i++) {printf("\t%c", G->vertex[i]);}printf("\n");for (i = 0; i < G->vexnum; i++) { //输出邻接矩阵printf("%c\t", G->vertex[i]);for (j = 0; j < G->vexnum; j++) {if (G->arcs[i][j].adj == INFINITY)printf("∞\t");elseprintf("%d\t", G->arcs[i][j].adj);}printf("\n");}
}int main() {AdjMatrix G;CreateDN(&G);AdjMatrixDisplay(&G);return 0;
}
运行结果
2. 邻接表表示法
2.1 图的邻接表存储结构
邻接表(Adjacency List)表示法是图的一种链式存储结构,它只存储图中存在的边信息。在邻接表中,对图中的每一个顶点建立一个带头结点的边链表,每个边链表的头结点又构成一个表头结点表。这样,一个n个顶点的图的邻接表表示由表头结点与边表两部分构成。
① 表头结点表:由所有表头结点以顺序结构(向量)的形式存储,以便可以随机访问任一顶点的边链表。表头结点由两部分组成,其中数据域vexdata用于存储顶点的名或其它相关信息;链域firstarc用于指向链表中第一个顶点。
② 边表:由表示图中顶点间邻接关系的n个边链表组成。边链表的弧结点结构由三部分组成,邻接点域adjvex用于存放与顶点vi相邻接的顶点在图中的位置;链域nextarc用于指向与顶点vi相关联的下一条边或弧的结点;数据域info用于存放与边或弧相关的信息(如赋权图中每条边或弧的权值)。
# define MAX_VERTEX_NUM 20 //最多顶点个数/*图的邻接表表示法*/
typedef char VertexData;
//弧结点结构
typedef struct ArcNode {int adjvex; //该弧指向顶点的位置struct ArcNode* nextarc; //指向下一条弧的指针int info; //与弧相关的信息
}ArcNode;
//表头结点结构
typedef struct VertexNode {VertexData data; //顶点数据ArcNode* firstarc; //指向该顶点的第一条弧的指针
}VertexNode;
//邻接表结构
typedef struct {VertexNode vertex[MAX_VERTEX_NUM];int vexnum, arcnum; //图的顶点数和弧数
}AdjList;
2.2 创建有向图的邻接表
/*采用邻接表表示法创建有向图*/
/*求顶点位置*/
int LocateVertex(AdjList* G, VertexData v) {int k;for (k = 0; k < G->vexnum; k++) {if (G->vertex[k].data == v)break;}return k;
}/*创建有向图*/
int CreateAdjList(AdjList* G) {int i, j, k;VertexData v1, v2;ArcNode* p;printf("输入图的顶点数和弧数:"); //输入图的顶点数和弧数scanf("%d%d", &G->vexnum, &G->arcnum);printf("输入图的顶点:");for (i = 0; i < G->vexnum; i++) { //输入图的顶点,初始化顶点结点scanf(" %c", &(G->vertex[i].data));G->vertex[i].firstarc = NULL;}for (k = 0; k < G->arcnum; k++) {printf("输入第%d条弧的两个顶点:", k + 1);scanf(" %c %c", &v1, &v2); //输入一条弧的两个顶点i = LocateVertex(G, v1);j = LocateVertex(G, v2);p = (ArcNode*)malloc(sizeof(ArcNode)); //申请新弧结点p->adjvex = j;p->nextarc = G->vertex[i].firstarc;G->vertex[i].firstarc = p;}
}
3. 十字链表表示法
3.1 图的十字链表存储结构
十字链表(Orthogonal List)是有向图的另一种链式存储结构。有向图中的每一条弧对应十字链表中的一个弧结点,同时有向图中的每个顶点在十字链表中对应有一个结点,称为顶点结点。
data:用于存储与顶点有关的信息,如顶点的名字等。
firstin:用于指向以该顶点作为弧头的第一个弧顶点。
firstout:用于指向以该顶点作为弧尾的第一个弧顶点。
tailvex:表示弧尾顶点在图中的位置。
headvex:表示弧头顶点在图中的位置。
hlink:指向与此弧的弧头相同的下一条弧。
tlink:指向与此弧的弧尾相同的下一条弧。
info:指向该弧的相关信息,如权值等。
# define MAX_VERTEX_NUM 20 //最多顶点个数/*十字链表表示法*/
typedef char VertexData;
//弧结点结构
typedef struct ArcNode {int tailvex, headvex;struct ArcNode* hlink, * tlink;
}ArcNode;
//顶点结构
typedef struct VertexNode {VertexData data; //顶点信息ArcNode* firstin, * firstout;
}VertexNode;
//十字链表结构
typedef struct {VertexNode vertex[MAX_VERTEX_NUM];int vexnum, arcnum; //图的顶点数和弧数
}OrthList;
3.2 创建有向图的十字链表
/*创建有向图的十字链表*/
/*求顶点位置*/
int LocateVertex(OrthList* G, VertexData v) {int k;for (k = 0; k < G->vexnum; k++) {if (G->vertex[k].data == v)break;}return k;
}/*创建有向图的十字链表*/
void CreateOrthList(OrthList* G) {int i, j, k;VertexData vt, vh;ArcNode* p;printf("输入图的顶点数和弧数:");scanf("%d%d", &G->vexnum, &G->arcnum); //输入图的顶点数和弧数printf("输入图的顶点:");for (i = 0; i < G->vexnum; i++) { //输入图的顶点,初始化顶点结点scanf(" %c", &(G->vertex[i].data));G->vertex[i].firstin = NULL;G->vertex[i].firstout = NULL;}for (k = 0; k < G->arcnum; k++) {printf("输入第%d条弧的弧尾和弧头:", k + 1);scanf(" %c %c", &vt, &vh);i = LocateVertex(G, vt);j = LocateVertex(G, vh);p = (ArcNode*)malloc(sizeof(ArcNode)); //申请新弧结点p->tailvex = i;p->headvex = j;p->tlink = G->vertex[i].firstout;G->vertex[i].firstout = p;p->hlink = G->vertex[j].firstin;G->vertex[j].firstin = p;}
}
4. 邻接多重表
4.1 邻接多重表的存储结构
邻接多重表(Adjacency Multi-list)是无向图的存储结构,它能够提供更为方便的边处理信息。
data:用于存储与顶点有关的信息,如顶点的名字。
firstedge:用于指向第一条依附于该顶点的边。
mark:标志域,用以标记该条边是否被搜索过。
ivex / jvex:为该边依附的两个顶点在图中的位置。
ilink:用于指向下一条依附于顶点ivex的边。
jlink:用于指向下一条依附于顶点jvex的边。
# define MAX_VERTEX_NUM 20 //最多顶点个数/*邻接多重表表示法*/
typedef char VertexData;
//边结点结构
typedef struct EdgeNode {int mark, ivex, jvex;struct EdgeNode* ilink, * jlink;
}EdgeNode;
//顶点结点结构
typedef struct {VertexData data;EdgeNode* firstedge;
}VertexNode;
//邻接多重表结构
typedef struct {VertexNode vertex[MAX_VERTEX_NUM];int vexnum, arcnum; //图的顶点数和弧数
}AdjMultiList;
4.2 创建无向图的邻接多重表
/*创建无向图的邻接多重表*/
/*求顶点位置*/
int LocateVertex(AdjMultiList* G, VertexData v) {int k;for (k = 0; k < G->vexnum; k++) {if (G->vertex[k].data == v)break;}return k;
}/*创建无向图的邻接多重表*/
void CreateAdjMultiList(AdjMultiList* G) {int i, j, k;VertexData v1, v2;EdgeNode* p;printf("输入图的顶点数和弧数:");scanf("%d%d", &G->vexnum, &G->arcnum); //输入图的顶点数和弧数printf("输入图的顶点:");for (i = 0; i < G->vexnum; i++) { //输入图的顶点,初始化顶点结点scanf(" %c", &(G->vertex[i].data));G->vertex[i].firstedge = NULL;}for (k = 0; k < G->arcnum; k++) {printf("输入第%d条弧的两个顶点:", k + 1);scanf(" %c %c", &v1, &v2); //输入一条弧的两个顶点i = LocateVertex(G, v1);j = LocateVertex(G, v2);p = (EdgeNode*)malloc(sizeof(EdgeNode));p->ivex = i;p->jvex = j;p->mark = 0;p->ilink = G->vertex[i].firstedge;p->jlink = G->vertex[j].firstedge;G->vertex[i].firstedge = p;G->vertex[j].firstedge = p;}
}
参考:耿国华《数据结构——用C语言描述(第二版)》
更多数据结构内容关注我的《数据结构》专栏:https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482
【数据结构】图的存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)及实现(C语言)相关推荐
- 20.0、C语言数据结构——图的存储结构
20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...
- 数据结构考研笔记(十五)——图的存储结构邻接矩阵、邻接表、十字链表、临界多重表的概念
图的存储结构 1.邻接矩阵 1.1有向图 1.2无向图 2.邻接表法 2.1有向图边表 2.2无向图边表 3.十字链表 4.临界多重表 十字链表与临界多重表 1.邻接矩阵 邻接矩阵法结点数为n的图G ...
- 数据结构——图(存储结构)
数据结构--图 图的定义和基本术语 图的类型定义 图的存储结构 数组(邻接矩阵表示法) 网(即有权图)的邻接矩阵表示法 邻接表 邻接表表示法(链式) 图的邻接表存储表示 采用邻接表表示法创建无向网 邻 ...
- 数据结构--图的存储结构
系列文章目录 第九话 数据结构之图的存储 文章目录 一.了解什么是图 二.图的定义和基本术语 三.存储结构之邻接矩阵 1.邻接矩阵的介绍 2.邻接矩阵的创建 3.主函数中实现 四.存储结构之邻接表 ...
- 数据结构——图的存储结构
邻接矩阵法 通过矩阵来表示所有的 有向图的邻接矩阵法 无向图的邻接矩阵法 无向图的矩阵一定是对称的,可以才用压缩存储方式 网的邻接矩阵法 网就是带权值的图,所以数组里面直接放权值,不存在的边用正无穷表 ...
- 7.2图的存储结构(邻接矩阵)
邻接矩阵(无向图) 因为图是由顶点和边或弧组成的,所以最好是把他们分开存储. 下面来看无向图的邻接矩阵. 图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图. 如下图所示: ...
- 图的存储结构(邻接矩阵和邻接表)
图的存储结构(邻接矩阵和邻接表) 前言: 前面我们学习图的有些定义和术语,对图这个数据结构有了新的见解和认知,让我们理解图结构的知识,今天我们学习图的存储结构,图的存储结构比较多,我们今天主要是学习邻 ...
- 数据结构之图的存储结构:邻接多重表
图的存储结构:邻接多重表 产生条件: 邻接多重表的定义: 邻接多重表的代码定义: 删除: 性能分析: 十字链表与邻接多重表的对比 产生条件: 当用邻接矩阵法存储时:空间复杂度为O(|V|^2),太大 ...
- 数据结构之图的存储结构:邻接表法
图的存储结构:邻接表法 产生条件: 邻接表法的定义: 邻接表法的特点: 邻接表法的代码定义: 邻接表法与邻接矩阵法的对比: 产生条件: 当用邻接矩阵存储时:空间复杂度为O(|v|^2),太大 邻接表法 ...
最新文章
- Spring Boot 的 10 个核心模块
- 树莓派安装Ubuntu
- 删除联想OEM分区的方法 推荐!
- Codeforces Gym 100650B 	Countdown (离线)
- [转]九个Console命令,让js调试更简单
- java xfire下载_XFIRE教程 PDF 下载
- React应用里Invalid hook call错误消息的处理
- Generator函数的基本概念
- POI报表入门,excel,使用事件模型解析百万数据excel报表
- linux服务器安装nexus,Linux下搭建maven服务器nexus
- mysql让数据-1_mysql数据库基本操作1
- FPGA之旅设计99例之第十八例----OV5640摄像头SCCB时序
- linux用光盘安装系统时需要如何设置,Linux如何设置光盘启动
- The destination is read-only
- Linux模拟试题及答案(全)
- linux查看系统所有变量,Linux系统各指标命令
- RGB转YUV420,支持NV12(420p)和NV21(420sp)
- 蓝桥杯学习记录-基础练习
- 优步UBER司机全国各地奖励政策汇总 (4月4日-4月10日)
- shell中for循环
热门文章
- KB5022282 0x800F0922 安装更新失败
- Perceptron感知机代码讲解笔记
- 面试时巧用这些“谈薪技巧”,让你的薪资提高20%!
- 2021上海复旦微电子IC
- 在VS中使用万能头文件#include bits/stdc++.h编译错误的解决方法
- “魔幻”的直播带货:一夜血亏100万,依然有无数人入局!
- Android视频播放器缓冲时流量显示的实现方式
- 腾讯音乐财报:年营收超300亿 拟在香港以介绍形式二次上市
- 关于微前端,你想知道的都在这!
- 用数据说话,外贸B2C产品选择(上篇)-热门搜索法