邻接表结构函数(GRAPH1.H)。。
计算机学科专业基础综合数据结构-图(二)_真题-无答案
计算机学科专业基础综合数据结构-图(二)(总分100,考试时间90分钟)一、单项选择题(下列每题给出的4个选项中,只有一个最符合试题要求)1. 具有6个顶点的无向图至少应有______条边才能确保是一个连通图。
A.5 B.6 C.7 D.82. 设G是一个非连通无向图,有15条边,则该图至少有______个顶点。
A.5 B.6 C.7 D.83. 下列关于无向连通图特性的叙述中,正确的是______。
①所有顶点的度之和为偶数②边数大于顶点个数减1③至少有一个顶点的度为1A.只有① B.只有② C.①和② D.①和③4. 对于具有n(n>1)个顶点的强连通图,其有向边的条数至少是______。
A.n+1B.nC.n-1D.n-25. 下列有关图的说法中正确的是______。
A.在图结构中,顶点不可以没有任何前驱和后继 B.具有n个顶点的无向图最多有n(n-1)条边,最少有n-1条边 C.在无向图中,边的条数是结点度数之和 D.在有向图中,各顶点的入度之和等于各顶点的出度之和6. 对于一个具有n个顶点和e条边的无向图,若采用邻接矩阵表示,则该矩阵大小是______,矩阵中非零元素的个数是2e。
A.n B.(n-1)2 C.n-1 D.n27. 无向图的邻接矩阵是一个______。
A.对称矩阵 B.零矩阵 C.上三角矩阵 D.对角矩阵8. 从邻接矩阵可知,该图共有______个顶点。
如果是有向图,该图共有4条有向边;如果是无向图,则共有2条边。
A.9 B.3 C.6 D.1 E.5 F.4 G.2 H.09. 下列说法中正确的是______。
A.一个图的邻接矩阵表示是唯一的,邻接表表示也唯一 B.一个图的邻接矩阵表示是唯一的,邻接表表示不唯一 C.一个图的邻接矩阵表示不唯一,邻接表表示唯一 D.一个图的邻接矩阵表示不唯一,邻接表表示也不唯一10. 用邻接表存储图所用的空间大小______。
A.与图的顶点数和边数都有关 B.只与图的边数有关 C.只与图的顶点数有关 D.与边数的二次方有关11. 采用邻接表存储的图的深度优先搜索算法类似于二叉树的______,广度优先搜索算法类似于二叉树的层次序遍历。
数据结构-邻接表
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. 集合论(Set theory):集合论是离散数学的基础,涉及了集合的概念、运算和恒等关系,以及集合的分类、子集、幂集和笛卡尔积等基本概念和性质。
2. 逻辑(Logic):逻辑是离散数学的重要组成部分,涉及了命题逻辑和谓词逻辑的基本概念和推理规则,包括命题的真值表、谓词的量化、逻辑等价和逻辑蕴含等概念。
3. 函数(Functions):函数是离散数学中的核心概念之一,涉及了函数的定义、域和值域、函数的性质、特殊的函数(如恒等函数、常值函数、单射函数和满射函数等)以及函数的复合和逆函数等。
4. 关系(Relations):关系是离散数学中的另一个核心概念,涉及了关系的定义、关系的特性(如自反性、对称性、传递性和等价关系等)、关系的闭包和自反闭包、关系的图示表示和矩阵表示、等价关系和偏序关系等。
5. 图论(Graph theory):图论是离散数学的重要分支,涉及了图的基本概念(如顶点、边、路径和圈等)、图的表示方法(如邻接矩阵和邻接表等)、图的遍历算法(如深度优先和广度优先等)、图的连通性和可达性、最小生成树和最短路径等基础知识。
7. 代数结构(Algebraic structures):代数结构是离散数学的一个重要方向,涉及了群、环、域和格等基本代数结构的定义、性质和分类,以及同态映射和同构等概念。
8. 数论(Number theory):数论是离散数学的一个重要分支,涉及了自然数的性质和结构,包括质数和素数、最大公因数和最小公倍数、同余和模运算、欧几里得算法和扩展欧几里得算法、费马小定理和欧拉函数等。
9. 排序和选择(Sorting and selection):排序和选择是离散数学中的一类重要问题,涉及了各种排序算法(如冒泡排序、插入排序、快速排序和归并排序等)和选择算法(如选择排序和堆排序等),以及它们的复杂度分析和应用。
matlab 中的graph函数
matlab 中的graph函数【最新版】目录一、Matlab 中的 graph 函数介绍1.graph 函数的作用2.graph 函数的基本语法3.graph 函数的参数二、利用 graph 函数实现边列表生成邻接矩阵1.边列表表示法2.邻接矩阵表示法3.利用 graph 函数实现边列表生成邻接矩阵的方法a.方法一:利用 matlab 函数b.方法二:自定义函数三、总结1.Matlab 中的 graph 函数的功能和应用2.边列表生成邻接矩阵的实现方法正文一、Matlab 中的 graph 函数介绍Matlab 中的 graph 函数是一个非常实用的函数,它可以用于创建、操作和显示图形。
graph 函数的作用是将输入的边列表转换成邻接矩阵,从而可以方便地表示图形的结构。
graph 函数的基本语法如下:```matlabG = graph(N, edge_list)```其中,N 表示节点数,edge_list 表示边列表。
边列表是由每条边的两个顶点组成的向量,例如:[1 2; 1 3; 1 4]。
graph 函数的参数有:- N:节点数,必须是一个正整数- edge_list:边列表,必须是一个 N×2 的矩阵,表示每条边的两个顶点二、利用 graph 函数实现边列表生成邻接矩阵1.边列表表示法:边列表表示法是一种用于表示图形结构的方法,它由一组边的顶点组成。
例如,对于一个有 4 个节点的图形,边列表可以表示为:[1 2; 1 3; 1 4]。
2.邻接矩阵表示法:邻接矩阵表示法是一种用于表示图形结构的方法,它由一个 N×N 的矩阵组成,矩阵的每个元素表示两个节点之间是否存在一条边。
例如,对于一个有 4 个节点的图形,邻接矩阵可以表示为:```0 1 1 11 0 1 01 1 0 11 0 1 0```3.利用 graph 函数实现边列表生成邻接矩阵的方法:a.方法一:利用 matlab 函数可以使用 graph 函数直接将边列表转换为邻接矩阵,如下所示:```matlab= 4;edge_list = [1 2; 1 3; 1 4];G = graph(N, edge_list);A = G.A;```在这个例子中,我们首先创建了一个有 4 个节点的图形,然后利用graph 函数的 A 属性得到了邻接矩阵。
实验六 图及其应用
实验六图及其应用数据结构实验六图及其应用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 已经存在;操作结果:返回图从某个结点开始的按广度遍历的结果。
分析: 修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。
有向图的邻接表表示法
有向图的邻接表表⽰法图的邻接表表⽰法类似于树的孩⼦链表表⽰法。
对于图G中的每个顶点vi,该⽅法把所有邻接于vi的顶点vj链成⼀个带头结点的单链表,这个单链表就称为顶点vi的邻接表(Adjacency List)。
1.邻接表的结点结构(1)表结点结构┌────┬───┐│adjvex │next │└────┴───┘ 邻接表中每个表结点均有两个域: ①邻接点域adjvex 存放与vi相邻接的顶点vj的序号j。
②链域next 将邻接表的所有表结点链在⼀起。
注意: 若要表⽰边上的信息(如权值),则在表结点中还应增加⼀个数据域。
(2)头结点结构┌────┬─────┐│vertex │firstedge │└────┴─────┘ 顶点vi邻接表的头结点包含两个域: ①顶点域vertex 存放顶点vi的信息 ②指针域firstedge vi的邻接表的头指针。
注意: ①为了便于随机访问任⼀顶点的邻接表,将所有头结点顺序存储在⼀个向量中就构成了图的邻接表表⽰。
②有时希望增加对图的顶点数及边数等属性的描述,可将邻接表和这些属性放在⼀起来描述图的存储结构。
代码实例2.{输出结果为:int VexNum,ArcNum;//定义图的顶点数和边数VertexNode vertex[MAX_VERTEX_NUM];//定义头结点数组。
}AdjList;void CreateGraph(AdjList *adj,int *n){int e,s,d;cout<<"输⼊顶点数和边数"<<endl;cin>>*n>>e;//输⼊顶点数和边数。
adj->VexNum=*n;adj->ArcNum=e;EdgeNode *q=NULL;//初始化表头结点int i;for(i=1;i<=*n;i++){输⼊第2条边的起点和终点2 4输⼊第3条边的起点和终点2 1输⼊第4条边的起点和终点4 3输⼊第5条边的起点和终点3 6输⼊第6条边的起点和终点3 53.代码实例2(ps:补充于2011-6-14) 总体⽽⾔,邻接表表⽰法中主要含有两种结点,分别是头结点和表结点(也叫做边结点),在头结点(s)到表结点(d)之间存在着⼀条边。
《数据结构》第 7 章 图
v3
v4 v5 v4
v3
v5 v4
v3
v5 v4
v3
v5 v4
v3
v5
注
一个图可以有许多棵不同的生成树。 所有生成树具有以下共同特点: 生成树的顶点个数与图的顶点个数相同; 生成树是图的极小连通子图; 一个有 n 个顶点的连通图的生成树有 n-1 条边; 生成树中任意两个顶点间的路径是唯一的; 在生成树中再加一条边必然形成回路。 含 n 个顶点 n-1 条边的图不一定是生成树。
A1 = {< v1, v2>, < v1, v3>, < v3, v4>, < v4, v1>} v1 v2
有向图
v3
v4
制作:计算机科学与技术学院 徐振中
数据结构 边:若 <v, w>∈VR 必有<w, v>∈VR,则以 无序对 (v, w) 代表这两个有序对,表示 v 和 w 之 间的一条边,此时的图称为无向图。 G2 = (V2, E2) V2 = {v1, v2, v3, v4, v5}
第七章 图
E2 = {(v1, v2), (v1, v4), (v2, v3), (v2, v5) , (v3, v4), (v3, v5)} v1
G2
v3
v2
无向图
v4
v5
制作:计算机科学与技术学院 徐振中
数据结构
第七章 图
例:两个城市 A 和 B ,如果 A 和 B 之间的连线的涵义是 表示两个城市的距离,则<A, B> 和 <B, A> 是相同的, 用 (A, B) 表示。 如果 A 和 B 之间的连线的涵义是表示两城市之 间人口流动的情况,则 <A, B> 和 <B, A> 是不同的。 北京 <北京,上海> (北京,上海) <上海,北京> <北京,上海> 北京 上海 上海
邻接表的深度遍历
邻接表的深度遍历邻接表是一种表示图的数据结构,深度遍历是一种图遍历的算法。
下面是邻接表的深度遍历的一般步骤:1.初始化:建立一个布尔类型的数组,用于标记节点是否已经被访问。
2.选择起始节点:从图中选择一个未被访问的节点作为起始节点。
3.深度优先遍历:对于选定的起始节点,进行深度优先遍历。
具体步骤如下:•将当前节点标记为已访问。
•访问当前节点,并执行相应的操作。
•对于当前节点的所有未访问邻接节点,递归调用深度遍历函数。
4.迭代:重复步骤3,直到所有节点都被访问。
下面是一个深度遍历的伪代码示例,假设图用邻接表表示:# 定义图的邻接表表示graph = {'A': ['B', 'C'],'B': ['A', 'D', 'E'],'C': ['A', 'F', 'G'],'D': ['B'],'E': ['B', 'H'],'F': ['C'],'G': ['C'],'H': ['E']}# 定义深度遍历函数def dfs(node, visited):if node not in visited:print(node)visited.add(node)for neighbor in graph[node]:dfs(neighbor, visited)# 初始化已访问节点的集合visited_set = set()# 选择起始节点start_node = 'A'# 调用深度遍历函数dfs(start_node, visited_set)这个示例中,图用字典表示,每个节点对应一个键,对应的值是一个列表,包含与该节点邻接的节点。
邻接表和逆邻接表
邻接表和逆邻接表邻接表和逆邻接表是图论中常用的两种数据结构,它们分别用于存储有向图和无向图的邻居关系,是算法设计和优化中最常用的数据结构之一。
下面,我们将分别介绍邻接表和逆邻接表的定义、构建和应用。
一、邻接表邻接表是一种用于表示有向图和无向图的数据结构,实际上就是将图中的每个结点与其相邻结点关联起来,并存储在一个链表中。
因此,邻接表的基本结构是一个链表数组,其中每个链表代表一个结点和其邻居结点的关系。
邻接表一般可以通过以下步骤进行构建:1. 定义一个链表数组,数组的长度等于图中结点的个数;2. 遍历图中每个结点,将每个结点与其直接相连的结点添加到该结点对应的链表中;3. 添加完毕后,邻接表即构建完成。
邻接表的应用非常广泛,例如:1. 求解最短路径:通过遍历邻接表中的每个结点,可以找到从起点到终点的最短路径;2. 求解连通分量:通过遍历邻接表,可以找到有多少个连通分量,并输出每个连通分量的结点集合;3. 拓扑排序:通过邻接表和入度数组即可实现拓扑排序算法等等。
二、逆邻接表逆邻接表是指有向图中每个结点的入度集合,即表示指向某个节点的所有其他节点的集合。
逆邻接表的构建比较简单,只需要将邻接表反向,即将有向图的每个结点的所有入边指向相应的出边即可。
逆邻接表同样有着广泛的应用,例如:1. 求解强连通分量:通过遍历逆邻接表,可以求解图中的所有强连通分量;2. 拓扑排序:通过逆邻接表和入度数组,即可实现基于反向边的拓扑排序算法;3. 最短路径算法优化:当搜索从终点到起点时,通过使用逆邻接表,可以加速搜索过程。
总的来说,邻接表和逆邻接表是在图论中应用非常广泛的两种数据结构。
我们可以运用它们构建和优化各种算法,从而提高程序效率。
因此,熟练掌握邻接表和逆邻接表的概念、构建方法和应用场景是每一个程序员必备的技能。
邻接表转换成邻接矩阵
邻接表转换成邻接矩阵邻接表和邻接矩阵是图数据结构中常见的两种表示方式。
邻接表是一种链式存储结构,适用于稀疏图,而邻接矩阵则是一种二维数组的存储结构,适用于稠密图。
本文将介绍如何将邻接表转换成邻接矩阵,并对其优缺点进行比较。
1. 邻接表在图的邻接表表示中,每个顶点都对应一个链表,该链表存储了与该顶点相连的所有边的信息。
具体来说,可以使用一个数组来存储这些链表。
数组的大小为顶点的个数。
下面是一个示例图的邻接表表示:Vertex: 0 1 2 3Adjacency: 1 → 2 0 → 3 2 → 3 -对应的代码实现如下:class Node:def __init__(self, value):self.value = valueself.next = Noneclass Graph:def __init__(self, vertices):self.vertices = verticesself.adj_list = [None] * verticesdef add_edge(self, src, dest):node = Node(dest)node.next = self.adj_list[src]self.adj_list[src] = nodedef print_adj_list(graph):for i in range(graph.vertices):print(f"Vertex {i}:", end=" ")node = graph.adj_list[i]while node:print(node.value, end=" → ")node = node.nextprint("-")2. 邻接矩阵邻接矩阵是一种使用二维数组来表示图的方法。
对于包含n个顶点的图,邻接矩阵是一个n×n的矩阵,其中每个元素a[i][j]表示顶点i和顶点j之间是否存在边。
名词解释—邻接表:
名词解释—邻接表
邻接表(Adjacency List)是一种常用的图数据结构,用于表示图中的顶点以及它们之间的连接关系。
在计算机科学中,图是由顶点和边组成的数据结构,可以用来表示各种复杂的网络关系,如社交网络、交通网络、电路等。
邻接表是表示图的一种有效方法,尤其适用于稀疏图(即边的数量相对较少的图)。
邻接表的核心思想是将每个顶点与其相邻的顶点列表相关联。
具体实现时,通常使用一个数组或链表来存储每个顶点的相邻顶点。
对于无向图,每个顶点都需要存储其相邻顶点的信息;对于有向图,只需要存储出度(从该顶点出发的边)或入度(指向该顶点的边)的相邻顶点信息。
邻接表的优点包括:
节省空间:邻接表仅存储实际存在的边,对于稀疏图来说非常节省空间。
便于添加和删除顶点:只需要修改相应的顶点列表即可。
便于查询邻接顶点:可以通过直接访问顶点的相邻顶点列表来查询邻接顶点。
名词解释—邻接表:
名词解释—邻接表:
摘要:
1.邻接表的定义和作用
2.邻接表的类型和特点
3.邻接表的应用实例
4.邻接表的优缺点分析
正文:
邻接表是一种用于表示有向图或无向图中顶点之间关系的数据结构,通常用于存储顶点之间的关系信息。
在图论中,邻接表是一种重要的概念,它可以帮助我们更好地理解和分析图的结构。
邻接表的类型主要有两种:一种是邻接数组,另一种是邻接链表。
邻接数组是在数组中存储每个顶点的邻居信息,而邻接链表则是用链表来存储每个顶点的邻居信息。
这两种类型各有其特点,邻接数组适合表示稀疏图,而邻接链表适合表示稠密图。
邻接表在实际应用中有很多实例,比如在社交网络分析中,我们可以用邻接表来表示用户之间的关系;在搜索引擎中,邻接表可以用来表示网页之间的链接关系。
这些应用都充分体现了邻接表在数据表示和分析方面的优势。
邻接表的优点在于它可以灵活地表示图的结构,同时存储和查找邻居信息也非常方便。
但是,邻接表也存在一些缺点,比如它在存储稠密图时可能会浪费空间,此外,它的遍历效率相对较低。
图的两种存储方式---邻接矩阵和邻接表
图的两种存储⽅式---邻接矩阵和邻接表图:图是⼀种数据结构,由顶点的有穷⾮空集合和顶点之间边的集合组成,表⽰为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),保存顶点的数组,保存边的数组。
最短路径算法Dijkstra
最短路径算法Dijkstra一、图的邻接表存储结构及实现(回顾)1.头文件graph.h// Graph.h: interface for the Graph class.#if !defined(AFX_GRAPH_H__C891E2F0_794B_4ADD_8772_55BA3 67C823E__INCLUDED_)#defineAFX_GRAPH_H__C891E2F0_794B_4ADD_8772_55BA367C823E__I NCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <cassert>#include <vector>using namespace std;#define NULL 0typedef int weightType;typedef char Type; //数据元素类型class EdgeNode { // A singly-linked list node public:weightType weight; // Edge weightint v1; // Vertex edge comes fromint v2; // Vertex edge goes to EdgeNode* next; // Pointer to next edge in list EdgeNode(int vt1, int vt2, weightType w, EdgeNode* nxt =NULL) { v1 = vt1; v2 = vt2; weight = w; next = nxt; } // Constructor EdgeNode(EdgeNode* nxt =NULL) { next = nxt; } // Constructor };typedef EdgeNode* Edge;struct VertexNode{Type data;Edge first;VertexNode(Type d,Edge e):data(d),first(e){}};typedef VertexNode Vertex;class Graph { // Graph class: Adjacency list private:vector<Vertex> list; //The vertex listint numEdge; // Number of edgesvector<bool> Mark; // The mark arraypublic:Graph(); // Constructor~Graph(); // Destructorint n(); // Number of vertices for graph int e(); // Number of edges for graph Edge first(int); // Get the first edge for a vertex bool isEdge(Edge); // TRUE if this is an edge Edge next(Edge); // Get next edge for a vertexint v1(Edge); // Return vertex edge comes fromint v2(Edge); // Return vertex edge goes to weightType weight(int, int); // Return weight of edge weightType weight(Edge); // Return weight of edgebool getMark(int); // Return a Mark valuevoid setMark(int, bool); // Set a Mark valuevoid setVertex(int i,Type vertexData){assert(i>=0&&i<list.size()) ; list[i].data =vertexData; }Type getVertex(int i){assert(i>=0&&i<list.size()) ; return list[i].data; }void InsertVertex ( const Type & vertexData );void InsertEdge ( const int v1, const int v2, weightType weight );void RemoveVertex ( const int v );void RemoveEdge ( const int v1, const int v2 );};void Dijkstra_shortest_Path(Graph& G, int s,weightType D[],int P[]);#endif// !defined(AFX_GRAPH_H__C891E2F0_794B_4ADD_8772_55BA367 C823E__INCLUDED_)2.cpp文件graph.cpp// Graph.cpp: implementation of the Graph class.#include "Graph.h"#define INFINITY 1000000Graph::Graph() { // ConstructornumEdge = 0;}Graph::~Graph() { // Destructor: return allocated space // Remove all of the edgesfor (int v=0; v<list.size(); v++) { // For each vertex...Edge p = list[v].first;while (p != NULL) { // return its edgesEdge temp = p;p = p->next;delete temp;}}}int Graph::n() { return list.size(); } // Number of verticesint Graph::e() { return numEdge; } // Number of edgesEdge Graph::first(int v) // Get the first edge for a vertex{ return list[v].first; }bool Graph::isEdge(Edge w) // TRUE if this is an edge{ return w != NULL; }Edge Graph::next(Edge w) { // Get next edge for a vertex if (w == NULL) return NULL;else return w->next;}int Graph::v1(Edge w) { return w->v1; } // Vertex edge comes from int Graph::v2(Edge w) { return w->v2; } // Vertex edge goes toweightType Graph::weight(int i, int j) { // Return weight of edge for (Edge curr = list[i].first; curr != NULL; curr = curr->next) if (curr->v2 == j) return curr->weight;return INFINITY;}weightType Graph::weight(Edge w) // Return weight of edge{ if (w == NULL) return INFINITY; else return w->weight; }bool Graph::getMark(int v) { return Mark[v]; }void Graph::setMark(int v, bool val) { Mark[v] = val; }//----------插入或删除数据-----------------------------void Graph::InsertVertex ( const Type & vertexData ){list.push_back( VertexNode(vertexData,NULL) );Mark.push_back(false);}void Graph::InsertEdge ( const int v1, const int v2, weightType weight ){ Edge edge= new EdgeNode(v1,v2,weight);edge->next = list[v1].first;list[v1].first = edge;numEdge++;}void Graph::RemoveVertex ( const int v ){}void Graph::RemoveEdge ( const int v1, const int v2 ){}3.测试程序main.cpp#include <iostream>#include <stack>#include "Graph.h"void main(){Graph G;Type vdata;cout<<"请依次输入顶点数据,用'ctrl+Z' 'ctrl+Z'结束输入\n";while(cin>>vdata){G.InsertVertex(vdata);}cin.clear(); //置为正常状态int v1 ,v2;weightType weight;cout<<"请输入边信息(格式为v1 v2 weight):";cin>>v1>>v2>>weight;while(v1>=0&&v2>=0){G.InsertEdge(v1,v2,weight);cout<<"请输入边信息(格式为v1 v2 weight):";cin>>v1>>v2>>weight;}int i;cout<<"图中顶点数据为:";for( i = 0 ;i <G.n(); i++)cout<<G.getVertex(i)<<" ";cout<<endl;cout<<"图中边数据为:";for( i = 0 ;i <G.n(); i++){Edge edge = G.first(i);while(edge){cout<<"("<<edge->v1<<" "<<edge->v2<<" "<<edge->weight<<") ";edge = G.next(edge);}}cout<<endl;}二、Dijkstra算法1.Dijkstra算法(Dijkstra_shortest_Path.cpp):#include "Graph.h"#define INFINITY 1000000const bool VISITED = true;const bool UNVISITED = false;// minVertex:在距离数组D中找最小的未加入S中的最短距离int minVertex(Graph& G, int* D);void Dijkstra_shortest_Path(Graph& G, int s,weightType D[],int P[]) { // Compute shortest path distances//初始时,所有顶点都未加入到已经最短路径的顶点集合Sint i;for(i = 0 ;i< G.n(); i++) G.setMark(s, UNVISITED);//将s作为起点,初始化距离数组和路径数组for ( i=0; i<G.n(); i++){ // InitializeD[i] = INFINITY; P[i] = s;}D[s] = 0; G.setMark(s, VISITED); //add s to Sfor (Edge e = G.first(s); G.isEdge(e); e = G.next(e))D[G.v2(e)] = G.weight(e);//在未加入S中的顶点中选择最短路径的那个顶点,//加入S,并更新距离和路径数组for (i=0; i<G.n()-1; i++) { // 最多进行n-1次//在不在S中的顶点中查找D(v)最小的顶点vint v = minVertex(G, D);if (D[v] == INFINITY) return; // 没有可以到达的顶点了G.setMark(v, VISITED);//更新v的所有邻接点v2的D(v2)和P(v2)for (Edge e = G.first(v); G.isEdge(e); e = G.next(e))if (D[G.v2(e)] > (D[v] + G.weight(e))){D[G.v2(e)] = D[v] + G.weight(e);P[G.v2(e)] = v; //}}for(i = 0 ;i< G.n(); i++) G.setMark(s, UNVISITED);}int minVertex(Graph& G, int* D) { // Find min cost vertex int v; // Initialize v to any unvisited vertex;for (int i=0; i<G.n(); i++)if (G.getMark(i) == UNVISITED) { v = i; break; } for (i++; i<G.n(); i++) // Now find smallest D valueif ((G.getMark(i) == UNVISITED) && (D[i] < D[v]))v = i;return v;}2.修改后的测试程序:#include <iostream>#include <stack>#include "Graph.h"void main(){Graph G;Type vdata;cout<<"请依次输入顶点数据,用'ctrl+Z' 'ctrl+Z'结束输入\n";while(cin>>vdata){G.InsertVertex(vdata);}cin.clear(); //置为正常状态int v1 ,v2;weightType weight;cout<<"请输入边信息(格式为v1 v2 weight):";cin>>v1>>v2>>weight;while(v1>=0&&v2>=0){G.InsertEdge(v1,v2,weight);cout<<"请输入边信息(格式为v1 v2 weight):";cin>>v1>>v2>>weight;}int i;cout<<"图中顶点数据为:";for( i = 0 ;i <G.n(); i++)cout<<G.getVertex(i)<<" ";cout<<endl;cout<<"图中边数据为:";for( i = 0 ;i <G.n(); i++){Edge edge = G.first(i);while(edge){cout<<"("<<edge->v1<<" "<<edge->v2<<" "<<edge->weight<<") ";edge = G.next(edge);}}cout<<endl;//Dijkstra_shortest_Path算法weightType *D = new weightType[G.n()];int *P = new int[G.n()];int s;cout<<"请输入起点的下标:"; cin>>s;Type sdata = G.getVertex(s);Dijkstra_shortest_Path(G, s, D, P);cout<<"输出所有最短路径,格式(终点,最短路径长度,最短路径)\n"; stack<int> pathStack;Type vertexdata;for( i = 0; i<G.n(); i++){if(i==s) continue;vertexdata = G.getVertex(i);if(D[i]>=100000){cout<<"起点"<<sdata<<"到顶点"<<vertexdata<<"没有路径\n";continue;}for(int j = P[i];j!=s;j = P[j])pathStack.push(j);cout<<vertexdata<<" "<<D[i]<<" "<<sdata;while(!pathStack.empty()){int j = pathStack.top(); pathStack.pop();cout<<G.getVertex(j);}cout<<G.getVertex(i)<<"\n";}delete[] D; delete[] P;}。
名词解释邻接表
邻接表邻接表(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 邻接表的遍历遍历邻接表可以获取图中所有顶点及其相邻顶点的信息。
数据结构实验任务书(8个)
目录实验1 线性表顺序存储的应用 (2)实验2 线性表链式存储的应用 (5)实验3 栈及其应用 (6)实验4 队列及其应用 (7)实验5 树及其应用 (8)实验6 图的遍历和连通性应用 (9)实验7 图的最短路径应用 (11)实验8 查找和排序应用 (12)实验1 线性表顺序存储的应用实验目的1.熟悉C语言的上机环境,掌握C语言的基本结构。
2.会定义线性表的顺序存储结构。
3.熟悉对顺序表的一些基本操作和具体的函数定义。
4.掌握在线性表的顺序存储结构上的一些其它操作。
实验要求1.独立完成;2.程序调试正确,有执行结果。
实验内容1、基础题:编写应用程序(填空),实现可以在顺序表中插入任意给定数据类型(定义为抽象数据类型)数据的功能。
要求在主函数中定义顺序表并对该顺序表插入若干个整数类型的数据(正整数),对它们求和并输出。
请使用动态内存分配的方式申请数组空间,并把主函数设计为一个文件SeqList.cpp,其余函数设计为另一个文件SeqList.h。
请填空完成以下给出的源代码并调试通过。
(1)文件SeqList.h:typedef struct List{ElemType *elem;int length;int listsize;}SeqList;void InitList(SeqList &L){ //初始化线性表…………}void ClearList(SeqList &L){ //清除线性表………………}int LengthList(SeqList L){ //求线性表长度………..}bool InsertList(SeqList &L, ElemType item, int pos){ //按给定条件pos向线性表插入一个元素…….}ElemType GetList(SeqList L, int pos){ //在线性表L中求序号为pos的元素,该元素作为函数值返回…………..}(2)文件SeqList.cpp:#include <stdio.h>#include <stdlib.h>typedef ElemType;#define MAXSize 10#include "SeqList.h"void main(void){SeqList myList;int i=1, x, sum=0, n;InitList ( );scanf(“%d”, &x);while ( x!= -1 ){if ( InsertList (myList, , i )==0) {printf("错误!\n");return ;}i++;scanf(“%d”, &x);}n = LengthList (myList);for (i=1; i<=n; i++){x=GetList(myList, i);sum = + x;}printf("%d\n ", sum);ClearList(myList);}2、提高部分:编写函数bool DeleteElem(SeqList &L, int min, int max)实现从顺序表中删除其值在给定值min和max之间(min < max)的所有元素,要求把该函数添加到文件SeqList.h中,并在主函数文件SeqList.cpp中添加相应语句进行测试。
邻接表(c语言)
邻接表(c语⾔)#include<stdio.h>#include<stdlib.h>#include<string.h>#define MaxVertices 100typedef char ElemType; //顶点类型假定为char//边表结点typedef struct node{int adjvex; //指向⽬标结点位置struct node *next; //指向下⼀条边}ArcNode;// 顶点表typedef struct{ElemType data; //顶点ArcNode * first; //指向边表}VerNode;//邻接表typedef struct{VerNode adjList[MaxVertices];//顶点表int n,e;//顶点总数边数}AdjList;//返回顶点在顶点表的位置int weizhi(char v,AdjList l){int i=0;for(i;i<l.n;i++){if(v==l.adjList[i].data){return i;}}return -1;}//⽣成邻接表void CreateGraph(AdjList *L){int i,p,q;char vi,vj;ArcNode *s;printf("请输⼊总顶点数和总边数:");scanf("%d %d",&L->n,&L->e);getchar();printf("建⽴顶点表\n");for(i=0;i<L->n;i++){printf("请输⼊第%d个顶点:",i+1);scanf("%c",&L->adjList[i].data);getchar();L->adjList[i].first=NULL;//边表指针初始化为null}//前插法建⽴边表printf("建⽴边表\n");for(i=0;i<L->e;i++){//有向表 printf("请依次输⼊起始节点和终点节点:")/*⽆向表 */ printf("请输⼊边的两个的顶点值:");scanf("%c %c",&vi,&vj);getchar();p=weizhi(vi,*L);//返回起点的下标q=weizhi(vj,*L);//返回终点的下标s=(ArcNode *)malloc(sizeof(ArcNode));//创建边表的结点s->adjvex=q;s->adjvex=q;s->next=L->adjList[p].first;L->adjList[p].first=s;/*⽆向表则要双向添加s节点s=(ArcNode *)malloc(sizeof(ArcNode));//创建边表的结点s->adjvex=p;s->next=L->adjList[q].first;L->adjList[q].first=s; */}}//打印void DispGraph(AdjList L){int i;for(i=0;i<L.n;i++){printf("%c->",L.adjList[i].data);while(1){if(L.adjList[i].first==NULL){//该顶点的边表指针为空时printf("^");break;}//该顶点的边表指针不为空时printf("%d->",L.adjList[i].first->adjvex);//输出顶点所指向的边表结点的内容L.adjList[i].first=L.adjList[i].first->next;//顶点的指针指向当前边节点的next,即指向下⼀个边节点 }printf("\n");//⼀⾏输出完了换⾏}}int main(){AdjList L;CreateGraph(&L);DispGraph(L);return 1;}。
graph1_
} void DFS(Graph G, int v) {//从第v个顶点出发DFS遍历
�
邻接表
当图中的边数较少时,相邻矩阵就会出现大量 的零元素,存储这些零元素将耗费大量的存储 空间.对于稀疏图,可以采用邻接表存储法. 邻接表(adjacency list)表示法是一种链式存储结 邻接表 链式存储结 构,由一个顺序存储的顶点表和n个链接存储 的边(弧)表组成.
邻接表存储结构
typedef struct ArcNode{ int adjvex; double weight; struct ArcNode *nextarc; }ArcNode; typedef struct { VertexType data; ArcNode *firstarc; }AdjList[MaxVnum]; typedef struct { int vexnum,arcnum; AdjList vertices; }AGraph;
有向图
有向图的邻接矩阵不一定是对称的; 顶点v的出度(OD(v)):等于二维数组对应行中值为1 的元素个数; 顶点v的入度(ID(v)):等于二维数组对应列中值为1 的元素个数; 顶点v的度TD(v) = OD(vi) + ID(vj)
网的邻接矩阵
V1 3 V6 1 V5 6 5 (a) 网 V4 (b) 邻接矩阵 5 8 7 9 V3 5 V2 4 ∞ ∞ 8 ∞ ∞ 3 5 ∞ ∞ ∞ ∞ ∞ ∞ 4 ∞ 5 ∞ ∞ 7 ∞ ∞ ∞ ∞ ∞ ∞ ∞ 9 ∞ ∞ 6 5 ∞ ∞ ∞ 1 ∞
数据结构邻接表实例
数据结构邻接表实例邻接表是一种常用于表示图的数据结构,特别适用于稀疏图(图中的边相对较少的情况)。
下面是一个简单的无向图的邻接表实例,使用Python 语言表示:```pythonclass Graph:def __init__(self):self.adjacency_list = {}def add_vertex(self, vertex):if vertex not in self.adjacency_list:self.adjacency_list[vertex] = []def add_edge(self, vertex1, vertex2):# 无向图,所以边需要同时在两个顶点的邻接表中添加if vertex1 in self.adjacency_list and vertex2 in self.adjacency_list:self.adjacency_list[vertex1].append(vertex2)self.adjacency_list[vertex2].append(vertex1)def display(self):for vertex in self.adjacency_list:print(f"{vertex}: {self.adjacency_list[vertex]}")# 创建一个无向图graph = Graph()# 添加顶点graph.add_vertex("A")graph.add_vertex("B")graph.add_vertex("C")graph.add_vertex("D")# 添加边graph.add_edge("A", "B")graph.add_edge("B", "C")graph.add_edge("C", "D")graph.add_edge("D", "A")# 显示邻接表graph.display()```在上述代码中,`Graph` 类包含了三个方法:- `add_vertex`: 用于添加顶点到图中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/* 头文件:graph1.h:邻接表,中的遍历,生成树,关键路径 */int menu_netselect1(){ /* 邻接表菜单选择系统 */char s[8];int c;clrscr(); /* 清屏 */printf("\n");printf("\n");printf(" ************************************ \n");printf(" * * \n");printf(" * 邻接表结构操作窗口 *\n");printf(" * * \n");printf(" * 无向网:a1.txt; ..... i1.txt; * \n");printf(" * 有向网:a2.txt; ..... i2.txt; * \n");printf(" * 无环网:a3.txt; ..... i3.txt; * \n");printf(" * * \n");printf(" ************************************ \n");printf("\n");printf(" 01:建立邻接表(无向网)\n");printf(" 02:建立邻接表(有向网)\n");printf(" 03:输出邻接表结构\n");printf(" 04:深度遍(连通-非连通)\n");printf(" 05:广度遍(连通-非连通)\n");printf(" 06:邻接表 DFS 树\n");printf(" 07:邻接表 BFS 树\n");printf(" 08:深度遍历建生成树(无向网)\n");printf(" 09:拓扑排序(有向无环网)\n");printf(" 10:关键路径(有向无环网)\n");printf(" 11:销毁当前邻接表\n");printf(" 12:返回主窗口\n");do {printf("\n");printf(" 输入你的选择号:1---12: ");gets(s);c=atoi(s);}while(c<0||c>12);return(c);}int LocateVex1(ALGraph G,VertexType u){ /* 若G中存在顶点u,则返回该顶点在邻接表中位置;否则返回-1 */ int i;for(i=1;i<=G.vex;++i)if(strcmp(u,G.ver[i].data)==0) return i;return -1;}void DestroyGraph1(ALGraph *G){ /* 销毁图(邻接表)G */int i;LNode *p,*q;for(i=1;i<=G->vex;++i) /* 对于所有顶点 */{p=G->ver[i].first;while(p){q=p->next;free(p);p=q;}}G->vex=0; /* 顶点数为0 */G->arc=0; /* 边或弧数为0 */}void setlistunnetwork1(ALGraph *G){ /* 建立邻接表无向网 */int i,j,k,w,l=0; /* w是权值 */VertexType va,vb; /* 连接边或弧的2顶点 */LNode *p;char str[13];FILE *fp;clrscr(); /* 清屏 */printf("\n");printf("\n");printf(" ************************************ \n");printf(" * * \n");printf(" * * \n");printf(" * 邻接表(无向网)文件载入窗口 *\n");printf(" * * \n");printf(" * * \n");printf(" * * \n");printf(" ************************************ \n");printf("\n");printf("\n");printf(" 输入邻接表文件名(可带路径) : ");gets(str);fp=fopen(str,"r");while(fp==NULL){ l++;if(l==3){printf("\n");printf("\n");printf("\n");printf("\n");printf("************************************ \n");printf(" * * \n");printf(" * * \n");printf(" * 请建立图文件后存盘保存* \n");printf(" * * \n");printf(" * 选择新磁盘文件载入* \n");printf(" * * \n");printf(" * * \n");printf("************************************ \n");printf("\n");printf("\n");scanf("%*c");exit(0);}printf(" 邻接表文件 %s 不存在!\n",str);printf(" 输入邻接表文件名(可带路径) : ");gets(str);fp=fopen(str,"r");}fscanf(fp,"%d",&G->vex);fscanf(fp,"%d",&G->arc);for(i=1;i<=G->vex;i++) /* 构造顶点向量 */{fscanf(fp,"%s",G->ver[i].data);G->ver[i].first=NULL; /* 初始化与该顶点有关的出弧链表 */}for(k=1;k<=G->arc;k++) /* 构造相关弧链表 */{fscanf(fp,"%s%s%d",va,vb,&w);i=LocateVex1(*G,va); /* 起点,弧尾 */j=LocateVex1(*G,vb); /* 终点,弧头 */p=(LNode *)malloc(sizeof(LNode)); /* 有向网 */p->wig=w; /* 给待插表结点s赋值,图权 */p->adj=j; /* 弧头 */p->next=G->ver[i].first;G->ver[i].first=p;p=(LNode *)malloc(sizeof(LNode)); /* 无向网 */p->wig=w; /* 给待插表结点s赋值,图权 */p->adj=i; /* 弧头 */p->next=G->ver[j].first;G->ver[j].first=p;}printf("\n 邻接表文件 %s 装入内存成功!!!\n",str);fclose(fp); /* 关闭数据文件 */printf("\n\n");printf("\n按任意键返回..........");scanf("%*c");}void setlistnetwork1(ALGraph *G){ /* 建立邻接表有向网 */int i,j,k,w,l=0; /* w是权值 */VertexType va,vb; /* 连接边或弧的2顶点 */LNode *p;char str[13];FILE *fp;clrscr(); /* 清屏 */printf("\n");printf("\n");printf(" ************************************ \n");printf(" * * \n");printf(" * * \n");printf(" * 邻接表(有向网)文件载入窗口 *\n");printf(" * * \n");printf(" * * \n");printf(" * * \n");printf(" ************************************ \n");printf("\n");printf("\n");printf(" 输入邻接表文件名(可带路径) : ");gets(str);fp=fopen(str,"r");while(fp==NULL){ l++;if(l==3){printf("\n");printf("\n");printf("\n");printf("\n");printf("************************************ \n");printf(" * * \n");printf(" * * \n");printf(" * 请建立图文件后存盘保存* \n");printf(" * * \n");printf(" * 选择新磁盘文件载入* \n");printf(" * * \n");printf(" * * \n");printf("************************************ \n");printf("\n");printf("\n");scanf("%*c");exit(0);}printf(" 邻接表文件 %s 不存在!\n",str);printf(" 输入邻接表文件名(可带路径) : ");gets(str);fp=fopen(str,"r");}fscanf(fp,"%d",&G->vex);fscanf(fp,"%d",&G->arc);for(i=1;i<=G->vex;++i) /* 构造顶点向量 */{fscanf(fp,"%s",G->ver[i].data);G->ver[i].first=NULL; /* 初始化与该顶点有关的出弧链表 */}for(k=1;k<=G->arc;++k) /* 构造相关弧链表 */{fscanf(fp,"%s%s%d",va,vb,&w);i=LocateVex1(*G,va); /* 起点,弧尾 */j=LocateVex1(*G,vb); /* 终点,弧头 */p=(LNode *)malloc(sizeof(LNode)); /* 有向网 */p->wig=w; /* 给待插表结点s赋值,图权 */p->adj=j; /* 弧头 */p->next=G->ver[i].first;G->ver[i].first=p;}printf("\n 邻接表文件 %s 装入内存成功!!!\n",str);fclose(fp); /* 关闭数据文件 */printf("\n\n");printf("\n按任意键返回..........");scanf("%*c");}void printetwork1(ALGraph G){ /* 输出图的邻接表G */int i;Link p;printf("%d个顶点:\n",G.vex);printf("图顶点值:");for(i=1;i<=G.vex;++i)printf("[%3s]",G.ver[i].data);printf("\n");printf("图下标值:");for(i=1;i<=G.vex;++i)printf("[%3d]",i);printf("\n\n该无向图的邻接表结构:\n");printf("[下标][ 表头]→[ 结点]→[ 结点]→[ 结点]→[ 结点]→[ 结点]→[ 结点 ]\n");for(i=1;i<=G.vex;i++){printf("[%4d][ %4s ]",i,G.ver[i].data);p=G.ver[i].first;while(p!=NULL){printf("→[%2d, %2d]",p->adj,p->wig);p=p->next;}printf("\n");}printf("\n");}/*以下为无头单链表中的相关算法*/int LocateElem1(Link L,ElemTypese,int(*compare)(ElemTypes,ElemTypes)){ /* 返回L中第1个与e满足关系compare()的数据元素的位序。