图的存储结构——邻接表
图的存储结构之邻接表
- 一、邻接表表示法
- 无向图的邻接表
- 有向图的邻接表
- 有向图的逆邻接表
- 二、图的邻接表存储表示
- 三、采用邻接表表示法创建无向网
一、邻接表表示法
回忆在线性表时,顺序存储结构就存在预先分配内存可能造成存储空间浪费的问题,于是引出了链式存储结构,同样的,我们可以考虑对边或弧使用链式存储方式来避免空间浪费问题
邻接表是图的一种链式存储结构。
由两部分组成:表头结点表和边表。
邻接表中每个单链表的第一个结点存放有关顶点的信息,把这一结点看成链表的表头,其余结点存放有关边的信息
(1)表头结点表:包括数据域和链域,数据域存储顶点的名称,链域用于指向链表中第一个结点(与顶点邻接的第一个顶点)
(2)边表:包括邻接点域(指示与顶点邻接的点在图中的位置,即数组下标)、数据域(存储和边相关的信息,如权值)、链域(指示与顶点邻接的下一条边的结点)。
表头结点表:
边表:
无向图的邻接表
特点:
- 邻接表不唯一(边表顺序可以互换)
- 若无向图中有n个顶点、e条边,则其邻接表需n个头结点和2e个边结点,复杂度为O(n+2e)<O(n^2),所以适合存储稀疏图
- 无向图中顶点Vi的度为第i个单链表中的结点数。
有向图的邻接表
特点:
- 顶点vi的出度为第i个单链表中的结点个数
- 顶点vi的入度为整个单链表中邻接点域值是i-1的结点个数(需要遍历整个整个邻接表,较麻烦)。
为了便于确定顶点的入度,可以建立一个有向图的逆邻接表,即对每个顶点vi建立一个链接所以进入vi的边的表
有向图的逆邻接表
与上图同步
特点:
- 顶点vi的入度为第i个单链表中的结点个数
- 顶点vi的出度为整个单链表中邻接点域值是i-1的结点个数
此时我们很容易就可以算出某个顶点的入度或出度是多少,判断两顶点是否存在弧也很容易实现。
二、图的邻接表存储表示
//边的结点结构
#define MVNum 100 //最大顶点数
typedef struct ArcNode{int adjvex; //该边所指向的顶点的位置 struct ArcNode *nextarc;//指向下一条边的指针 Otherinfo info; //和边相关的信息
}ArcNode;//顶点的结点结构
typedef struct VNode{VerTexType data;//顶点信息、ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];//AdjList表示邻接表类型//图的结构定义
typedef struct{AdjList vertices; //定义一个数组vertices,是vertex的复数形式int vexnum,arcnum; //图的当前顶点数和弧数
}ALGraph;
三、采用邻接表表示法创建无向网
//创建无向图G
bool CreateUDG(ALGraph &G){ int i,j,k,v1,v2;cin>>G.vexnum>>G.arcnum;//输入总顶点数,总边数for(i=0;i<G.vexnum;i++){//输入各顶点,构造表头结点表 cin>>G.vertices[i].data;//输入顶点值 G.vertices[i].firstarc=NULL;//初始化表头结点的指针域}//for//输入各边,构造邻接表for(k=0;k<G.arcnum;k++){cin>>v1>>v2; //输入一条边依附的两个顶点 i=LocateVex(G,v1);j=LocateVex(G,v2); //确定顶点在G.vertices中的序号ArcNode *p1=new ArcNode; //生成一个新的边结点*p1p1->adjvex=j; //邻接点序号为j //头插法将新结点*p1插入顶点vi的边表头部 p1->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p1; ArcNode *p2=new ArcNode;p2->adjvex=i; //邻接点序号为i//头插法插入p2 ,因为是无向网,所以是两条 p2->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p2; }//forreturn true;
}//CreateUDG
算法时间复杂度是O(n+e);
int LocateVex(ALGraph G,VerTexType u){//在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1int i;for(i=0;i<G.vexnum;i++)if(u==G.vertices[i])return i;return -1;
}
注意:一个图的邻接矩阵表示是唯一的,但其邻接表表示不唯一,这是因为邻接表表示中,各边表结点的链接次序取决于建立邻接表的算法,以及边的输入次序
代码实现此邻接表:
#include<iostream>
#include<queue>
using namespace std;
#define MVNum 100 //最大顶点数typedef struct ArcNode{int adjvex; //该边所指向的顶点的位置 struct ArcNode *nextarc;//指向下一条边的指针
}ArcNode;//顶点的结点结构
typedef struct VNode{char data;//顶点信息、ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];//AdjList表示邻接表类型//图的结构定义
typedef struct{AdjList vertices; //定义一个数组vertices,是vertex的复数形式int vexnum,arcnum; //图的当前顶点数和弧数
}ALGraph;int LocateVex(ALGraph G,int u){//在图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1int i;for(i=1;i<=G.vexnum;i++)if(u == G.vertices[i].data)return i;return -1;
} //创建无向图G
bool CreateUDG(ALGraph &G){ cout << "请输入总结点数和总边数:" << endl; cin>>G.vexnum>>G.arcnum;//输入总顶点数,总边数cout << " 输入各顶点值: " << endl; for(int i = 1;i <= G.vexnum;i++){//输入各顶点,构造表头结点表 cin>>G.vertices[i].data;//输入顶点值 G.vertices[i].firstarc=NULL;//初始化表头结点的指针域}//forgetchar();//输入各边,构造邻接表cout << "输入一条边依附的两个顶点值"<<endl; for(int k=1;k<=G.arcnum;k++){char v1,v2;cin>>v1>>v2; //输入一条边依附的两个顶点 getchar();int i=LocateVex(G,v1);int j=LocateVex(G,v2); //确定顶点在G.vertices中的序号ArcNode *p1=new ArcNode; //生成一个新的边结点*p1p1->adjvex=j; //邻接点序号为j //头插法将新结点*p1插入顶点vi的边表头部 p1->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p1; ArcNode *p2=new ArcNode;p2->adjvex=i; //邻接点序号为i//头插法插入p2 ,因为是无向网,所以是两条 p2->nextarc=G.vertices[j].firstarc;G.vertices[j].firstarc=p2; }//forreturn true;
}//CreateUDGint main()
{ALGraph G;ArcNode *p;CreateUDG(G);cout << "输出邻接表: " <<endl;for(int i = 1; i<= G.vexnum; i++){cout << G.vertices[i].data;for(p = G.vertices[i].firstarc; p != NULL; p = p->nextarc)printf("->%d", p->adjvex);cout << endl; } return 0;
}
邻接表表示法优缺点:
(1)优点
- 便于增加和删除顶点。
- 便于统计边的数目,时间复杂度是O(n+e)
- 空间效率高
(2)缺点
- 不便于判断顶点之间是否有边
- 不便于计算有向图各顶点的度
图的存储结构——邻接表相关推荐
- 图的存储结构——邻接表法
图的存储结构--邻接表法 一.邻接表 由顶点表和边表构成,顶点表由顶点域(data)和指向第一条邻接边的指针(firstarc)构成,边表(邻接表)结点由邻接点域(adjvex)和指向下一条邻接边 ...
- 7.2图的存储结构(邻接表)
为什么要采用邻接表: 对于边数相对顶点较少的图,这种结构无疑是存储空间的极大浪费. 所以把数组和链表结合起来存储,这种方式在图结构中适用,称为邻接表(AdjacencyList) 邻接表的处理方法如下 ...
- 图的存储结构---邻接表
1. 邻接表(无向图) 对于边数相对顶点较少的图,可采取邻接表. 把数组与链表结合在一起来存储,这种方式在图结构也适用,称为邻接表(AdjacencyList). 2. 邻接表(有向图) 以每个顶点出 ...
- 【数据结构】图的存储结构—邻接表
目录 什么是邻接表? 邻接表:定义 邻接表:相关类 邻接表:基本操作 1)创建无向网 2)创建有向网 3)顶点定位 4)插入边 5)第一个邻接点 6)查询下一个邻接点 小试牛刀 对比邻接表与邻接矩阵
- 图的存储 邻接矩阵+邻接表+链式前向星
图的存储 - 邻接矩阵 在树的问题中,邻接矩阵是空间.时间的极大浪费. 假设树的结点个数为 N = 100000. 建立邻接矩阵需要空间为 1e5*1e5 但是由于只有 N - 1 条边,所以在邻接矩 ...
- 20.0、C语言数据结构——图的存储结构
20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...
- 数据结构考研笔记(十五)——图的存储结构邻接矩阵、邻接表、十字链表、临界多重表的概念
图的存储结构 1.邻接矩阵 1.1有向图 1.2无向图 2.邻接表法 2.1有向图边表 2.2无向图边表 3.十字链表 4.临界多重表 十字链表与临界多重表 1.邻接矩阵 邻接矩阵法结点数为n的图G ...
- 【数据结构】图的存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)及实现(C语言)
目录 1. 邻接矩阵表示法 1.1 图的邻接矩阵 1.2 创建有向网的邻接矩阵 2. 邻接表表示法 2.1 图的邻接表存储结构 2.2 创建有向图的邻接表 3. 十字链表表示法 3.1 图的十字链表存 ...
- 【图】什么是图?无向图怎么存储?邻接表和邻接矩阵如何用代码存储图?
目录 一.概念 图是什么 各种图的定义 二.图的存储结构 邻接矩阵 邻接表 三.代码实现图的存储 1.无向图存储 2.邻接矩阵存储图 核心代码 完整代码 3.邻接表存储有向图(不含权重) 核心代码 完 ...
- 数据结构之图的存储结构:邻接多重表
图的存储结构:邻接多重表 产生条件: 邻接多重表的定义: 邻接多重表的代码定义: 删除: 性能分析: 十字链表与邻接多重表的对比 产生条件: 当用邻接矩阵法存储时:空间复杂度为O(|V|^2),太大 ...
最新文章
- 百度:2020年十大科技趋势
- SqlHelper全攻略
- 编程之美2.1 求二进制中1的个数
- python电脑下载网址-python下载文件文件到本地电脑(基于requests)
- JIRA 6.3.6版本部署
- codevs1316 文化之旅
- 只安装和配置instantclient,用plsql developer,navicat for oracle,sqlplus连接oracle数据库 ....
- jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理
- rstudio和matlab,R语言与matlab循环时间对比
- linux blind函数,C++拾遗--bind函数绑定
- 链表反转的两种实现方法,后一种击败了100%的用户
- Using the isBranch() method to determine if a Tree item is a branch or leaf
- set获取元素_C++与STL入门(4):关联容器:集合set
- MFC 教程【12_对话框和对话框类CDialog 】
- 文远知行公布自动驾驶运营路线图:全新升级自动驾驶方案,建立500辆规模的自动驾驶车队...
- 1537 学生干部虚基类
- ps怎么撤销参考线_PS怎么拉辅助线和清除、移动参考线——视频教程十
- 盗QQ号的现在越来越牛B了,我差点被骗!大家要小心了
- 【转】清华本科结业生两年的工作经历
- 安全网站导航 farmsec
热门文章
- 做了个小工具,可以一键导出所有微信表情包,有趣的表情包,不再只限一个APP使用,【微信表情包吸血鬼】
- matlab矩阵最大值最小值均值,Matlab 处理数据—最小值、最大值、均值、方差
- 【word】删除页眉横线
- 钢铁企业的能耗管理现状和管理建议
- 2021年中国大企业创新百强排行榜:华为位居榜首,北京上榜企业最多(附年榜TOP100详单)
- python 网络小说爬取2
- 科研作图软件介绍附带AI安装包
- File system specific implementation of LookupAndOpen [file] failed
- 邮箱容量多大?163邮箱发邮件无限容量解读
- 微信公众号登陆微商城