图采用邻接矩阵存储结构

合集下载

图-存储结构-数组表示法(邻接矩阵)

图-存储结构-数组表示法(邻接矩阵)

图-存储结构-数组表⽰法(邻接矩阵)⽂字描述 ⽤两个数组分别存储顶点信息和边/弧信息。

⽰意图算法分析 构造⼀个采⽤邻接矩阵作存储结构、具有n个顶点和e条边的⽆向⽹(图)G的时间复杂度是(n*n + e*n), 其中对邻接矩阵G.arcs的初始化耗费了n*n的时间。

借助于邻接矩阵容易判定两个顶点之间是否有边/弧相连,并容易求得各个顶点的度。

对于⽆向图,顶点vi的度是邻接矩阵地i⾏(或第i列)的元素之和;对于有向图,第i⾏的元素之和为顶点vi的出度;第j列的元素之和为顶点vj的⼊度;代码实现1/*2以数组表⽰法(邻接矩阵)作为图的存储结构创建图。

3*/4 #include <stdio.h>5 #include <stdlib.h>6 #include <string.h>78#define INFINITY 100000 //最⼤值9#define MAX_VERTEX_NUM 20 //最⼤顶点数10 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向⽹,⽆向图,⽆向⽹}11 typedef int VRType;12 typedef char VertexType;13 typedef struct{14char note[10];15 }InfoType;16 typedef struct ArcCell{17 VRType adj; //顶点关系类型:1)对⽆权图,⽤1或0表⽰相邻否;2)对带权图,则为权值类型18 InfoType *info; //该弧相关信息的指针19 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];20 typedef struct{21 VertexType vexs[MAX_VERTEX_NUM]; //顶点向量22 AdjMatrix arcs; //邻接矩阵23int vexnum, arcnum; //图的当前顶点数和弧数24 GraphKind kind; //图的种类标志25 }MGraph;2627/*28若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。

实现图的邻接矩阵和邻接表存储

实现图的邻接矩阵和邻接表存储

实现图的邻接矩阵和邻接表存储1.需求分析对于下图所示的有向图G,编写一个程序完成如下功能:1.建立G的邻接矩阵并输出之2.由G的邻接矩阵产生邻接表并输出之3.再由2的邻接表产生对应的邻接矩阵并输出之2.系统设计1.图的抽象数据类型定义:ADT Graph{数据对象V:V是具有相同特性的数据元素的集合,称为顶点集数据关系R:R={VR}VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}基本操作P:CreatGraph(&G,V,VR)初始条件:V是图的顶点集,VR是图中弧的集合操作结果:按V和VR的定义构造图GDestroyGraph(&G)初始条件:图G存在操作结果:销毁图GInsertVex(&G,v)初始条件:图G存在,v和图中顶点有相同特征操作结果:在图G中增添新顶点v……InsertArc(&G,v,w)初始条件:图G存在,v和w是G中两个顶点操作结果:在G中增添弧<v,w>,若G是无向的则还增添对称弧<w,v>……DFSTraverse(G,Visit())初始条件:图G存在,Visit是顶点的应用函数操作结果:对图进行深度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。

一旦Visit()失败,则操作失败BFSTraverse(G,Visit())初始条件:图G存在,Visit是顶点的应用函数操作结果:对图进行广度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。

一旦Visit()失败,则操作失败}ADT Graph2.主程序的流程:调用CreateMG函数创建邻接矩阵M;调用PrintMatrix函数输出邻接矩阵M调用CreateMGtoDN函数,由邻接矩阵M创建邻接表G调用PrintDN函数输出邻接表G调用CreateDNtoMG函数,由邻接表M创建邻接矩阵N调用PrintMatrix函数输出邻接矩阵N3.函数关系调用图:3.调试分析(1)在MGraph的定义中有枚举类型typedef enum{DG,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网}赋值语句G.kind(int)=M.kind(GraphKind);是正确的,而反过来M.kind=G.kind则是错误的,要加上那个强制转换M.kind=GraphKind(G.kind);枚举类型enum{DG,DN,UDG,UDN}会自动赋值DG=0;DN=1,UDG=2,UDN=3;可以自动从GraphKind类型转换到int型,但不会自动从int型转换到GraphKind类型(2)算法的时间复杂度分析:CreateMG、CreateMGtoDN、CreateDNtoMG、PrintMatrix、PrintDN的时间复杂度均为O(n2) n为图的顶点数,所以main:T(n)= O(n2)4.测试结果用需求分析中的测试数据输入:输出:5、用户手册(1)输入顶点数和弧数;(2)输入顶点内容;(3)按行序输入邻接矩阵,输入各弧相应权值(4)回车输出邻接矩阵M、邻接表G和邻接矩阵N6、附录源程序:#include <stdio.h>#include <stdlib.h>#define MAX_VERTEX_NUM 20typedef int VRType;typedef int InfoType;typedef int VertexType;typedef enum{DG,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网} typedef struct ArcCell{VRType adj;//VRType是顶点关系类型,对无权图用1或0表示是否相邻;//对带权图则为权值类型InfoType *info;//该弧相关信息的指针}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct{VertexType vexs[MAX_VERTEX_NUM];//顶点向量AdjMatrix arcs;//邻接矩阵int vexnum,arcnum;//图的当前顶点数和弧数GraphKind kind;//图的种类标志}MGraph;void CreateMG(MGraph &M){int i,j;M.kind=DN;printf("输入顶点数:");scanf("%d",&M.vexnum);printf("输入弧数:");scanf("%d",&M.arcnum);printf("输入顶点:\n");for(i=0;i<M.vexnum;i++)scanf("%d",&M.vexs[i]);printf("建立邻接矩阵:\n");for(i=0;i<M.vexnum;i++)for(j=0;j<M.vexnum;j++)scanf("%d",&M.arcs[i][j].adj);printf("输入相应权值:\n");for(i=0;i<M.vexnum;i++)for(j=0;j<M.vexnum;j++)if(M.arcs[i][j].adj){scanf("%d",&M.arcs[i][j].info);}}typedef struct ArcNode{int adjvex;//该弧所指向的顶点在数组中的下标struct ArcNode *nextarc;InfoType *info;//该弧相关信息的指针}ArcNode;typedef struct VNode{VertexType data;//顶点信息ArcNode *firstarc;//指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;//图的当前顶点数和弧数int kind;//图的种类标志}ALGraph;void PrintDN(ALGraph G){int i;ArcNode *p;printf("顶点:\n");for(i=0;i<G.vexnum;++i)printf("%2d",G.vertices[i].data);printf("\n弧:\n");for(i=0;i<G.vexnum;++i){p=G.vertices[i].firstarc;while(p){printf("%d→%d(%d)\t",i,p->adjvex,p->info);p=p->nextarc;}printf("\n");}//for}void CreateMGtoDN(ALGraph &G,MGraph M){//采用邻接表存储表示,构造有向图G(G.kind=DN)int i,j;ArcNode *p;G.kind=M.kind;G.vexnum=M.vexnum;G.arcnum=M.arcnum;for(i=0;i<G.vexnum;++i){//构造表头向量G.vertices[i].data=M.vexs[i];G.vertices[i].firstarc=NULL;//初始化指针}for(i=0;i<G.vexnum;++i)for(j=0;j<G.vexnum;++j)if(M.arcs[i][j].adj==1){p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;p->nextarc=G.vertices[i].firstarc;p->info=M.arcs[i][j].info;G.vertices[i].firstarc=p;}}void CreateDNtoMG(MGraph &M,ALGraph G){int i,j;ArcNode *p;M.kind=GraphKind(G.kind);M.vexnum=G.vexnum;M.arcnum=G.arcnum;for(i=0;i<M.vexnum;++i)M.vexs[i]=G.vertices[i].data;for(i=0;i<M.vexnum;++i){p=G.vertices[i].firstarc;while(p){M.arcs[i][p->adjvex].adj=1;p=p->nextarc;}//whilefor(j=0;j<M.vexnum;++j)if(M.arcs[i][j].adj!=1)M.arcs[i][j].adj=0;}//for}void PrintMatrix(MGraph M){ int i,j;for(i=0;i<M.vexnum;++i){for(j=0;j<M.vexnum;++j) printf("%2d",M.arcs[i][j].adj); printf("\n");}}void main(){MGraph M,N;ALGraph G; CreateMG(M);PrintMatrix(M); CreateMGtoDN(G,M); PrintDN(G); CreateDNtoMG(N,G); PrintMatrix(N);}。

《数据结构》第八章习题参考答案 (1)

《数据结构》第八章习题参考答案 (1)
邻接表表示时:无向图的任意顶点的度=顶点所对应边结点链表中结点个数;
有向图的任意顶点的度=邻接表中顶点所对应边链表中结点个数+逆邻接表中顶点所对应边链表中结点个数;
4、课本P3928.3题
【解答】
n个顶点的无向连通图至少有n-1条边,n个பைடு நூலகம்点的无向强连通图至少有n(n-1)/2条边;n个顶点的有向连通图至少有n条边,n个顶点的有向强连通图至少有n(n-1)条边。
上面不正确的是(A)。
A.(1),(2),(3) B.(1) C.(1),(3) D.(2),(3)
5、下列说法不正确的是(C)。
A.图的遍历是从给定的源点出发每一个顶点仅被访问一次
B.遍历的基本算法有两种:深度遍历和广度遍历
C.图的深度遍历不适用于有向图
D.图的深度遍历是一个递归过程
三、填空题
1、判断一个无向图是一棵树的条件是_有n个顶点,n-1条边的无向连通图_。
注: 答案并不唯一
2、课本P3928.1题
【解答】
(1)不是强连通图
(2)简单路径如:D->B->C->F
(3)略
(4)邻接表见图,其他略
3、课本P3928.2题
【解答】
(1)邻接矩阵表示:无向图的边数为
矩阵中非零元素的个数/2;有向图的边数为矩阵中非零元素的个数。
邻接表表示时:无向图的边数为邻接表中边结点的个数/2;有向图的边数为邻接表中边结点的个数。
(2)(3)略
12、课本P3958.24题
【解答】
A->B : 10
A->B->D: 15
A->B->D->C : 17
A->B->D->E : 17

图的常用存储结构

图的常用存储结构

图的常⽤存储结构⼀、邻接矩阵 邻接矩阵是简单的也是⽐较常⽤的⼀种表⽰图的数据结构,对于⼀个有N个点的图,需要⼀个N*N的矩阵,这个矩阵的i⾏第j列的数值表⽰点vi到点vj的距离。

邻接矩阵需要初始化,map[i][i] = 0;map[i][j] = INF(i != j),对于每组读⼊的数据vi,vj,w(vi为边的起点,vj为边的终点,w为边的权值),赋值map[vi][vj] = w,另外邻接矩阵的值和边的输⼊顺序⽆关。

对于邻接矩阵来说,初始化需要O(n^2)的时间,建图需要O(m),所以总时间复杂度是O(n^2),空间上,邻接矩阵的开销也是O(n^2),和点的个数有关。

⼆、前向星 前向星是⼀种通过存储边的⽅式来存储图的数据结构。

构造的时候,只需要读⼊每条边的信息,将边存放在数组中,把数组中的边按照起点顺序排序,前向星就构造完毕,为了查询⽅便,经常会有⼀个数组存储起点为vi的第⼀条边的位置. 由于涉及排序,前向星的构造时间复杂度与排序算法有关,⼀般情况下时间复杂度为O(mlogN),空间上需要两个数组,所以空间复杂度为O(m + n),有点在于可以应对点⾮常多的情况,可以存储重边,但是不能直接判断任意两个顶点之间是否有边.1 #include <iostream>2 #include <cmath>3 #include <cstdio>4 #include <cstring>5 #include <cstdlib>6 #include <algorithm>7using namespace std;8 typedef long long LL;910const int MAXN = 1000 + 3;11int head[MAXN]; //存储起点为Vi的边第⼀次出现的位置1213struct NODE14 {15int from;16int to;17int w;18 };19 NODE edge[MAXN];2021bool cmp(NODE a, NODE b)22 {23if(a.from == b.from && a.to == b.to) return a.w < b.w;24if(a.from == b.from) return a.to < b.to;25return a.from < b.from;26 }2728int main()29 {30 freopen("input.txt", "r", stdin);31int n,m;32 cin >> n >> m;33for(int i = 0; i < m; i++)34 {35 cin >> edge[i].from >> edge[i].to >> edge[i].w;36 }37 sort(edge, edge + m, cmp);38 memset(head, -1, sizeof(head));39 head[edge[0].from] = 0;40for(int i = 1; i < m; i++)41 {42if(edge[i].from != edge[i - 1].from)43 {44 head[edge[i].from] = i;45 }46 }47for(int i = 1; i <= n; i++)48 {49for(int k = head[i]; edge[k].from == i && k < m; k++)50 {51 cout << edge[k].from << '' << edge[k].to << '' << edge[k].w <<endl;52 }53 }54for(int i = 0; i <= n; i++)55 {56 cout << head[i] << "";57 }58 cout << endl;59return0;60 }三、链式前向星 链式前向星采⽤数组模拟链表的⽅式实现邻接表的功能,并且使⽤很少的额外空间,是当前建图和遍历效率最⾼的存储⽅式.数组模拟链表的主要⽅式是记录下⼀个节点的数组的在哪⼀个位置。

数据结构 第7章习题答案

数据结构 第7章习题答案

第7章 《图》习题参考答案一、单选题(每题1分,共16分)( C )1. 在一个图中,所有顶点的度数之和等于图的边数的 倍。

A .1/2 B. 1 C. 2 D. 4 (B )2. 在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的 倍。

A .1/2 B. 1 C. 2 D. 4 ( B )3. 有8个结点的无向图最多有 条边。

A .14 B. 28 C. 56 D. 112 ( C )4. 有8个结点的无向连通图最少有 条边。

A .5 B. 6 C. 7 D. 8 ( C )5. 有8个结点的有向完全图有 条边。

A .14 B. 28 C. 56 D. 112 (B )6. 用邻接表表示图进行广度优先遍历时,通常是采用 来实现算法的。

A .栈 B. 队列 C. 树 D. 图 ( A )7. 用邻接表表示图进行深度优先遍历时,通常是采用 来实现算法的。

A .栈 B. 队列 C. 树 D. 图 ()8. 已知图的邻接矩阵,根据算法思想,则从顶点0出发按深度优先遍历的结点序列是( D )9. 已知图的邻接矩阵同上题8,根据算法,则从顶点0出发,按深度优先遍历的结点序列是A . 0 2 4 3 1 5 6 B. 0 1 3 5 6 4 2C. 0 4 2 3 1 6 5D. 0 1 2 34 6 5 ( D )10. 已知图的邻接表如下所示,根据算法,则从顶点0出发按深度优先遍历的结点序列是( A )11. 已知图的邻接表如下所示,根据算法,则从顶点0出发按广度优先遍历的结点序列是A .0 2 4 3 1 5 6B. 0 1 3 6 5 4 2C. 0 1 3 4 2 5 6D. 0 3 6 1 5 4 2⎥⎥⎥⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡0100011101100001011010110011001000110010011011110A .0 1 3 2 B. 0 2 3 1 C. 0 3 2 1 D. 0 1 2 3(A)12. 深度优先遍历类似于二叉树的A.先序遍历 B. 中序遍历 C. 后序遍历 D. 层次遍历(D)13. 广度优先遍历类似于二叉树的A.先序遍历 B. 中序遍历 C. 后序遍历 D. 层次遍历(A)14. 任何一个无向连通图的最小生成树A.只有一棵 B. 一棵或多棵 C. 一定有多棵 D. 可能不存在(注,生成树不唯一,但最小生成树唯一,即边权之和或树权最小的情况唯一)二、填空题(每空1分,共20分)1. 图有邻接矩阵、邻接表等存储结构,遍历图有深度优先遍历、广度优先遍历等方法。

数据结构课程设计-图的邻接矩阵

数据结构课程设计-图的邻接矩阵

数据结构课程设计报告设计题目:图的邻接矩阵存储结构院系计算机学院年级x 级学生xxxx学号xxxxxxxxxx指导教师xxxxxxxxx起止时间10-6/10-102013年10月10日目录1 需求分析 (3)2 概要设计 (4)2.1 ADT描述 (4)2.2程序模块结构 (5)2.3各功能模块 (6)3详细设计 (7)3.1类的定义 (7)3.2 初始化 (8)3.3 图的构建操作 (8)3.4 输出操作 (9)3.5 get操作 (9)3.6 插入操作 (10)3.7 删除操作 (10)3.8 求顶点的度操作 (11)3.10 判断连通操作 (12)3.11 主函数 (13)4 调试分析 (16)4.1调试问题 (16)4.2 算法时间复杂度 (16)5用户手册 (16)5.1 主界面 (16)5.2 创建图 (17)5.3插入节点 (17)5.4 深度优先遍历 (17)5.5 求各顶点的度 (18)5.6 输出图 (18)5.7 判断是否连通 (19)5.8 求边的权值 (19)5.9 插入边 (19)5.10 删除边 (20)结论 (20)参考文献 (20)摘要随着计算机的普及,涉及计算机相关的科目也越来越普遍,其中数据结构是计算机专业重要的专业基础课程与核心课程之一,为适应我国计算机科学技术的发展和应用,学好数据结构非常必要,然而要掌握数据结构的知识非常难,所以对“数据结构”的课程设计比不可少。

本说明书是对“无向图的邻接矩阵存储结构”课程设计的说明。

首先是对需求分析的简要阐述,说明系统要完成的任务和相应的分析,并给出测试数据。

其次是概要设计,说明所有抽象数据类型的定义、主程序的流程以及各程序模块之间的层次关系,以及ADT描述。

然后是详细设计,描述实现概要设计中定义的基本功操作和所有数据类型,以及函数的功能及代码实现。

再次是对系统的调试分析说明,以及遇到的问题和解决问题的方法。

然后是用户使用说明书的阐述,然后是测试的数据和结果的分析,最后是对本次课程设计的结论。

2013吉林省数据库考试含答案基础

2013吉林省数据库考试含答案基础

1、假设以邻接矩阵作为图的存储结构,编写算法判别在给定的有向图中是否存在一个简单有向回路,若存在,则以顶点序列的方式输出该回路(找到一条即可)。

(注:图中不存在顶点到自己的弧)有向图判断回路要比无向图复杂。

利用深度优先遍历,将顶点分成三类:未访问;已访问但其邻接点未访问完;已访问且其邻接点已访问完。

下面用0,1,2表示这三种状态。

前面已提到,若dfs(v)结束前出现顶点u到v的回边,则图中必有包含顶点v和u的回路。

对应程序中v的状态为1,而u是正访问的顶点,若我们找出u的下一邻接点的状态为1,就可以输出回路了。

void Print(int v,int start ) //输出从顶点start开始的回路。

{for(i=1;i<=n;i++)if(g[v][i]!=0 && visited[i]==1 ) //若存在边(v,i),且顶点i的状态为1。

{printf(“%d”,v);if(i==start) printf(“\n”); else Print(i,start);break;}//if}//Printvoid dfs(int v){visited[v]=1;for(j=1;j<=n;j++ )if (g[v][j]!=0) //存在边(v,j)if (visited[j]!=1) {if (!visited[j]) dfs(j); }//ifelse {cycle=1; Print(j,j);}visited[v]=2;}//dfsvoid find_cycle() //判断是否有回路,有则输出邻接矩阵。

visited数组为全局变量。

{for (i=1;i<=n;i++) visited[i]=0;for (i=1;i<=n;i++ ) if (!visited[i]) dfs(i);}//find_cycle2、设T是一棵满二叉树,编写一个将T的先序遍历序列转换为后序遍历序列的递归算法。

邻接表 和邻接矩阵

邻接表 和邻接矩阵

邻接表和邻接矩阵
邻接表和邻接矩阵是表示图的两种常用数据结构,它们用于描述图中各个顶点之间的连接关系。

具体分析如下:
- 邻接表:邻接表是一种链表数组,其中每个数组元素对应一个顶点,并且包含一个链表,链表中的每个节点代表与该顶点相邻的顶点。

这种结构特别适合于表示稀疏图,即边的数量远小于顶点数量的平方的图。

在邻接表中,对于每个顶点,只需要存储与其直接相连的顶点,因此可以节省空间。

当图的顶点较多,且图为稀疏图时,邻接表通常是更合适的选择。

- 邻接矩阵:邻接矩阵是一种二维数组,其中行和列都代表图中的顶点。

如果两个顶点之间存在边,则相应的矩阵元素值为1(或者边的权重,如果是带权图),否则为0。

邻接矩阵适用于表示稠密图,即边的数量接近顶点数量的平方的图。

邻接矩阵的优点是可以快速地判断任意两个顶点之间是否存在边,但是当图非常稀疏时,它会占用较多的内存空间。

总的来说,邻接表和邻接矩阵各有优势,选择哪种数据结构取决于具体的应用场景。

如果图是稀疏的,并且需要节省存储空间,邻接表通常更合适;如果需要快速查询任意两点之间的关系,而图又相对稠密,邻接矩阵可能是更好的选择。

2011上半年软件设计师试题与答案.

2011上半年软件设计师试题与答案.

1在CPU中用于跟踪指令地址的寄存器是—1—。

A .地址寄存器(MAR)B .数据寄存器(MDR)C .程序计数器(PC)D .指令寄存器(IR)2指令系统中采用不同寻址方式的目的是—2_。

A .提高从内存获取数据的速度B .提高从外存获取数据的速度C •降低操作码的译码难度D •扩大寻址空间并提高编程灵活性3在计算机系统中采用总线结构,便于实现系统的积木化构造,同时可以—3—。

A .提高数据传输速度B .提高数据传输量C .减少信息传输线的数量D .减少指令系统的复杂性4原码表示法和补码表示法是计算机中用于表示数据的两种编码方法,在计算机系统中常采用补码来表示和运算数据,原因是采用补码可以_______________________ 4_。

A •保证运算过程与手工运算方法保持一致B .简化计算机运算部件的设计C .提高数据的运算速度D .提高数据的运算精度5计算机中的浮点数由三部分组成:符号位S,指数部分E(称为阶码)和尾数部分M。

在总长度固定的情况下,增加E的位数、减少M的位数可以__5 ________ 。

A .扩大可表示的数的范围同时降低精度B .扩大可表示的数的范围同时提高精度C .减小可表示的数的范围同时降低精度D .减小可表示的数的范围同时提高精度6某计算机系统由下图所示的部件构成,假定每个部件的干小时可靠度都为R,则该系统的千小时可靠度为 6 。

A . R+2R/4 B. R+R2/4 C . R(1-(1-R)2 ) D. R(1-(1-R)2 )27用户A从CA获得用户B的数字证书,并利用_______ 7—验证数字证书的真实性。

A . B的公钥B . B的私钥C . CA的公钥D . CA的私钥8宏病毒一般感染以__8 ____ 为扩展名的文件。

A . EXEB . COMC . DOCD . DLL9在IE浏览器中,安全级别最高的区域设置是_______ 9_。

A . In ternetB .本地IntranetC.可信站点D.受限站点10下列关于软件著作权中翻译权的叙述不正确的是:翻译权是指—10— 的权利。

分别以邻接矩阵和邻接表作为图的存储结构

分别以邻接矩阵和邻接表作为图的存储结构

分别以邻接矩阵和邻接表作为图的存储结构,给出连通图的深度优先遍历的递归算法算法思想:(1)访问出发点vi,并将其标记为已访问过。

(2)遍历vi的的每一个邻接点vj,若vi未曾访问过,则以vi为新的出发点继续进行深度优先遍历。

算法实现:Boolean visited[max]; // 访问标志数void DFS(Graph G, int v){ // 算法7.5从第v个顶点出发递归地深度优先遍历图Gint w;visited[v] = TRUE; printf("%d ",v); // 访问第v个顶点for (w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G, v, w)) if (!visited[w]) // 对v的尚未访问的邻接顶点w递归调用DFS DFS(G, w);}/*****************************************************/ /*以邻接矩阵作为存储结构*/DFS1(MGraph G,int i){int j;visited[i]=1;printf("%c",G.vexs[i]);for(j=1;j<=G.vexnum;j++)if(!visited[j]&&G.arcs[i][j]==1) DFS1(G,j);}/*以邻接表作为存储结构*/DFS2(ALGraph G,int i){int j;ArcPtr p;visited[i]=1;printf("%c",G.vertices[i].data);for(p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc){j=p->adjvex;if(!visited[j]) DFS2(j);}}。

邻接矩阵和邻接表

邻接矩阵和邻接表

邻接矩阵和邻接表邻接矩阵与邻接表都是建立在图结构中的逻辑关系,用于存储图中相邻节点之间的连接关系,是用来表示网络的重要的数据结构,大量应用于无权图或带权图的表示、存储和操作。

一、邻接矩阵1.概念:邻接矩阵(Adjacency Matrix)是一种用来存储图G中顶点之间的关系的结构,它是由一个二维数组来表示的,数组中的每一行和每一列都代表一个顶点,而数组元素之间的值有一定含义,这些值代表了两个顶点之间是否存在连接,也就是说,只有存在边才能够表示值,否则以无穷大表示。

2.特点:(1)存储空间大:邻接矩阵是一个矩形数组,其中的每一行和每一列都代表一个顶点,那么它所占用的空间一定是与节点的度数有关的,因此在稀疏图结构中使用邻接矩阵对空间也会非常消耗;(2)查找方便:邻接矩阵存储的是节点两两之间的连接关系,只要矩阵中相应位置上的值不为无穷大,就能判断这两个节点之间是否存在连接,因此在查找图中某两节点之间连接关系的时候,邻接矩阵的效率会比较高。

二、邻接表1.概念:邻接表也是一种非常常用的表示图的数据结构,它采用的是链表的形式来存储顶点的相邻的结点的关系,也就是说,每个顶点都会有一个链表来存储它周围的结点。

它能够比较好的展示出图中各个顶点之间的关系,以及图中结点的孤立情况。

2.特点:(1)存储空间小:由于邻接表使用链表的方式存储节点,它可以精确的表示两个节点的距离,而非像邻接矩阵一样,数组中的每一行和每一列都代表一个节点,因此,它所占用的空间会比邻接矩阵小些,在内存空间中有比较大的空间优势;(2)查找速度略低:虽然邻接表能精确的表示两个节点之间的距离,而且只需要占用少量内存,但是查找两点之间连接关系所花费的时间会略大于邻接矩阵。

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

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

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;}。

图的三种存储方式

图的三种存储方式

图的三种存储⽅式⼀、邻接矩阵适⽤:稠密图,就是说点数的平⽅与边数接近的情况,换句话说就是边特别多。

不适⽤:稀疏图,就是点数的平⽅与边数差的特别多,边数少,但点数多,就不⾏了,因为空间占⽤太⼤了。

实现代码#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量int n;int v[N][N]; //邻接矩阵/*** 测试数据40 5 2 35 0 0 12 0 0 43 14 0*/int main() {cin >> n;//读⼊到邻接矩阵for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)cin >> v[i][j];//下⾯的代码将找到与点i有直接连接的每⼀个点以及那条边的长度for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)if (v[i][j]) cout << "edge from point "<< i << " to point " << j << " with length " << v[i][j] << endl;return 0;}⼆、邻接表#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量struct Edge { //记录边的终点,边权的结构体int to; //终点int value; //边权};int n, m; //表⽰图中有n个点,m条边vector<Edge> p[N]; //使⽤vector的邻接表/*** 测试数据4 62 1 11 3 24 1 42 4 64 2 33 4 5*/int main() {cin >> n >> m;//m条边for (int i = 1; i <= m; i++) {int u, v, l; //点u到点v有⼀条权值为l的边cin >> u >> v >> l;p[u].push_back({v, l});}//输出for (int i = 1; i <= n; i++) {printf("出发点:%d ", i);for (int j = 0; j < p[i].size(); j++)printf(" ⽬标点:%d,权值:%d;", p[i][j].to, p[i][j].value);puts("");}return 0;}三、链式前向星链式前向星是邻接表存图的第⼆种⽅法,它⾃⼰还有两种写法,⽐⽤向量存图的那种邻接表要快。

数据结构习题集

数据结构习题集

数据结构习题集一、判断题:1.图可以没有边,但不能没有顶点。

( )2.在无向图中,(v1,v2)和(v2,v1)是两条不同的边。

(X)3.邻接表只能用于有向图的存储。

(X)4.一个图的邻接矩阵表示是唯一的。

( )5.用邻接矩阵法存储一个图时,所占用的存储空间大小与图中顶点个数无关,而只与图的边数有关。

(X)6.有向图不能进行广度优先遍历。

(X)7.若一个无向图以顶点v1为起点进行深度优先遍历,所得的遍历序列唯一,则可以唯一确定该图。

( )8.存储无向图的邻接矩阵是对称的,因此只要存储邻接矩阵上三角(或下三角)部分就可以了。

( )9.用邻接表法存储图时,占用的存储空间大小只与图中的边数有关,而与结点的个数无关。

(X)10.若从一个无向图中任一顶点出发,进行一次深度优先遍历,就可以访问图中所有的顶点,则该图一定是连通的。

( )11.二分查找法要求待查表的关键字值必须有序。

()12.对有序表而言,采用二分查找部总比采用顺序查找法速度快。

()13.在二叉排序树中,根结点的值都小于孩子结点的值。

()14.散列存储法的基本思想是由关键字的值决定数据的存储地址。

()15.哈希表是一种将关键字转换为存储地址的存储方法。

()16.选择好的哈希函数就可以避免冲突的发生。

()17.在有序的顺序表和有序的链表上,均可以采用二分查找来提高查找的速度。

()18.采用分块查找,既能实现线性表所希望的查找速度,又能适应动态变化的需要。

()19.哈希查找的效率主要取决于哈希表构造时选取的哈希函数和处理冲突的方法。

()20.在二叉排序树上删除一个结点时,不必移动其他结点,只要将该结点的父结点的相应指针域置空即可。

()二、填空题:1.图常用的存储方式有邻接矩阵和等。

2.图的遍历有和广度优先搜索等方法。

3.有n条边的无向图邻接矩阵中,1的个数是。

4.有向图的边也称为。

5.图的邻接矩阵表示法是表示之间相信关系的矩阵。

6.有向图G用邻接矩阵存储,其第i行的所有元素之和等于顶点i的。

图的两种存储结构及基本算法

图的两种存储结构及基本算法

图的两种存储结构及基本算法第一篇:图的两种存储结构及基本算法一、图的邻接矩阵存储1.存储表示#definevexnum10typedefstruct{vextypevexs[vexnum];intarcs[vexnum][vexnum];}mgraph;2.建立无向图的邻接矩阵算法voidcreat(mgraph*g, inte){for(i=0;iscanf(“%c”,&g->vexs[i]);for(i=0;ifor(j=0;jg->arcs[i][j]=0;for(k=0;kscanf(“%d,%d”,&i,&j);g->arcs[i][j]=1;g->arcs[j][i]=1;} }3.建立有向图的邻接矩阵算法voidcreat(mgraph*g, inte){for(i=0;iscanf(“%c”,&g->vexs[i]);for(i=0;ifor(j=0;jg->arcs[i][j]=0;for(k=0;kscanf(“%d,%d,%d”,&i,&j,&w);g->arcs[i][j]=w;}}二、图的邻接表存储1.邻接表存储表示#definevexnum10typedefstructarcnode{intadjvex;structarcnode*nextarc;}Arcnode;typedefstructvnode{vextypedata;Arcnode*firstarc;}Vnode;typedefstruct{Vnodevertices[vexnum];intvexnum,arcnum;}algraph;2.建立无向图的邻接表算法:voidcreat(algraph*g, inte){for(i=0;iscanf(“%c”,&g->vertices[i]->data);g->vertices[i]->firstarc=NULL;}for(k=0;kscanf(“%d,%d”,&i,&j);q=(Arcnode*)malloc(sizeof(Arcnode));p=(Arcnode*)malloc(s izeof(Arcnode));p->adjvex=j;p->nextarc=g->vertices[i]->firstarc;g->vertices[i]->firstarc=p;q->adjvex=i;q->nextarc=g->vertices[j]->firstarc;g->vertices[j]->firstarc=q;}}3.建立有向图邻接表算法:voidcreat(algraph*g, inte){for(i=0;iscanf(“%c”,&g->vertices[i]->data);g->vertices[i]->firstarc=NULL;}for(k=0;kscanf(“%d,%d”,&i,&j);p=(Arcnode*)malloc(sizeof(Arcnode));p->adjvex=j; p->nextarc=g->vertices[i]->firstarc;g->vertices[i]->firstarc=p;}}三、图的遍历1.连通图的深度优先搜索遍历intvisited[vexnum]={0};voiddfs(mgraph*g, inti){printf(“%3c”,g->vexs[i]);visited[i]=1;for(j=0;jif((g->arcs[i][j]==1)&&(!visited[j]))dfs(g, j);}2.联通图的广度优先搜索遍历intvisited[vexnum]={0};voidbfs(mgraph*g, intk){intq[20], f, r;f=0;r=0;printf(“%3c”,g->vexs[k]);visited[k]=1;q[r]=k;r++;while(r!=f){i=q[f];f++;for(j=0;jif((g->arcs[i][j]==1)&&!visited[j]){printf(“%3c”,g->vexs[j]);visited[j]=1;q[r]=j;r++;}}}4.求图的联通分量intvisited[vexnum]={0};voidcomponent(mgraph*g){intcount=0;for(j=0;jif(!visited[j]){count++;printf(“n第%d个联通分量:”, count);dfs(g, j);} printf(“n 共有%d个联通分量。

邻接矩阵法

邻接矩阵法

邻接矩阵法邻接矩阵法是图论中一种常用的表示图结构的方法。

它通过一个二维矩阵来表示图中各个顶点之间的连接关系。

在邻接矩阵中,矩阵的行和列分别代表图中的顶点,而矩阵中的元素则表示对应顶点之间是否存在边。

邻接矩阵的定义假设有一个无向图G=(V,E),其中V为顶点集合,E为边集合。

邻接矩阵A是一个n×n的方阵,其中n为图中顶点的个数。

邻接矩阵A满足以下条件:•如果顶点i和顶点j之间存在边,则A[i][j]=1;•如果顶点i和顶点j之间不存在边,则A[i][j]=0。

对于有向图来说,邻接矩阵也可以用来表示其连接关系,只是在有向图中,边具有方向性。

邻接矩阵的应用邻接矩阵作为一种常见的图表示方法,在许多算法和应用中都得到了广泛的应用。

下面介绍一些常见的应用场景:1. 图遍历通过邻接矩阵,我们可以方便地遍历图中的顶点和边。

对于一个顶点i,我们只需要遍历邻接矩阵的第i行(或第i列),就可以获取到与该顶点直接相连的所有顶点。

2. 最短路径算法邻接矩阵常被用于求解最短路径问题,例如Dijkstra算法和Floyd-Warshall算法。

在这些算法中,通过邻接矩阵来表示各个顶点之间的距离或权重,然后根据具体的算法逻辑来计算最短路径。

3. 最小生成树邻接矩阵也可以用于求解最小生成树问题,例如Prim算法和Kruskal算法。

在这些算法中,邻接矩阵用来表示图中各个顶点之间的连接关系,并根据具体的算法逻辑选择合适的边来构建最小生成树。

4. 图的连通性判断通过邻接矩阵,我们可以判断一个图是否是连通图。

如果一个无向图的邻接矩阵是对称且连通的,则说明该图是一个连通图。

如果一个有向图的邻接矩阵是强连通的,则说明该有向图是强连通图。

邻接矩阵的优缺点邻接矩阵作为一种图的表示方法,具有以下优点:•表示简单:邻接矩阵直观地表示了图中各个顶点之间的连接关系,易于理解和实现。

•查询高效:通过邻接矩阵,可以快速判断两个顶点之间是否存在边,时间复杂度为O(1)。

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

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

图的两种存储⽅式---邻接矩阵和邻接表图:图是⼀种数据结构,由顶点的有穷⾮空集合和顶点之间边的集合组成,表⽰为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),保存顶点的数组,保存边的数组。

数据结构实验 图的邻接表和邻接矩阵操作

数据结构实验 图的邻接表和邻接矩阵操作
5
p->weight=weight; p->nextarc=G.vertices[vv].firstarc; G.vertices[vv].firstarc=p; strcmp(G.vertices[vv].data,v);
q=(ArcNode *)malloc(sizeof(ArcNode)); q->adjvex=vv; q->weight=weight; q->nextarc=G.vertices[ww].firstarc; G.vertices[ww].firstarc=q; strcmp(G.vertices[ww].data,w);
实验报告 6
课程 数据结构 实验名称 图的建立及遍历
第页
专业
班级_ __ 学号_ ___ 姓名
实验日期: 2010 年 11 月 23 日
评分
一 、实验目的
1.学会用邻接矩阵和邻接表实现图结构和对图的基本操作。 2.掌握对图操作的具体实现; 3. 掌握图的两种遍历算法(深度优先、广度优先); 4、掌握求图的最小生成树和顶点间最短路径的算法;
int adjvex;//该弧指向的顶点的位置 ArcType weight; struct ArcNode *nextarc;//指向下一条弧指针 //InfoType *info;该弧相关信息的指针 }ArcNode; typedef struct VNode { VertexType data;//顶点信息 ArcNode *firstarc;//指向第一条依附该顶点的弧的指针 }VNode,AdjList[MAX_VEX_NUM]; typedef struct { AdjList vertices; int vexnum,arcnum; GraphKind kind; }ALGraph; ALGraph G; struct MiniSpanTree_Flag { VertexType adjvex; ArcType lowcost; }closedge[MAX_VEX_NUM]; typedef bool PathMatrix[MAX_VEX_NUM][MAX_VEX_NUM];

数据结构试题及答案

数据结构试题及答案

一、判断题:1、线性表的逻辑顺序与物理顺序总是一致的。

( )2、线性表的顺序存储表示优于链式存储表示。

( )3、线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续。

( )4、二维数组是其数组元素为线性表的线性表。

( )5、每种数据结构都应具备三种基本运算:插入、删除和搜索。

( )6、数据结构概念包括数据之间的逻辑结构,数据在计算机中的存储方式和数据的运算三个方面。

( )7、线性表中的每个结点最多只有一个前驱和一个后继。

()8、线性的数据结构可以顺序存储,也可以链接存储。

非线性的数据结构只能链接存储。

()9、栈和队列逻辑上都是线性表。

()10、单链表从任何一个结点出发,都能访问到所有结点()11、删除二叉排序树中一个结点,再重新插入上去,一定能得到原来的二叉排序树。

()12、快速排序是排序算法中最快的一种。

()13、多维数组是向量的推广。

()14、一般树和二叉树的结点数目都可以为0。

()15、直接选择排序是一种不稳定的排序方法。

()16、98、对一个堆按层次遍历,不一定能得到一个有序序列。

()17、在只有度为0和度为k的结点的k叉树中,设度为0的结点有n0个,度为k的结点有nk个,则有n0=nk+1。

()18、折半搜索只适用与有序表,包括有序的顺序表和有序的链表。

()19、堆栈在数据中的存储原则是先进先出。

()20、队列在数据中的存储原则是后进先出。

()21、用相邻矩阵表示图所用的存储空间大小与图的边数成正比。

()22、哈夫曼树一定是满二叉树。

()23、程序是用计算机语言表述的算法。

()24、线性表的顺序存储结构是通过数据元素的存储地址直接反映数据元素的逻辑关系。

()25、用一组地址连续的存储单元存放的元素一定构成线性表。

()26、堆栈、队列和数组的逻辑结构都是线性表结构。

()27、给定一组权值,可以唯一构造出一棵哈夫曼树。

()28、只有在初始数据为逆序时,冒泡排序所执行的比较次数最多。

图的存储实验报告

图的存储实验报告

图的存储实验报告图的存储实验报告引言在计算机科学领域中,图是一种重要的数据结构,用于描述对象之间的关系。

图的存储方式对于图的遍历、搜索和其他操作有着重要的影响。

本实验旨在探究不同的图存储方式,并比较它们在不同操作下的性能差异。

一、邻接矩阵存储方式邻接矩阵是一种常见的图存储方式,它使用二维数组来表示图中各个顶点之间的关系。

在邻接矩阵中,行和列分别代表图中的顶点,矩阵中的元素表示两个顶点之间的边的关系。

实验中,我们通过一个简单的例子来说明邻接矩阵的存储方式。

假设有一个无向图,其中包含5个顶点和6条边。

我们可以使用一个5x5的矩阵来表示这个图,矩阵中的元素为1表示两个顶点之间存在边,为0表示不存在边。

邻接矩阵的优点是可以快速判断两个顶点之间是否存在边,时间复杂度为O(1)。

然而,邻接矩阵的缺点是当图中的边数较少时,会造成存储空间的浪费。

此外,在图中顶点的增加和删除操作时,需要重新调整矩阵的大小,开销较大。

二、邻接表存储方式邻接表是另一种常见的图存储方式,它使用链表来表示图中各个顶点之间的关系。

在邻接表中,每个顶点都有一个链表,链表中存储了与该顶点相邻的顶点。

实验中,我们同样以一个简单的例子来说明邻接表的存储方式。

假设有一个有向图,其中包含4个顶点和5条边。

我们可以使用一个包含4个链表的数组来表示这个图,数组中的每个元素表示一个顶点,链表中的元素表示与该顶点相邻的顶点。

邻接表的优点是在图中边的数量较少时,可以节省存储空间。

此外,在图中顶点的增加和删除操作时,开销较小。

然而,邻接表的缺点是判断两个顶点之间是否存在边的时间复杂度较高,需要遍历链表,时间复杂度为O(顶点的度数)。

三、性能比较与结论通过实验,我们对比了邻接矩阵和邻接表两种图存储方式在不同操作下的性能差异。

在判断两个顶点之间是否存在边的操作中,邻接矩阵的时间复杂度为O(1),而邻接表的时间复杂度为O(顶点的度数)。

因此,在此操作下,邻接矩阵的性能更优。

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

图采用邻接矩阵存储结构#define TRUE 1#define FALSE 0#define MAXV 20typedef int V ertexType; //用顶点编号表示顶点typedef struct { // 图的定义int edges[MAXV][MAXV] ; // 边数组int n, e; //顶点数,弧数V ertexType vexs[MAXV]; // 顶点信息} MGraph;1、创建具有n个顶点e条边的无向图void CreateUDG(MGraph &G,int n,int e){int i,j,u,v;G.n=n;G.e=e;/*printf("请输入%d个顶点的编号:\n",n);for(i=0;i<n;i++)scanf("%d",&G.vexs[i]);*///初始化顶点信息,假设顶点的编号和顶点在数组内的下标相同for(i=0;i<n;i++)G.vexs[i]=i;//初始化邻接矩阵for(i=0;i<n;i++)for(j=0;j<n;j++)G.edges[i][j]=0;for(j=0;j<e;j++){printf("请输入一条边的两个顶点编号:");scanf("%d%d",&u,&v);G.edges[u][v]=G.edges[v][u]=1;}}2、创建具有n个顶点e条弧的有向图void CreateDG(MGraph &G,int n,int e){int i,j,u,v;G.n=n;G.e=e;/*printf("请输入%d个顶点的编号:\n",n);for(i=0;i<n;i++)scanf("%d",&G.vexs[i]);*///初始化顶点信息,假设顶点的编号和顶点在数组内的下标相同for(i=0;i<n;i++)G.vexs[i]=i;//初始化邻接矩阵for(i=0;i<n;i++)for(j=0;j<n;j++)G.edges[i][j]=0;for(j=0;j<e;j++){printf("请输入一条弧的两个顶点编号(注意先输入的为弧尾):"); scanf("%d%d",&u,&v);G.edges[u][v]=1;}}3、求图G中顶点v的第一个邻接点int FirstAdjV ex(MGraph G, int v){for(int i=0;i<G.n;i++)if(G.edges[v][i]==1)return i;return -1;}4、求图G中顶点v相对于w的下一个邻接点int NextAdjV ex(MGraph G, int v,int w){for(int i=w;i<G.n;i++)if(G.edges[v][i]==1)return i;return -1;}5、深度优先搜索算法Boolean visited[MAXV];void DFSTravse (MGraph G){// 对图 G 作深度优先遍历。

for (v=0; v<G.vexnum; ++v)visited[v] = FALSE; // 访问标志数组初始化for (v=0; v<G.vexnum; ++v)if (!visited[v]) DFS(G, v);// 对尚未访问的顶点调用DFS}void DFS(MGraph G, int v) {// 从顶点v出发,深度优先搜索遍历连通图 Gvisited[v] = TRUE; printf(v);for(int w=FirstAdjV ex(G, v);w>=0; w=NextAdjV ex(G,v,w))if (!visited[w]) DFS(G, w);// 对v的尚未访问的邻接顶点w// 递归调用DFS} // DFS6、广度优先搜索算法void BFSTraverse(MGraph G){for (v=0; v<G.vexnum; ++v)visited[v] = FALSE; //初始化访问标志InitQueue(Q); // 置空的辅助队列Qfor ( v=0; v<G.vexnum; ++v )if ( !visited[v]){ // v 尚未访问visited[v] = TRUE; printf(v); // 访问vEnQueue(Q, v); // v入队列while (!QueueEmpty(Q)){DeQueue(Q, u); // 队头元素出队并置为ufor(w=FirstAdjV ex(G, u); w>=0; w=NextAdjV ex(G,u,w)) if ( ! visited[w]){visited[w]=TRUE; printf(w);EnQueue(Q, w); // 访问的顶点w入队列} // if} // while} //if} // BFS图采用邻接表存储结构typedef struct ANode /*弧(边)的结点结构类型*/{ int adjvex; /*该弧(边)的终点位置*/struct ANode *nextarc; /*指向下一条弧(边)的指针*/} ArcNode;typedef struct Vnode /*邻接表头结点的类型*/{ V ertexType data; /*顶点信息*/ArcNode *firstarc; /*指向第一条弧(边)*/} VNode;typedef VNode AdjList[MAXV]; /*AdjList是邻接表类型*/typedef struct{ AdjList adjlist; /*邻接表*/int n,e; /*图中顶点数n和边数e*/} ALGraph; /*图的类型*/1、创建具有n个顶点e条边的无向图void CreateUDG(ALGraph &G,int n,int e){int i,j,u,v;ArcNode *p1,*p2,*q;G.n=n;G.e=e;//初始化顶点信息(头结点),假设顶点的编号和顶点在数组内的下标相同for(i=0;i<n;i++){ G.adjlist[i].data=i; G.adjlist[i].firstarc=NULL; }//生成每个顶点的邻接点的单链表for(j=0;j<e;j++)printf("请输入一条边的两个顶点编号:");scanf("%d%d",&u,&v);p1=(ArcNode *)malloc(sizeof(ArcNode));p1->adjvex=v;p1->nextarc=NULL;if(G.adjlist[u].firstarc==NULL) G.adjlist[u].firstarc=p1;else{ q=G.adjlist[u].firstarc;while(q->nextarc!=NULL) q=q->nextarc;q->nextarc=p1;}p2=(ArcNode *)malloc(sizeof(ArcNode));p2->adjvex=u;p2->nextarc=NULL;if(G.adjlist[v].firstarc==NULL) G.adjlist[v].firstarc=p2;else{ q=G.adjlist[v].firstarc;while(q->nextarc!=NULL) q=q->nextarc;q->nextarc=p2;}}//for}2、创建具有n个顶点e条弧的有向图void CreateUDG(ALGraph &G,int n,int e){int i,j,u,v;ArcNode *p,*q;G.n=n;G.e=e;//初始化顶点信息(头结点),假设顶点的编号和顶点在数组内的下标相同for(i=0;i<n;i++){ G.adjlist[i].data=i; G.adjlist[i].firstarc=NULL; }//生成每个顶点的邻接点的单链表for(j=0;j<e;j++){printf("请输入一条弧的两个顶点编号(先输入的为弧尾):");scanf("%d%d",&u,&v);p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=v;p->nextarc=NULL;if(G.adjlist[u].firstarc==NULL) G.adjlist[u].firstarc=p; else{ q=G.adjlist[u].firstarc;while(q->nextarc!=NULL) q=q->nextarc;q->nextarc=p;}}//for}3、求图G中顶点v的第一个邻接点int FirstAdjV ex(ALGraph G, int v){ ArcNode *p=G.adjlist[v].firstarc;if(p!=NULL) return p->adjvex;else return -1;}4、求图G中顶点v相对于w的下一个邻接点int NextAdjV ex(ALGraph G, int v,int w){ ArcNode *p=G.adjlist[v].firstarc;while(p!=NULL&&p->adjvex!=w)p=p->nextarc;if(p) return p->adjvex;else return -1;}。

相关文档
最新文档