邻接表存储表示

合集下载

第七章图状结构

第七章图状结构

图的应用非常广泛。
2
7.1 图的类型定义
7.2 图的存储表示
7.3 图的遍历
7.4 最小生成树 7.5 两点之间的最短路径问题 7.6 拓扑排序
7.7 关键路径
3
图的结构定义:
图是由一个顶点集 V 和一个弧集 R构 成的数据结构。 Graph = (V , R ) 其中,R={<v,w>| v,w∈V 且 P(v,w)} <v,w>表示从 v 到 w 的一条弧,并称 v 为弧尾,w 为弧头。
4
由于“弧”是有方向的,因此称由顶 点集和弧集构成的图为有向图。
例如: G1 = (V1, VR1)
A
B C D E
其中 V1={A, B, C, D, E} VR1={<A,B>, <A,E>,
<B,C>, <C,D>, <D,B>, <D,A>, <E,C> }
5
若<v, w>VR 且<w, v>VR, 则称 (v,w) 为顶点v 和顶点 w 之间存在一条边。 例如: G2=(V2,VR2) V2={A, B, C, D, E, F} VR2={(A,B), (A,E),
0 0 0 1 0 1
0 0 1 0 0 1
1 1 0 0 0 0
0 1 1 1 0 0
24
无向图邻接矩阵表示法特点:
1)无向图邻接矩阵是对称矩阵 2)顶点v的度 3)判断两顶点v、u是否为邻接点 4)顶点不变,在图中增加、删除边 5)适用于边稠密的图;
25
有向图的邻接矩阵 为非对称矩阵
0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0

图的邻接矩阵和邻接表相互转换

图的邻接矩阵和邻接表相互转换

图的邻接矩阵和邻接表相互转换图的邻接矩阵存储方法具有如下几个特征:1)无向图的邻接矩阵一定是一个对称矩阵。

2)对于无向图的邻接矩阵的第i 行非零元素的个数正好是第i 个顶点的度()i v TD 。

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

4)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是否有边相连;但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所发费得时间代价大。

邻接表是图的一种顺序存储与链式存储相结合的存储方法。

若无向图中有n 个顶点、e 条边,则它的邻接表需n 个头结点和2e 个表结点。

显然,在边稀疏的情况下,用邻接表表示图比邻接矩阵存储空间。

在无向图的邻接表中,顶点i v 的度恰好是第i 个链表中的结点数,而在有向图中,第i 个链表中结点个数是顶点i v 的出度。

在建立邻接表或邻逆接表时,若输入的顶点信息即为顶点的编号,则建立临接表的时间复杂度是)(e n O +;否则,需要通过查找才能得到顶点在图中位置,则时间复杂度为)*(e n O 。

在邻接表上容易找到任意一顶点的第一个邻接点和下一个邻接点,但要判断任意两个顶点之间是否有边或弧,则需要搜索第i 个或第j 个链表,因此,不及邻接矩阵方便。

邻接矩阵和邻接表相互转换程序代码如下:#include<iostream.h>#define MAX 20//图的邻接表存储表示typedef struct ArcNode{int adjvex; //弧的邻接定点 char info; //邻接点值struct ArcNode *nextarc; //指向下一条弧的指针}ArcNode;typedef struct Vnode{ //节点信息char data;ArcNode *link;}Vnode,AdjList[MAX];typedef struct{AdjList vertices;int vexnum; //节点数int arcnum; //边数}ALGraph;//图的邻接矩阵存储表示typedef struct{int n; //顶点个数char vexs[MAX]; //定点信息int arcs[MAX][MAX]; //边信息矩阵}AdjMatrix;/***_____________________________________________________***///函数名:AdjListToMatrix(AdjList g1,AdjListMatrix &gm,int n)//参数:(传入)AdjList g1图的邻接表,(传入)int n顶点个数,(传出)AdjMatrix gm图的邻接矩阵//功能:把图的邻接表表示转换成图的邻接矩阵表示void AdjListToAdjMatrix(ALGraph gl,AdjMatrix &gm){int i,j,k;ArcNode *p;gm.n=gl.vexnum;for(k=0;k<gl.vexnum;k++)gm.vexs[k]=gl.vertices[k].data;for(i=0;i<MAX;i++)for(j=0;j<MAX;j++)gm.arcs[i][j]=0;for(i=0;i<gl.vexnum;i++){p=gl.vertices[i].link; //取第一个邻接顶点while(p!=NULL){ //取下一个邻接顶点gm.arcs[i][p->adjvex]=1;p=p->nextarc;}}}/***________________________________________________***///函数名:AdjMatrixToAdjListvoid AdjMatrixToAdjList(AdjMatrix gm,ALGraph &gl){int i,j,k,choice;ArcNode *p;k=0;gl.vexnum=gm.n;cout<<"请选择所建立的图形是无向图或是有向图:";cin>>choice;for(i=0;i<gm.n;i++){gl.vertices[i].data=gm.vexs[i];gl.vertices[i].link=NULL;}for(i=0;i<gm.n;i++)for(j=0;j<gm.n;j++)if(gm.arcs[i][j]==1){k++;p=new ArcNode;p->adjvex=j;p->info=gm.vexs[j];p->nextarc=gl.vertices[i].link;gl.vertices[i].link=p;}if(choice==1)k=k/2;gl.arcnum=k;}void CreateAdjList(ALGraph &G){int i,s,d,choice;ArcNode *p;cout<<"请选择所建立的图形是有向图或是无向图:";cin>>choice;cout<<"请输入节点数和边数:"<<endl;cin>>G.vexnum>>G.arcnum;for(i=0;i<G.vexnum;i++){cout<<"第"<<i<<"个节点的信息:";cin>>G.vertices[i].data;G.vertices[i].link=NULL;}if(choice==1){for(i=0;i<2*(G.vexnum);i++){cout<<"边----起点序号,终点序号:";cin>>s>>d;p=new ArcNode;p->adjvex=d;p->info=G.vertices[d].data;p->nextarc=G.vertices[s].link;G.vertices[s].link=p;}}else{for(i=0;i<G.vexnum;i++){cout<<"边----起点序号,终点序号:";cin>>s>>d;p=new ArcNode;p->adjvex=d;p->info=G.vertices[d].data;p->nextarc=G.vertices[s].link;G.vertices[s].link=p;}}}void CreateAdjMatrix(AdjMatrix &M){int i,j,k,choice;cout<<"请输入顶点个数:";cin>>M.n;cout<<"请输入如顶点信息:"<<endl;for(k=0;k<M.n;k++)cin>>M.vexs[k];cout<<"请选择所建立的图形是无向图或是有向图:";cin>>choice;cout<<"请输入边信息:"<<endl;for(i=0;i<M.n;i++)for(j=0;j<M.n;j++)M.arcs[i][j]=0;switch(choice){case 1:{for(k=0;k<M.n;k++){cin>>i>>j;M.arcs[i][j]=M.arcs[j][i]=1;}};break;case 2:{for(k=0;k<M.n;k++){cin>>i>>j;M.arcs[i][j]=1;}};break;}}void OutPutAdjList(ALGraph &G){int i;ArcNode *p;cout<<"图的邻接表如下:"<<endl;for(i=0;i<G.vexnum;i++){cout<<G.vertices[i].data;p=G.vertices[i].link;while(p!=NULL){cout<<"---->("<<p->adjvex<<" "<<p->info<<")";p=p->nextarc;}cout<<endl;}}void OutPutAdjMatrix(AdjMatrix gm){cout<<"图的邻接矩阵如下:"<<endl;for(int i=0;i<gm.n;i++){。

数据结构-邻接表

数据结构-邻接表
for(i=0;i<NumOfVertices() ;i++) if(!visited[i]) BroadFirstSearch(i, visited, Visit);
delete [ ] visited; }
8.4 图的遍历(续)
图的生成树
定义:G的所有顶点加上遍历过程中经过的边 所构成的子图称作图G的生成树G’
visited[v]=1;
/*标记第v个顶点已访问*/
/*访问第v个顶点邻接的未被访问过的顶点w,并从w出发递归地按照深度 优先的方式进行遍历*/
w= GetFirstNeighbor (v); /*得到第v个顶点的第一个邻接顶点w*/
while(w!= -1)
{ if(!visited[w]) DepthFirstSearch(w,visited,Visit); //递归调用
void BroadFirstSearch(const int v, int visited[ ], void visit(VT Vertex));
public:
AdjTWGraph(void);
~AdjTWGraph(void);
int NumOfVertices(void)const;
int NumOfEdges(void)const;
(2) 无向图:第i个链表中的表结点数为TD(vi); 能逆求邻有I接向D表(图vi。):。第为i个便链于表求中ID的(v表i) 可结另点外数建为立OD有(v向i),图不的
(3) 容易寻找顶点的邻接 点,但判断两顶点间是 否有边或弧,需搜索两 结点对应的单链表。
(4) 邻接表多用于稀疏 图的存储(e<<n2)
void Visit(VT item))

邻接表表示法的特点

邻接表表示法的特点

邻接表表示法的特点
邻接表表示法是一种把图结构的存储结构。

它的空间使用效率高,操作效率也比较高,而且相对来说存储结构比较清楚方便管理。

首先,邻接表存储结构最大的优点就是空间复杂度极小,因为它只需要存储图中的顶点信息和边信息就可以描述图中的结构,此外,每个顶点只需要存储其相邻节点的序号而不需要存储两顶点之间的
距离,所以节点所占的内存空间少,也减少了图中属性的存储。

其次,邻接表存储结构的操作效率也比较高,因为在邻接表存储结构中,每个顶点都有相应的链表来存储其相邻节点的序号,所以在查找和更新操作中,只需要找到顶点的链表,就可以很方便地查找或更新其邻接节点的信息,也十分提高了操作效率。

此外,邻接表存储结构的结构也比较清晰,在建立时只需要用一个数据结构把图的顶点和邻接边按照一定的顺序存储起来,就可以把图中的结构信息全部存储起来。

这样,程序员就可以非常快速地定位顶点的相邻边,也方便管理。

总之,邻接表表示法优化了图的存储,使得程序员可以更加快速准确地定位顶点的相邻边,并且使得管理变得更加简单方便。

邻接表表示法也在图的可视化中有着广泛的应用,有助于更好地提高图的存储效率和操作效率。

因此,邻接表表示法的特点是空间使用效率高,操作效率也比较高,相对来说存储结构比较清晰方便管理,且有着广泛的应用。

未来,会有更多的算法和应用技术来提高图的效率,并且在使用邻接表表示
法时,还有很多细节需要更新和思考,以更加优雅地描述图结构。

实验六 图及其应用

实验六 图及其应用

实验六图及其应用数据结构实验六图及其应用1、实验目的? 熟练掌握图的两种存储结构(邻接矩阵和邻接表)的表示方法 ? 掌握图的基本运算及应用? 加深对图的理解,逐步培养解决实际问题的编程能力2、实验内容:采用邻接表或邻接矩阵方式存储图,实现图的深度遍历和广度遍历;用广度优先搜索方法找出从一顶点到另一顶点边数最少的路径。

1.问题描述:利用邻接表存储结构,设计一种图(有向或无向),并能够对其进行如下操作:1) 创建一个可以随机确定结点数和弧(有向或无向)数的图; 2) 根据图结点的序号,得到该结点的值;3) 根据图结点的位置的第一个邻接顶点的序号,以及下一个邻接顶点的序号;4) 实现从第v 个顶点出发对图进行深度优先递归遍历; 5) 实现对图作深度优先遍历;6) 实现对图进行广度优先非递归遍历; 编写主程序,实现对各不同的算法调用。

2.实现要求:(以邻接表存储形式为例)编写图的基本操作函数::对图的各项操作一定要编写成为C(C++)语言函数,组合成模块化的形式,每个算法的实现要从时间复杂度和空间复杂度上进行评价。

1)“建立图的邻接表算法”:CreateGraph(ALGraph *G) 操作结果:采用邻接表存储结构,构造没有相关信息的图G2)“邻接表表示的图的递归深度优先遍历算法”:DFSTraverse(ALGraphG,void(*Visit)(char*)) 初始条件:图G 已经存在;操作结果:返回图的按深度遍历的结果。

3)“邻接表表示的图的广度优先遍历算法”: BFSTraverse(ALGraphG,void(*Visit)(char*)) 初始条件:图G 已经存在;操作结果:返回图的按广度遍历的结果。

4)“邻接表从某个结点开始的广度优先遍历算法”:BFS(ALGraph G, int v)初始条件:图G 已经存在;操作结果:返回图从某个结点开始的按广度遍历的结果。

分析: 修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。

数据结构-图及其存储结构

数据结构-图及其存储结构
//不含其他信息 for (i=0;i<G.vexnum;+ +i ) scanf(G.vexs[i]); //一维数组存放顶点值 for (i=0;i<G.vexnum;+ +i ) //二维数组赋初值
for (j=0;j<G.vexnum;+ +j ) adj Info G.arcs[i][j]={∞,NULL}; //Arccell的形式为: for (k=0;k<G.arcnum;+ +i ) { //二维数组存放各边上的信息 scanf(v1,v2,w); i=locatevex(G,v1); j=locatevex(G,v2); //求顶点v1,v2在图中的位置 G.arcs[i][j].adj=w; G.arcs[j][i].adj=w; //无向网的邻接矩阵是对称的 if (IncInfo) Input (*G.arcs[i][j].info); //将弧上的信息存储在指针info
case UDN: return CreateUDN(G);
default : return ERROR; }//CreateGraph
二、存储结构
2.数组表示法前提下图的输入
*以无向网为例,即当用户输入图的类型标志为UDN时,有:
Status CreateUDN(MGraph &G){ scanf(G.vexnum,G.arcnum,IncInfo); //IncInfo 为0时表示各弧
v2 6 5
v1 5 1 5 v3 3 6 4 2 v4
一个连通无向图的生成树是该图的一个连通分量,它 包含有该图的所有n个顶点以及连接这n个顶点的(n-1) 条边。 边或弧上带权值的图称为带权图或网(分为无向网和 有向网)。 一个无向图的所有生成树中,边上的权值之和最小的 生成树称为该图的最小生成树或最小代价生成树。

数据结构与算法教学大纲

数据结构与算法教学大纲

《数据结构与算法》课程教学大纲一、《数据结构》课程说明(一)课程代码:(二)课程英文名称:Data Stucture(三)开课对象:电子专业的本科生(四)课程性质:专业基础课《数据结构》是计算机专业的技术基础课。

主要讲述算法设计和数据结构的基础原理和技术。

是计算机科学与技术专业的核心课程。

由于本课程是计算机程序设计理论基础,所以也是非计算机理工类专业的重要选修课程。

本课程的学习过程也是算法设计的技巧和能力的训练过程。

本课程的先导课程为《C语言》,《计算机基础》。

(五)教学目的:通过本课程的学习,使学生深透地理解数据结构的逻辑结构和物理结构的基本概念以及有关算法,培养基本的、良好的程序设计技能,编制高效可靠的程序,为学习《操作系统》、《编译原理》和《数据库》等课程奠定基础。

(六)教学内容:本课程主要包括绪论、线性表、树型结构、图、查找、排序等几个部分。

通过教学的各个环节使学生达到各章中所提的基本要求。

习题课是重要的教学环节,教师必须予以重视。

(七)学时数、学分数及学时数具体分配学时数: 68学时学分数: 4学分(八)教学方式以多媒体教学手段为主要形式的课堂教学。

(九)考核方式和成绩记载说明考核方式为考试。

严格考核学生出勤情况,达到学籍管理规定的旷课量取消考试资格。

综合成绩根据平时成绩和期末成绩评定,平时成绩占20% ,期末成绩占80% 。

二、讲授大纲与各章的基本要求第一章绪论教学要点:通过本章的教学使学生初步了解《数据结构》的内容和目的,掌握数据结构的概念以及分类、抽象数据类型的表示与实现、算法的概念、算法的特性、算法的目标、算法效率的度量、算法的存储空间需求。

1、使学生准确掌握数据结构的概念。

2、使学生领会抽象数据类型的表示与实现。

3、使学生充分理解算法的概念。

4、明确算法的特性。

5、明确算法的目标。

6、熟练地掌握算法效率的度量。

7、掌握算法的存储空间需求。

教学时数:4学时教学内容:第一节数据结构概述第二节数据结构的概念一、基本概念二、数据结构及分类三、数据结构课程的内容第三节数据类型和抽象数据类型一、数据类型二、抽象数据类型第四节算法和算法分析考核要求:1、数据结构概述(识记)2、数据结构的概念2.1基本概念(识记)2.2数据结构及分类(识记)2.3数据结构课程的内容(识记)3、数据类型和抽象数据类型3.1数据类型(领会)3.2抽象数据类型(领会)4、算法和算法分析(应用)第二章线性表教学要点:通过本章的教学使学生初步了解线性表的结构特点;掌握顺序的和链式的存储结构各自特色;熟练掌握线性表的操作,以及链表的指针运算和各种链表的操作;理解循环链表以及双向链表。

图的定义和基本术语图的存储结构图的遍历生成树最短路径

图的定义和基本术语图的存储结构图的遍历生成树最短路径
操作结果: 在图G中增添新顶点v。
DeleteVex(&G, v) //删除顶点 初始条件: 图G存在, v和G中顶点有相同特性 。 操作结果:删除G中顶点v及其相关的弧。
InsertArc(&G, v, w) //插入弧 初始条件:图G存在,v 和w是G中两个顶点。 操作结果:在G中增添弧<v,w>,若G是无向的, 则还增添对称弧<w,v>。
DestroyGraph (&G ) // 销毁 初始条件:图G存在。 操作结果:销毁图G 。
LocateVex(G, u) // 定位 初始条件:图G存在,u 和G中顶点有相同特性 。 操作结果: 若G中存在顶点u ,则返回该顶点在 图中位置 ;否则返回其它信息。
GetVex(G, v)// 求值 初始条件:图G存在,v 是G中某个顶点。 操作结果:返回v的值。
//{有向图,有向网,无向图,无向网}
typedef struct ArcCell {// 弧的定义 VRType adj;//VRType是顶点关系类型。对无权图,
//用1或0表示相邻否;对带权图,则为权值类型。 InfoType *info; // 该弧相关信息的指针 } ArcCell ,
AdjMatrix[MAX_VERTEX_NUM] [MAX_VERTEX_NUM];
V2
V3
0110 0000 0001 10 0 0
//- -图的数组(邻接矩阵)存储表示--
#define INFINITY INT_MAX //最大值∞ #define MAX_VERTEX_NUM 20//最大顶点个数 typedef enum{DG,DN,UDG, UDN }graphkind;
表示,称为无向边;

数据结构_图_采用邻接矩阵存储,构造无向图

数据结构_图_采用邻接矩阵存储,构造无向图

1.采用邻接矩阵(邻接表)存储,构造无向图(网)输入:顶点数、边数、顶点信息、边信息输出:图的顶点,图的边邻接矩阵(数组表示法)处理方法:用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。

假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n 的方阵,定义为:如果(vi,vj)属于边集,则edges[i][j]=1,否则edges[i][j]=0。

邻接表存储的处理方法:对于图的每个顶点vi,将所有邻接于vi的顶点链成一个单链表,称为顶点vi的边表(对于有向图则称为出边表),所有边表的头指针和存储顶点信息的一维数组构成了顶点表。

程序代码:#include<iostream>using namespace std;#define MAX_VERTEX_NUM 20 //最大顶点个数#define OK 1typedef int Status;//图的数组(邻接矩阵)存储表示typedef struct ArcCell { // 弧的定义int adj; // VRType是顶点关系类型。

// 对无权图,用1或0表示相邻否;// 对带权图,则为权值类型。

int *info; // 该弧相关信息的指针} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct { // 图的定义char vexs[MAX_VERTEX_NUM];//顶点向量AdjMatrix arcs; // 邻接矩阵int vexnum, arcnum; // 图的当前顶点数、弧数} MGraph;int LocateV ex(MGraph G, char v){int a;for (int i = 0; i <= G.vexnum; i++){if (G.vexs[i] == v)a= i;}return a;}Status CreateUDN(MGraph &G) { //采用邻接矩阵表示法,构造无向网Gint i, j, k, w;char v1, v2;cout <<"输入顶点数,边数:"<< endl;cin >> G.vexnum >> G.arcnum;//IncInfo为0,表示各弧无信息cout <<"各顶点分别为:"<< endl;for (i = 0; i<G.vexnum; i++)cin >> G.vexs[i]; //构造顶点向量for (i = 0; i<G.vexnum; i++) //初始化邻接矩阵for (j = 0; j<G.vexnum; j++){G.arcs[i][j].adj =NULL;}cout <<"顶点信息、边信息:"<< endl;for (k = 0; k<G.arcnum; k++) { //构造邻接矩阵cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值i = LocateV ex(G, v1); j = LocateV ex(G, v2);G.arcs[i][j].adj = w;G.arcs[j][i] = G.arcs[i][j];} return OK;} //CreateUDN (p162 算法7.2)Status printf1(MGraph G){cout <<"该图的顶点分别为:";for (int i = 0; i<G.vexnum; i++)cout << G.vexs[i] <<"";return OK;}Status printf2(MGraph G){cout <<"该图的边为:";for (int i = 1; i<G.vexnum; i++) //初始化邻接矩阵for (int j = 0; j<i; j++){if (G.arcs[i][j].adj !=NULL)cout << G.vexs[j]<< G.vexs[i] <<"," ;}return OK;}int main(){MGraph G;CreateUDN(G);printf1(G);cout << endl;printf2(G);cout << endl;system("pause");return 0;}。

图的几种存储方式

图的几种存储方式

之前几天把数据结构扔在一边,在看离散数学的图论部分,看了大部分,最后还是觉得纯数学的,有一些可能现在我刚接触图还不会觉得有什么用,所以就选择性的跳过一些,现在也决定先放下书,回到数据结构上,开始图的部分的学习。

图的存储通用的存储方式有邻接矩阵表示法、邻接表表示法。

为方便有向图的顶点的入度与出度的计算,有有向图的十字链表表示法。

为方便对无向图的边进行操作,有无向图的邻接多重表表示法。

邻接矩阵表示法应该算是最容易的一种表示法,一些简单的操作比如查找某顶点的指定邻接点等很容易实现。

邻接表表示在计算无向图顶点的度很方便,计算有向图的出度也很方便,但是计算入度的话就要从第一个结点开始遍历,比较麻烦,这时采用逆邻接表表示法的话,求有向图的入度就会很方便,相应的,出度就不方便了,所以要根据需要选择存储结构。

如果在程序中要统计有向图的度,那么最好的方式就是采用十字链表的存储方式。

邻接多重表可以看作是对无向图的邻接矩阵的一种压缩表示,当然这种结构在边的操作上会方便很多,但是我现在还没学到,所以暂时还不知道。

下面是几种表示方法的算法实现,逆邻接表和邻接表的实现方式几乎一样,所以就不贴出来了。

1.#define MAX_VERTEX_NUM 202.3.#include<iostream>4.#include<string>ing namespace std;6.7.template<class T>8.int Locate_Vex(T G,string x) //定位顶点位置9.{10.for(int k=0;G.vexs[k]!=x;k++);11.return k;12.}13.14.//邻接矩阵存储图15.struct MGraph16.{17. string vexs[MAX_VERTEX_NUM];//顶点数组18.int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵19.int vexnum;//顶点数目20.int arcnum;//边数目21.};22.23.void CreateUDN_MG(MGraph &G)24.{25.//采用邻接矩阵表示法,构造无向网26. cin>>G.vexnum>>G.arcnum;27.for(int i=0;i<G.vexnum;i++)28. cin>>vaxs[i];29.30.for(i=0;i<G.vexnum;i++)31.for(int j=0;j<G.vexnum;j++)32. G.arcs[i][j]=-1;33.//上面是初始化邻接矩阵,-1表示两点间边的权值为无穷大34.35.for(int k=0;k<G.arcnum;k++)36. {37. string v1,v2;38.int w;39. cin>>v1>>v2>>w;40. i=Locate_Vex(G,v1);41. j=Locate_Vex(G,v2);42.while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)43. {44. cout<<"结点位置输入错误,重新输入: ";45. cin>>v1>>v2>>w;46. i=Locate_Vex(G,v1);47. j=Locate_Vex(G,v2);48. }49. G.arcs[i][j]=w;50. G.arcs[j][i]=G.arcs[i][j]; //置对称边51. }52.}53.54.//邻接表存储图55.//表结点56.struct ArcNode57.{58.int adjvex; //弧所指向顶点的位置59. ArcNode *nextarc;// 指向下一条弧60.};61.62.//头结点63.typedef struct VNode64.{65. string data;//顶点名66. ArcNode *firstarc;//指向第一条关联顶点的弧67.}AdjList[MAX_VERTEX_NUM];68.69.struct ALGraph70.{71. AdjList vertices;//头结点数组72.int vexnum;73.int arcnum;74.};75.76.void CreateDG_ALG(ALGraph &G)77.{78.//采用邻接表存储表示,构造有向图G79. string v1,v2;80.int i,j,k;81. cin>>G.arcnum>>G.vexnum;82.83.//构造头结点数组84.for(i=0;i<G.vexnum;i++)85. {86. cin>>G.vertices[i].data;87. G.vertices[i].firstarc=NULL;88. }89.90.//输入各弧并构造邻接表91.for(k=0;k<G.arcnum;k++)92. {93. cin>>v1>>v2;94. i=Locate_Vex(G,v1);95. j=Locate_Vex(G,v2);96.while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)97. {98. cout<<"结点位置输入错误,重新输入: ";99. cin>>v1>>v2;100. i=Locate_Vex(G,v1);101. j=Locate_Vex(G,v2);102. }103.104. ArcNode *p=new ArcNode;105. p->adjvex=j;106. p->nextarc=NULL;107. p->nextarc=G.vertices[i].firstarc;108. G.vertices[i].firstarc=p;109. }110.}111.112.//十字链表方式存储有向图113.//弧结点114.struct ArcBox115.{116.int tailvex,headvex;//弧结点头尾结点位置117. ArcBox *hlink,*tlink;//弧头和弧尾相同的弧的链域118.};119.120.//顶点结点121.struct VexNode122.{123. string data;124. ArcBox *firstin,*firstout;//顶点第一条入弧和出弧125.};126.127.struct OLGraph128.{129. VexNode xlist[MAX_VERTEX_NUM];130.int vexnum;131.int arcnum;132.};133.134.void CreateDG_OLG(OLGraph &G)135.{136.//采用十字链表存储表示,构造有向图G137. string v1,v2;138.int i,j,k;139. cin>>G.vexnum>>G.arcnum;140.for(i=0;i<G.vexnum;i++)141. {142. cin>>G.xlist[i].data;143. G.xlist[i].firstin=NULL;144. G.xlist[i].firstout=NULL;145. }146.for(k=0;k<G.arcnum;k++)147. {148. cin>>v1>>v2;149. i=Locate_Vex(G,v1);150. j=Locate_Vex(G,v2);151.152.while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1) 153. {154. cout<<"结点位置输入错误,重新输入: ";155. cin>>v1>>v2;156. i=Locate_Vex(G,v1);157. j=Locate_Vex(G,v2);158. }159.160. ArcBox *p=new ArcBox;161. p->tailvex=i;162. p->headvex=j;163. p->hlink=G.xlist[j].firstin;164. p->tlink=G.xlist[i].firstout;165. G.xlist[i].firstout=G.xlist[j].firstin=p;166. }167.}168.169.//邻接多重表存储170.//边结点171.struct EBox172.{173.int mark;//标志域,指示该边是否被访问过(0:没有 1:有) 174.int ivex,jvex;//该边关联的两个顶点的位置175. EBox *ilink,*jlink;//分别指向关联这两个顶点的下一条边176.};177.178.//顶点结点179.struct VexBox180.{181. string data;182. EBox *firstedge;//指向第一条关联该结点的边183.};184.185.struct AMLGraph186.{187. VexBox adjmulist[MAX_VERTEX_NUM];188.int vexnum;189.int arcnum;190.};191.192.void CreateUDG_AML(AMLGraph &G)193.{194.//用邻接多重表存储,构造无向图G195. string v1,v2;196.int i,j,k;197. cin>>G.vexnum>>G.arcnum;198.for(i=0;i<G.vexnum;i++)199. {200. cin>>G.adjmulist[i].data;201. G.adjmulist[i].firstedge=NULL;202. }203.204.for(k=0;k<G.arcnum;k++)205. {206. cin>>v1>>v2;207. i=Locate_Vex(G,v1);208. j=Locate_Vex(G,v2);209.210.while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1) 211. {212. cout<<"结点位置输入错误,重新输入: ";213. cin>>v1>>v2;214. i=Locate_Vex(G,v1);215. j=Locate_Vex(G,v2);216. }217.218. EBox *p=new EBox;219. p->ivex=i;220. p->jvex=j;221. p->ilink=G.adjmulist[i].firstedge;222. p->jlink=G.adjmulist[j].firstedge;223. p->mark=0;224. G.adjmulist[i].firstedge=G.adjmulist[j].firstedge=p; 225. }226.}。

图的存储结构

图的存储结构

第2讲图的存储结构——教学讲义本讲介绍4种较常用的存储表示法:①邻接矩阵表示法;②邻接表;③邻接多重表;④十字链表。

由于每种方法各有利弊,因此可以根据实际应用问题来选择合适的存储表示方法。

①邻接矩阵表示法图的邻接矩阵表示法(Adjacency Matrix)也称作数组表示法。

它采用两个数组来表示图:一个是用于存储顶点信息的一维数组,另一个是用于存储图中顶点之间关联关系的二维数组,这个关联关系数组被称为邻接矩阵。

若G是一具有n个顶点的无权图,G的邻接矩阵是具有如下性质的n×n矩阵A:上图所示G1和G2的邻接矩阵如下所示。

若图G是一个有n个顶点的网,则它的邻接矩阵是具有如下性质的n×n矩阵AA1=图G1,G2的邻接矩阵(a) G1是有向图(b) G2是无向图例如:下图就是一个有向网及其邻接矩阵的示例。

邻接矩阵表示法的C 语言描述如下:#define MAX_VERTEX_NUM 20 /*最多顶点个数*/#define INFINITY 32768 /*表示极大值,即∞*//* 图的种类:DG 表示有向图, DN 表示有向网, UDG 表示无向图, UDN 表示无向网 */typedef enum{DG, DN, UDG, UDN} GraphKind;typedef char VertexData; /*假设顶点数据为字符型*/ typedef struct ArcNode{AdjType adj; /* 对于无权图,用1或0表示是否相邻;对带权图,则为权值类型 */OtherInfo info; } ArcNode;typedef struct{VertexData vertex[MAX_VERTEX_NUM]; /*顶点向量*/ArcNode arcs [MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*邻接矩阵*/ int vexnum, arcnum; /*图的顶点数和弧数*/ GraphKind kind; /*图的种类标志*/ } AdjMatrix; /*(Adjacency Matrix Graph )*/邻接矩阵法的特点如下:● 存储空间: 对于无向图而言,它的邻接矩阵是对称矩阵(因为若(v i ,v j )∈E (G ),则(v j ,v i )∈E (G )),因此可以采用特殊矩阵的压缩存储法,即只存储其下三角即可,这样,一个具有n 个顶点的无向图G ,它的邻接矩阵需要n (n -1)/2个存储空间即可。

名词解释—邻接表:

名词解释—邻接表:

名词解释—邻接表
邻接表(Adjacency List)是一种常用的图数据结构,用于表示图中的顶点以及它们之间的连接关系。

在计算机科学中,图是由顶点和边组成的数据结构,可以用来表示各种复杂的网络关系,如社交网络、交通网络、电路等。

邻接表是表示图的一种有效方法,尤其适用于稀疏图(即边的数量相对较少的图)。

邻接表的核心思想是将每个顶点与其相邻的顶点列表相关联。

具体实现时,通常使用一个数组或链表来存储每个顶点的相邻顶点。

对于无向图,每个顶点都需要存储其相邻顶点的信息;对于有向图,只需要存储出度(从该顶点出发的边)或入度(指向该顶点的边)的相邻顶点信息。

邻接表的优点包括:
节省空间:邻接表仅存储实际存在的边,对于稀疏图来说非常节省空间。

便于添加和删除顶点:只需要修改相应的顶点列表即可。

便于查询邻接顶点:可以通过直接访问顶点的相邻顶点列表来查询邻接顶点。

图的两种存储方式---邻接矩阵和邻接表

图的两种存储方式---邻接矩阵和邻接表

图的两种存储⽅式---邻接矩阵和邻接表图:图是⼀种数据结构,由顶点的有穷⾮空集合和顶点之间边的集合组成,表⽰为G(V,E),V表⽰为顶点的集合,E表⽰为边的集合。

⾸先肯定是要对图进⾏存储,然后进⾏⼀系列的操作,下⾯对图的两种存储⽅式邻接矩阵和邻接表尽⾏介绍。

(⼀)、邻接矩阵存储:⽤两个数组分别进⾏存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。

存储顶点:⽤⼀个连续的空间存储n个顶点。

存储顶点之间的边:将由n个顶点组成的边⽤⼀个n*n的矩阵来存储,如果两个顶点之间有边,则表⽰为1,否则表⽰为0。

下⾯⽤代码来实现邻接矩阵的存储:#define SIZE 10class Graph{public:Graph(){MaxVertices = SIZE;NumVertices = NumEdges = 0;VerticesList = new char[sizeof(char)*MaxVertices];Edge = new int*[sizeof(int*)*MaxVertices];int i,j;for(i = 0;i<MaxVertices;i++)Edge[i] = new int[sizeof(int)*MaxVertices];for(i = 0;i<MaxVertices;i++){for(j = 0;j<MaxVertices;++j)Edge[i][j] = 0;}}void ShowGraph(){int i,j;cout<<"";for(i = 0;i<NumVertices;i++)cout<<VerticesList[i]<<"";cout<<endl;for(i = 0;i<NumVertices;i++){cout<<VerticesList[i]<<"";for(j = 0;j<NumVertices;j++)cout<<Edge[i][j] <<"";cout<<endl;}cout<<endl;}int GetVertexPos(char v){int i;for(i = 0;i<NumVertices;i++){if(VerticesList[i] == v)return i;}return -1;}~Graph(){Destroy();}void Insert(char v){if(NumVertices < MaxVertices){VerticesList[NumVertices] = v;NumVertices++;}}void InsertEdge(char v1,char v2){int i,j;int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2 == -1)return ;Edge[p1][p2] = Edge[p2][p1] = 1;NumEdges++;}void RemoveEdge(char v1,char v2){int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2== -1)return;if(Edge[p1][p2] == 0)return;Edge[p1][p2] = Edge[p2][p1] = 0;NumEdges--;}void Destroy(){delete[] VerticesList;VerticesList = NULL;for(int i = 0;i<NumVertices;i++){delete Edge[i];Edge[i] = NULL;}delete[] Edge;Edge = NULL;MaxVertices = NumVertices = 0;}void RemoveVertex(char v){int i,j;int p = GetVertexPos(v);int reNum = 0;if(p == -1)return;for(i = p;i<NumVertices-1;i++){VerticesList[i] = VerticesList[i+1];}for(i = 0;i<NumVertices;i++){if(Edge[p][i] != 0)reNum++;}for(i = p;i<NumVertices-1;i++){for(j = 0;j<NumVertices;j++){Edge[i][j] = Edge[i+1][j];}}for(i = p;i<NumVertices;i++){for(j = 0;j<NumVertices;j++)Edge[j][i] = Edge[j][i+1];}NumVertices--;NumEdges = NumEdges - reNum;}private:int MaxVertices;int NumVertices;int NumEdges;char *VerticesList;int **Edge;};上⾯的类中的数据有定义最⼤的顶点的个数(MaxVertices),当前顶点的个数(NumVertices),当前边的个数(NumEdges),保存顶点的数组,保存边的数组。

邻接表

邻接表

VerAdj cost
link
图 7.4 边结点 其中,VerAdj 域存放 V 的某个邻接顶点在顶点表中的序号;cost 域存放边<V,VerAdj>的权值;link 域存放指向 点显示的是边<V,VerAdj>的信息,因此称之为边结点。
对于无权图,边没有权值,边结点也就不需要包含 cost 域,所以边结点由两个域 VerAdj 和 l
(b) 若图为非权图,则 (1) aij =0; (2) aij =1, 当 i≠j, 且<Vi,Vj>存在时; (3) aij=∝,当且 i≠j, 且<Vi,Vj< /SUB> >不存在时。
称矩阵 A 为图的邻接矩阵。
显然,无向图的邻接矩阵是对称矩阵 .
上图所对应的邻接矩阵如下:
7.2.1.2 邻接表 我们首先给出边链表的概念:与顶点 V 邻接的所有顶点以某种次序组成的一个链表,被称为顶 所示:
对于无权图,边没有权值,边结点也就不需要包含 cost 域,所以边结点由两个域 VerAdj 和 l 用顺序存储方式存储图的顶点表 n-1,每个顶点的结构如图 7.5 所示
7.5 顶点结点
VerName adjacent
其中,VerName 域存放该顶点的名称,adjacent 域是指针域,存放指向 VerName 的边链表的头 adjacent 域存放的是顶点 VerName 的边链表的头指针。
info
头结点
data
firstarc
二、无向图的邻接表
ห้องสมุดไป่ตู้
图 7-5
三、有向图的邻接表和逆邻接表 (一)在有向图的邻接表中,第 i 个单链表链接的边都是顶点 i
发出的边。 (二)为了求第 i 个顶点的入度,需要遍历整个邻接表。因此可

名词解释邻接表

名词解释邻接表

邻接表邻接表(Adjacency List)是一种用于表示图的数据结构。

图是由节点(顶点)和边组成的数据结构,它们之间的关系可以用邻接表来表示和存储。

1. 图的基本概念在介绍邻接表之前,我们先简单了解一下图的基本概念。

•顶点(Vertex):也称为节点,是图中的一个元素。

顶点可以有一个或多个相关联的边。

•边(Edge):连接两个顶点的线段,表示两个顶点之间的关系。

•有向图(Directed Graph):每条边都有一个方向,从一个顶点指向另一个顶点。

•无向图(Undirected Graph):边没有方向,可以从任意一个顶点到达另一个顶点。

2. 邻接表的定义邻接表是一种用于表示图的数据结构,它使用链表来存储每个顶点及其相邻顶点之间的关系。

具体来说,对于每个顶点,我们使用一个链表来存储与该顶点相邻的其他顶点。

3. 邻接表的实现3.1 数据结构定义为了表示邻接表,我们需要定义两个数据结构:•节点(VertexNode):表示图中的一个顶点,包含一个指向第一个相邻顶点的指针。

•边(EdgeNode):表示图中的一条边,包含一个指向与之相邻的顶点的指针。

// 节点结构struct VertexNode {int vertex; // 顶点数据EdgeNode* firstEdge; // 指向第一条边的指针};// 边结构struct EdgeNode {int adjVertex; // 相邻顶点数据EdgeNode* nextEdge; // 指向下一条边的指针};3.2 邻接表的创建创建邻接表需要遍历图中每个顶点,并为每个顶点创建一个节点。

对于每个节点,我们需要遍历其相邻顶点,并为每个相邻顶点创建一条边。

// 创建邻接表void createAdjList(VertexNode*& adjList, int numOfVertices) {adjList = new VertexNode[numOfVertices]; // 创建节点数组for (int i = 0; i < numOfVertices; i++) {adjList[i].vertex = i + 1; // 给每个节点赋值cout << "请输入与" << adjList[i].vertex << "相邻的顶点(以0结束):" << endl;EdgeNode* pre = nullptr;EdgeNode* cur;int adjVertex;cin >> adjVertex;while (adjVertex != 0) {cur = new EdgeNode;cur->adjVertex = adjVertex;if (pre == nullptr) {adjList[i].firstEdge = cur;} else {pre->nextEdge = cur;}pre = cur;cin >> adjVertex;}}}3.3 邻接表的遍历遍历邻接表可以获取图中所有顶点及其相邻顶点的信息。

邻接表 + floyd算法

邻接表 + floyd算法

邻接表 + floyd算法
邻接表是一种表示图的数据结构,它通过链表的方式存储每个顶点的邻居节点。

在使用邻接表表示图的时候,我们可以使用floyd算法来求解任意两个顶点之间的最短路径。

floyd算法是一种求解图中任意两点最短路径的经典算法,它的基本思想是动态规划。

我们可以使用一个二维数组dist来存储任意两个顶点之间的最短路径,其中dist[i][j]表示从顶点i到顶点j
的最短路径长度。

在floyd算法中,我们通过对dist数组进行多次更新来求解最短路径。

具体来说,我们可以通过遍历所有顶点k,如果从顶点i到k再到顶点j的路径比当前的最短路径还要短,那么我们就更新
dist[i][j]的值为从顶点i到k再到顶点j的路径长度。

经过多次遍历后,dist数组中存储的就是任意两个顶点之间的最短路径长度。

使用邻接表和floyd算法可以方便地处理大规模的图。

在实际应用中,我们可以使用邻接表来存储图数据,然后使用floyd算法来求解最短路径。

由于floyd算法的时间复杂度为O(n^3),所以对于非常大的图,我们可能需要使用其他更为高效的算法来求解最短路径。

- 1 -。

邻接表表示法的特点

邻接表表示法的特点

邻接表表示法的特点
邻接表表示法是一种常用的图的存储方式,它是表示两个顶点之间连接关系的一种数据结构,它通过一种“键”和“值”的关系来表示图中各个结点和它们之间的边。

因此,邻接表表示法在图论以及图算法方面是非常有用的。

本文将介绍邻接表表示法的特点,并归纳总结出邻接表表示法的优点和缺点。

首先,邻接表表示法的特点之一就是存储利用率比较高。

邻接表表示法只需要存储节点和边的关系,而不需要存储节点的额外信息,因此它只需要占用少量的存储空间,而它可以表示图中所有的边,因此它支持非常大的图。

其实,它也可以支持连通图的存储,这一点极大的方便了读写操作,使得它可以被用来存储大型图。

此外,邻接表表示法还具有操作简单快捷的特点。

它可以把图中任意两个点之间的关系表示出来,并且可以简便地查找任意两个节点之间的路径,这对于寻找最短路径以及路径搜索来说非常有用。

邻接表表示法也可以很方便地操作权重边,所以它也可以用来表示容量图,带权图和特殊图。

最后,邻接表表示法的一个显著特点就是灵活的应用。

它可以用于表示不同类型的图,如无向图、有向图、带权图和容量图,这一点对于实际应用非常有用。

由于它可以表示图中任意两个点之间的边,因此它可以被用来表示一些复杂的网络,比如互联网和电话网络。

综上所述,邻接表表示法具有较高的存储利用率、操作简单快捷的特点和灵活的应用,因此它在数据结构与图算法方面是非常有用的
存储方式。

当前,邻接表表示法已经被广泛应用于实际的网络系统以及图算法开发中,它也一直在不断发展,一定会把图算法研究带到一个新的高度。

邻接表表示法的特点

邻接表表示法的特点

邻接表表示法的特点
邻接表是图或网络数据结构的一种重要表示方法,它可以有效地表示网络拓扑结构,在图论和网络分析中有着重要的应用。

邻接表的特点主要有以下几点:
一、数据存储的方便性
邻接表的表示方法能够以很方便的方式存储复杂的图数据,其中每个顶点会有非常多的相邻顶点,而邻接表可以有效地表示每个顶点的所有邻接点,使得数据的存储更加方便。

二、操作的便捷性
在操作邻接表时,可以实现对复杂的图网络数据的快速查询、统计,这样使得在处理大规模图数据时,变得更加方便。

三、图计算的效率
在使用邻接表来描述网络拓扑结构时,可以更加关注每个顶点之间的邻接关系,特别是在计算机图形学中,可以使用邻接表来快速计算图形网络的最佳路径等,极大地提升了图计算的效率。

四、实现的简易性
邻接表的实现比较简单,只需要实现一组简单的操作语句,就可以完成对图的描述,而且邻接表只需要一个数组,节省了存储空间,使实现变得更加简单。

总结:邻接表是图或网络数据结构的一种重要表示方法,其特点包括:(1)数据存储的方便性;(2)操作的便捷性;(3)图计算的效率;(4)实现的简易性。

邻接表在图论和网络分析中有着广泛的应用,
为复杂的图网络数据的快速查询和统计提供了可靠而有效的解决方案。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

邻接表存储表示Status Build_AdjList(ALGraph &G)//输入有向图的顶点数,边数,顶点信息和边的信息建立邻接表{InitALGraph(G);scanf("%d",&v);if(v<0) return ERROR;G.vexnum=v;scanf("%d",&a);if(a<0) return ERROR;G.arcnum=a;for(m=0;m<v;m++)G.vertices[m].data=getchar();for(m=1;m<=a;m++){t=getchar();h=getchar();if((i=LocateVex(G,t))<0) return ERROR;if((j=LocateVex(G,h))<0) return ERROR;p=(ArcNode*)malloc(sizeof(ArcNode));if(!G.vertices.[i].firstarc) G.vertices[i].firstarc=p;else{for(q=G.vertices[i].firstarc;q->nextarc;q=q->nextarc);q->nextarc=p;}p->adjvex=j;p->nextarc=NULL;}//whilereturn OK;}//Build_AdjList邻接多重表存储表示Status Build_AdjMulist(AMLGraph &G)//输入有向图的顶点数,边数,顶点信息和边的信息建立邻接多重表{InitAMLGraph(G);scanf("%d",&v);if(v<0) return ERROR; //顶点数不能为负G.vexnum=v;scanf(%d",&a);if(a<0) return ERROR; //边数不能为负G.arcnum=a;for(m=0;m<v;m++)G.adjmulist[m].data=getchar(); //输入各顶点的符号for(m=1;m<=a;m++){t=getchar();h=getchar(); //t为弧尾,h为弧头if((i=LocateVex(G,t))<0) return ERROR;if((j=LocateVex(G,h))<0) return ERROR; //顶点未找到p=(EBox*)malloc(sizeof(EBox));p->ivex=i;p->jvex=j;p->ilink=NULL;p->jlink=NULL; //边结点赋初值if(!G.adjmulist[i].firstedge) G.adjmulist[i].firstedge=p; else{q=G.adjmulist[i].firstedge;while(q){r=q;if(q->ivex==i) q=q->ilink;else q=q->jlink;}if(r->ivex==i) r->ilink=p;//else r->jlink=p; //}//elseif(!G.adjmulist[j].firstedge) G.adjmulist[j].firstedge=p; else{q=G.adjmulist[i].firstedge;while(q){r=q;if(q->jvex==j) q=q->jlink;else q=q->ilnk;}if(r->jvex==j) r->jlink=p;else r->ilink=p;}//else}//forreturn OK;}//Build_AdjList图的邻接表存储的15个基本操作int LocateVex(ALGraph G,VertexType u){int i;for(i=0;i<G.vexnum;++i)if(strcmp(u,G.vertices[i].data)==0)return i;return -1;}Status CreateGraph(ALGraph *G){int i,j,k;int w;VertexType va,vb;ArcNode *p;printf("请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3): ");scanf("%d",&(*G).kind);printf("请输入图的顶点数,边数: ");scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME);for(i=0;i<(*G).vexnum;++i){scanf("%s",(*G).vertices[i].data);(*G).vertices[i].firstarc=NULL;}if((*G).kind==1||(*G).kind==3) /* 网*/printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n");else /* 图*/printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):\n");for(k=0;k<(*G).arcnum;++k){if((*G).kind==1||(*G).kind==3)scanf("%d%s%s",&w,va,vb);else /* 图*/scanf("%s%s",va,vb);i=LocateVex(*G,va); /* 弧尾*/j=LocateVex(*G,vb); /* 弧头*/p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;if((*G).kind==1||(*G).kind==3) /* 网*/{p->info=(int *)malloc(sizeof(int));*(p->info)=w;}elsep->info=NULL;p->nextarc=(*G).vertices[i].firstarc;(*G).vertices[i].firstarc=p;if((*G).kind>=2){p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=i;if((*G).kind==3){p->info=(int*)malloc(sizeof(int));*(p->info)=w;}elsep->info=NULL;p->nextarc=(*G).vertices[j].firstarc;(*G).vertices[j].firstarc=p;}}return OK;}void DestroyGraph(ALGraph *G){int i;ArcNode *p,*q;(*G).vexnum=0;(*G).arcnum=0;for(i=0;i<(*G).vexnum;++i){p=(*G).vertices[i].firstarc;while(p){q=p->nextarc;if((*G).kind%2)free(p->info);free(p);p=q;}}}VertexType* GetVex(ALGraph G,int v){ /* 初始条件: 图G存在,v是G中某个顶点的序号。

操作结果: 返回v的值*/if(v>=G.vexnum||v<0)exit(ERROR);return &G.vertices[v].data;}Status PutVex(ALGraph *G,VertexType v,VertexType value){ /* 初始条件: 图G存在,v是G中某个顶点*//* 操作结果: 对v赋新值value */int i;i=LocateVex(*G,v);if(i>-1) /* v是G的顶点*/{strcpy((*G).vertices[i].data,value);return OK;}return ERROR;}int FirstAdjVex(ALGraph G,VertexType v){ /* 初始条件: 图G存在,v是G中某个顶点*//* 操作结果: 返回v的第一个邻接顶点的序号。

若顶点在G中没有邻接顶点,则返回-1 */ ArcNode *p;int v1;v1=LocateVex(G,v); /* v1为顶点v在图G中的序号*/p=G.vertices[v1].firstarc;if(p)return p->adjvex;elsereturn -1;}int NextAdjVex(ALGraph G,VertexType v,VertexType w){ /* 初始条件: 图G存在,v是G中某个顶点,w是v的邻接顶点*//* 操作结果: 返回v的(相对于w的)下一个邻接顶点的序号。

*//* 若w是v的最后一个邻接点,则返回-1 */ArcNode *p;int v1,w1;v1=LocateVex(G,v); /* v1为顶点v在图G中的序号*/w1=LocateVex(G,w); /* w1为顶点w在图G中的序号*/p=G.vertices[v1].firstarc;while(p&&p->adjvex!=w1)p=p->nextarc;if(!p||!p->nextarc)return -1;else /* p->adjvex==w */return p->nextarc->adjvex; /* 返回v的(相对于w的)下一个邻接顶点的序号*/}void InsertVex(ALGraph *G,VertexType v){ /* 初始条件: 图G存在,v和图中顶点有相同特征*//* 操作结果: 在图G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做) */ strcpy((*G).vertices[(*G).vexnum].data,v); /* 构造新顶点向量*/(*G).vertices[(*G).vexnum].firstarc=NULL;(*G).vexnum++; /* 图G的顶点数加1 */}Status DeleteVex(ALGraph *G,VertexType v){ /* 初始条件: 图G存在,v是G中某个顶点*//* 操作结果: 删除G中顶点v及其相关的弧*/int i,j;ArcNode *p,*q;j=LocateVex(*G,v); /* j是顶点v的序号*/if(j<0) /* v不是图G的顶点*/return ERROR;p=(*G).vertices[j].firstarc; /* 删除以v为出度的弧或边*/while(p){q=p;p=p->nextarc;if((*G).kind%2) /* 网*/free(q->info);free(q);(*G).arcnum--; /* 弧或边数减1 */}(*G).vexnum--; /* 顶点数减1 */for(i=j;i<(*G).vexnum;i++) /* 顶点v后面的顶点前移*/(*G).vertices[i]=(*G).vertices[i+1];for(i=0;i<(*G).vexnum;i++) /* 删除以v为入度的弧或边且必要时修改表结点的顶点位置值*/{p=(*G).vertices[i].firstarc; /* 指向第1条弧或边*/while(p) /* 有弧*/{if(p->adjvex==j){if(p==(*G).vertices[i].firstarc) /* 待删结点是第1个结点*/{(*G).vertices[i].firstarc=p->nextarc;if((*G).kind%2) /* 网*/free(p->info);free(p);p=(*G).vertices[i].firstarc;if((*G).kind<2) /* 有向*/(*G).arcnum--; /* 弧或边数减1 */}else{q->nextarc=p->nextarc;if((*G).kind%2) /* 网*/free(p->info);free(p);p=q->nextarc;if((*G).kind<2) /* 有向*/(*G).arcnum--; /* 弧或边数减1 */}}else{if(p->adjvex>j)p->adjvex--; /* 修改表结点的顶点位置值(序号) */q=p;p=p->nextarc;}}}return OK;}Status InsertArc(ALGraph *G,VertexType v,VertexType w){ /* 初始条件: 图G存在,v和w是G中两个顶点*//* 操作结果: 在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v> */ ArcNode *p;int w1,i,j;i=LocateVex(*G,v); /* 弧尾或边的序号*/j=LocateVex(*G,w); /* 弧头或边的序号*/if(i<0||j<0)return ERROR;(*G).arcnum++; /* 图G的弧或边的数目加1 */if((*G).kind%2) /* 网*/{printf("请输入弧(边)%s→%s的权值: ",v,w);scanf("%d",&w1);}p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;if((*G).kind%2){p->info=(int*)malloc(sizeof(int));*(p->info)=w1;}elsep->info=NULL;p->nextarc=(*G).vertices[i].firstarc; /* 插在表头*/(*G).vertices[i].firstarc=p;if((*G).kind>=2) /* 无向,生成另一个表结点*/{p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=i;if((*G).kind==3){p->info=(int*)malloc(sizeof(int));*(p->info)=w1;}elsep->info=NULL;p->nextarc=(*G).vertices[j].firstarc; /* 插在表头*/(*G).vertices[j].firstarc=p;}return OK;}Status DeleteArc(ALGraph *G,VertexType v,VertexType w){ /* 初始条件: 图G存在,v和w是G中两个顶点*//* 操作结果: 在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v> */ ArcNode *p,*q;int i,j;i=LocateVex(*G,v); /* i是顶点v(弧尾)的序号*/j=LocateVex(*G,w); /* j是顶点w(弧头)的序号*/if(i<0||j<0||i==j)return ERROR;p=(*G).vertices[i].firstarc; /* p指向顶点v的第一条出弧*/while(p&&p->adjvex!=j){ /* p指向下一条弧*/q=p;p=p->nextarc;}if(p&&p->adjvex==j){if(p==(*G).vertices[i].firstarc) /(*G).vertices[i].firstarc=p->nextarc; /* 指向下一条弧*/ elseq->nextarc=p->nextarc;if((*G).kind%2)free(p->info);free(p);(*G).arcnum--;}if((*G).kind>=2){p=(*G).vertices[j].firstarc;while(p&&p->adjvex!=i){ /* p指向下一条弧*/q=p;p=p->nextarc;}if(p&&p->adjvex==i){if(p==(*G).vertices[j].firstarc)(*G).vertices[j].firstarc=p->nextarc;elseq->nextarc=p->nextarc;if((*G).kind==3)free(p->info);free(p);}}return OK;}递归深度优先遍历Boolean visited[MAX_VERTEX_NUM];void(*VisitFunc)(char* v);void DFS(ALGraph G,int v){int w;VertexType v1,w1;strcpy(v1,*GetVex(G,v));visited[v]=TRUE;VisitFunc(G.vertices[v].data); /* 访问第v个顶点*/for(w=FirstAdjVex(G,v1);w>=0;w=NextAdjVex(G,v1,strcpy(w1,*GetVex(G,w))))if(!visited[w])DFS(G,w);}非递归深度优先遍历void DFSTraverse(ALGraph G,void(*Visit)(char*)){int v;VisitFunc=Visit;for(v=0;v<G.vexnum;v++)visited[v]=FALSE; /* 访问标志数组初始化*/for(v=0;v<G.vexnum;v++)if(!visited[v])DFS(G,v); /* 对尚未访问的顶点调用DFS */printf("\n");}广度优先遍历typedef int QElemType;void BFSTraverse(ALGraph G,void(*Visit)(char*))int v,u,w;VertexType u1,w1;LinkQueue Q;for(v=0;v<G.vexnum;++v)visited[v]=FALSE; /* 置初值*/InitQueue(&Q); /* 置空的辅助队列Q */for(v=0;v<G.vexnum;v++)if(!visited[v]){visited[v]=TRUE;Visit(G.vertices[v].data);EnQueue(&Q,v); /* v入队列*/while(!QueueEmpty(Q)) /* 队列不空*/{DeQueue(&Q,&u); /* 队头元素出队并置为u */strcpy(u1,*GetVex(G,u));for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))if(!visited[w]){visited[w]=TRUE;Visit(G.vertices[w].data);EnQueue(&Q,w); /* w入队*/}}}printf("\n");}邻接矩阵void Display(ALGraph G)int i;ArcNode *p;switch(G.kind){case DG: printf("有向图\n");break;case DN: printf("有向网\n");break;case AG: printf("无向图\n");break;case AN: printf("无向网\n");}printf("%d个顶点:\n",G.vexnum);for(i=0;i<G.vexnum;++i)printf("%s ",G.vertices[i].data);printf("\n%d条弧(边):\n",G.arcnum);for(i=0;i<G.vexnum;i++){p=G.vertices[i].firstarc;while(p){if(G.kind<=1) /* 有向*/{printf("%s→%s ",G.vertices[i].data,G.vertices[p->adjvex].data);if(G.kind==DN) /* 网*/printf(":%d ",*(p->info));}else /* 无向(避免输出两次) */{if(i<p->adjvex){printf("%s-%s ",G.vertices[i].data,G.vertices[p->adjvex].data);if(G.kind==AN) /* 网*/printf(":%d ",*(p->info));}}p=p->nextarc;}printf("\n");}}。

相关文档
最新文档