图的遍历和生成树求解实现_课程设计报告
图的遍历及生成树

• •邻接表的DFS算法
void DFS(ALGraph G, int v) { ArcNode *p;
visited[v] = 1; /*置已访问标记*/ printf("%d ", v); /*输出被访问顶点的编号*/ p = G.vertices[v].firstarc; /*p指向顶点v的第一个邻接点*/ while (p!=NULL) {
•v11
•v1,
•v2
•v3
•v2,
•v4,
•v5
•v8,
•v4
•v6
•v7
•v5,
•v3,
•v8
•v6,
•v7
•
•图的DFS算法一般描述
•int visited[MAXVEX]; //访问标志数组
•void DFSTraverse(Graph G)
•{ //对图G作深度优先遍历
• for( v=0; v<G.vexnum; ++v ) visited[v]=FALSE;
•} // DFS1
•G.arcs[v][j] =1
•有邻接点
•visited [n]=0
•未访问过
•
分析:
在遍历图时,对图中每个顶点至多调用一次DFS函数 ,因为一旦某个顶点被标志成已被访问,就不再从它出发 进行搜索。
因此,遍历图的过程实质上是对每个顶点查找其邻接 点的过程。其耗费的时间则取决于所采用的存储结构。 如果用邻接矩阵来表示图,遍历图中每一个顶点都要从 头扫描该顶点所在行,因此遍历全部顶点所需的时间为 O(n2)。 如果用邻接表来表示图,虽然有 2e 个表结点,但只需扫 描 e 个结点即可完成遍历,加上访问 n个头结点的时间, 因此遍历图的时间复杂度为O(n+e)。
图的遍历和生成树求解实现的课程结构设计

图是一种较线性表和树更为复杂的数据结构。
在线性表中,数据元素之间仅有线性关系,每一个数据元素惟独一个直接前驱和一个直接后继;在树形结构中, 数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素〔及其孩子结点相关但只能和上一层中一个元素〔即双亲结点相关;而在图形结构中,节点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
生成树求解主要利用普利姆和克雷斯特算法求解最小生成树,惟独强连通图才有生成树。
1> 先任意创建一个图;2> 图的 DFS,BFS 的递归和非递归算法的实现3> 最小生成树〔两个算法的实现,求连通分量的实现4> 要求用邻接矩阵、邻接表等多种结构存储实现输入数据类型为整型和字符型,输出为整型和字符a.图的邻接矩阵存储:根据所建无向图的结点数 n,建立n*n 的矩阵,其中元素全是无穷大〔int_max,再将边的信息存到数组中。
其中无权图的边用 1 表示, 无边用 0 表示;有全图的边为权值表示,无边用∞表示。
b.图的邻接表存储:将信息通过邻接矩阵转换到邻接表中,即将邻接矩阵的每一行都转成链表的形式将有边的结点进行存储。
c.图的广度优先遍历:假设从图中的某个顶点 v 出发,在访问了 v 之后挨次访问 v 的各个未曾经访问过的邻接点,然后再访问此邻接点的未被访问的邻接点, 并使"先被访问的顶点的邻接点"先于"后被访问的顶点的邻接点"被访问,直至图中所有已被访问的顶点的邻接点都被访问到。
若此时图中还有未被访问的,则另选未被访问的重复以上步骤,是一个非递归过程。
d.图的深度优先遍历:假设从图中某顶点 v 出发,依挨次访问 v 的邻接顶点, 然后再继续访问这个邻接点的系一个邻接点,如此重复,直至所有的点都被访问, 这是个递归的过程。
e.图的连通分量:这是对一个非强连通图的遍历,从多个结点出发进行搜索, 而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其连通分量的顶点集。
,图的遍历及最小生成树实验报告

实验三最小生成树问题班级:计科1101班学号:0909101605姓名:杜茂鹏2013年5月23日一、实验目的掌握图的存储表示和以及图的最小生成树算法。
二、实验内容1.实现图的存储,并且读入图的内容。
2.利用普里姆算法求网络的最小生成树。
3.实现构造生成树过程中的连通分量抽象数据类型。
4.以文本形式输出对应图的最小生成树各条边及权值。
三、实验要求1.在上机前写出全部源程序;2.能在机器上正确运行程序;3.用户界面友好。
四、概要设计、首先采用图的邻接矩阵存储结构,然后从终端输入图的顶点名称、弧以及弧的权值建立邻接矩阵,并将图存储在文件Graph.txt中。
然后利用已经建好的图,分别对其进行深度、广度优先遍历,一次输出遍历的顶点最后建立此图的最小生成树,并将对应的边及权值写入文件graph_prim.txt 中。
六、详细设计实验内容(原理、操作步骤、程序代码)#include<stdio.h>#include<stdlib.h>#include<limits.h>#define INFINITY INT_MAX //最大值#define MAX_VERTEX_NUM 20 //最大顶点个数int visited[MAX_VERTEX_NUM];typedef struct ArcCell{int adj;int *info; //该弧相关信息的指针}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct close{char adjvex;int lowcost;}closedge[MAX_VERTEX_NUM];typedef struct{char vexs[MAX_VERTEX_NUM]; //顶点向量AdjMatrix arcs; //邻接矩阵int vexnum,arcnum; //图的当前顶点数和弧数closedge cld;}MGraph;typedef struct QNode{char data;struct QNode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front1;QueuePtr rear;}LinkQueue;void (*VisitFunc)(MGraph G,int v);void DFSTraverse(MGraph G,void (* Visit)(MGraph G,int v)); void DFS(MGraph G,int v);void InitQueue(LinkQueue &Q){Q.front1=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front1)exit(0);Q.front1->next=NULL;}void EnQueue(LinkQueue &Q,char e){QueuePtr p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(0);p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;}char DeQueue(LinkQueue &Q){if(Q.front1==Q.rear)exit(0);QueuePtr p=Q.front1->next;char e=p->data;Q.front1->next=p->next;if(Q.rear==p)Q.rear=Q.front1;free(p);return e;}int QueueEmpty(LinkQueue Q){if(Q.front1==Q.rear)return 1;return 0;}int LocateVex(MGraph &G,char v1){int i=0;while(!(G.vexs[i]==v1))i++;return i;}char GetVex(MGraph G,int i){char u;u=G.vexs[i];return u;}int minimum(MGraph G,closedge cld){int mini=1000,s1;for(int i=0;i<G.vexnum;i++){if(cld[i].lowcost!=0&&mini>cld[i].lowcost){mini=cld[i].lowcost;s1=i;}}return s1;}void CreateUDN(MGraph &G){int IncInfo;printf("请分别输入顶点数/弧数/以及弧所含信息:");scanf("%d %d %d",&G.vexnum,&G.arcnum,&IncInfo);getchar();for(int i=0;i<G.vexnum;i++){ //构造顶点向量printf("请输入顶点:");scanf("%c",&G.vexs[i]);getchar();}for(int i=0;i<G.vexnum;i++) //初始化邻接矩阵for(int j=0;j<G.vexnum;j++){G.arcs[i][j].adj=INFINITY;G.arcs[i][j].info=NULL;}for(int k=0;k<G.arcnum;k++){char v1,v2;int w,i,j;printf("输入一条边依附的顶点及权值:"); //构造邻接矩阵scanf("%c %c %d",&v1,&v2,&w); //输入一条边依附的顶点及权值i=LocateVex(G,v1);j=LocateVex(G,v2);G.arcs[i][j].adj=w;if(IncInfo)*G.arcs[i][j].info=IncInfo;G.arcs[j][i]=G.arcs[i][j];getchar();}}//深度优先遍历void Visit(MGraph G,int v){printf("%c",G.vexs[v]);}void DFSTraverse(MGraph G,void (* Visit)(MGraph G,int v)){VisitFunc=Visit;for(int v=0;v<G.vexnum;v++)visited[v]=0;for(int v=0;v<G.vexnum;v++)if(!visited[v]){DFS(G,v);}}void DFS(MGraph G,int v){visited[v]=1;VisitFunc(G,v);for(int j=0;j<G.vexnum;j++)if(!visited[j]&&G.arcs[v][j].adj!=INFINITY)DFS(G,j);}void BFSTraverse(MGraph G,void(*Visit)(MGraph G,int v)) {LinkQueue Q;for(int v=0;v<G.vexnum;v++)visited[v]=0;InitQueue(Q);for(int v=0;v<G.vexnum;v++)if(!visited[v]){visited[v]=1;Visit(G,v);EnQueue(Q,G.vexs[v]);while(!QueueEmpty(Q)){DeQueue(Q);for(int j=0;j<G.vexnum;j++)if(!visited[j]&&G.arcs[v][j].adj!=INFINITY) {visited[j]=1;Visit(G,j);EnQueue(Q,G.vexs[j]);}}}}void MiniSpanTree_PRIM(MGraph G,char u){FILE *IN;if((IN=fopen("graph_prim.txt","w+"))==NULL){printf("file open error!");exit(1);}int k=LocateVex(G,u);for(int j=0;j<G.vexnum;j++)if(j!=k){G.cld[j].adjvex=u;G.cld[j].lowcost=G.arcs[k][j].adj;}G.cld[k].lowcost=0;for(int i=1;i<G.vexnum;i++){k=minimum(G,G.cld);printf("%c%c",G.cld[k].adjvex,G.vexs[k]);int m=LocateVex(G,G.cld[k].adjvex);printf("%d\n",G.arcs[m][k].adj);fprintf(IN,"%c,%c,%d",G.cld[k].adjvex,G.vexs[k],G.arcs[m][k].adj);fputs("\n",IN);G.cld[k].lowcost=0;for(int j=0;j<G.vexnum;j++)if(G.arcs[k][j].adj<G.cld[j].lowcost){G.cld[j].adjvex=G.vexs[k];G.cld[j].lowcost=G.arcs[k][j].adj;}}fclose(IN);}void menu(){printf("1.生成无向网G\n");printf("2.最小生成树\n");printf("3.深度遍历\n");printf("4.广度遍历\n");printf("0.退出\n");}int main(void){MGraph G;int m;do{menu();printf("输入你想要进行的操作的序号:");scanf("%d",&m);getchar();switch(m){case 1:CreateUDN(G);break;case 2:char u;u=GetVex(G,0);MiniSpanTree_PRIM(G,u);break;case 3:DFSTraverse(G,Visit);break;case 4:BFSTraverse(G,Visit);break;case 0:break;default:break;}}while(m);}七、测试结果(截图)主界面八、实验心得1拼写错误节应该避免2尽量用通俗易懂的标示符定义函数、变量3变量应该先定义再使用4应该从使用者的角度考虑,做出简洁的主界面5编好一个函数时应该加注释方便以后阅读时好理解。
实现图的遍历算法实验报告

实现图的遍历算法实验报告实现图的遍历算法实验报告⼀实验题⽬: 实现图的遍历算法⼆实验要求:2.1:(1)建⽴如图(p126 8.1)所⽰的有向图 G 的邻接矩阵,并输出之(2)由有向图G的邻接矩阵产⽣邻接表,并输出之(3)再由(2)的邻接表产⽣对应的邻接矩阵,并输出之2.2 (1)输出如图8.1所⽰的有向图G从顶点0开始的深度优先遍历序列(递归算法)(2)输出如图8.1所⽰的有向图G从顶点0开始的深度优先遍历序列(⾮递归算法)(3)输出如图8.1所⽰的有向图G从顶点0开始的⼴度优先遍历序列三实验内容:3.1 图的抽象数据类型:ADT Graph{数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。
数据关系R:R={VR}VR={|v,w∈V且P(v,w),表⽰从v到w的弧,谓词P(v,w)定义了弧的意义或信息}基本操作:CreateGraph( &G, V, VR )初始条件:V是图的顶点集,VR是图中弧的集合。
操作结果:按V和VR的定义构造图G。
DestroyGraph( &G )初始条件:图G存在。
操作结果:销毁图G。
LocateVex( G, u )初始条件:图G存在,u和G中顶点有相同特征。
操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回其它信息。
GetVex( G, v )初始条件:图G存在,v是G中某个顶点。
操作结果:返回v的值。
PutVex( &G, v, value )初始条件:图G存在,v是G中某个顶点。
初始条件:图G存在,v是G中某个顶点。
操作结果:返回v的第⼀个邻接顶点。
若顶点在G中没有邻接顶点,则返回“空”。
NextAdjVex( G, v, w )初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。
操作结果:返回v的(相对于w的)下⼀个邻接顶点。
若w是v 的最后⼀个邻接点,则返回“空”。
InsertVex( &G, v )初始条件:图G存在,v和图中顶点有相同特征。
图的遍历算法实验报告

图的遍历算法实验报告
《图的遍历算法实验报告》
在计算机科学领域,图的遍历算法是一种重要的算法,它用于在图数据结构中
访问每个顶点和边。
图的遍历算法有两种常见的方法:深度优先搜索(DFS)
和广度优先搜索(BFS)。
在本实验中,我们将对这两种算法进行实验,并比较
它们的性能和应用场景。
首先,我们使用深度优先搜索算法对一个简单的无向图进行遍历。
通过实验结
果可以看出,DFS算法会首先访问一个顶点的所有邻居,然后再递归地访问每
个邻居的邻居,直到图中所有的顶点都被访问到。
这种算法在一些应用场景中
非常有效,比如寻找图中的连通分量或者寻找图中的环路。
接下来,我们使用广度优先搜索算法对同样的无向图进行遍历。
通过实验结果
可以看出,BFS算法会首先访问一个顶点的所有邻居,然后再按照距离递增的
顺序访问每个邻居的邻居。
这种算法在一些应用场景中也非常有效,比如寻找
图中的最短路径或者寻找图中的最小生成树。
通过对比实验结果,我们可以发现DFS和BFS算法各自的优势和劣势。
DFS算
法适合用于寻找图中的连通分量和环路,而BFS算法适合用于寻找最短路径和
最小生成树。
因此,在实际应用中,我们需要根据具体的需求来选择合适的算法。
总的来说,图的遍历算法是计算机科学中非常重要的算法之一,它在许多领域
都有着广泛的应用。
通过本次实验,我们对DFS和BFS算法有了更深入的了解,并且对它们的性能和应用场景有了更清晰的认识。
希望通过这篇实验报告,读
者们也能对图的遍历算法有更深入的理解和认识。
生成树实验报告

一、实验目的1. 理解生成树的概念和作用;2. 掌握Prim算法和Kruskal算法实现生成树的方法;3. 分析算法的时间复杂度和空间复杂度;4. 提高算法设计与分析能力。
二、实验原理生成树(Spanning Tree)是一个无向图的所有顶点构成的一棵树,且该树包含了原图的所有顶点。
生成树在计算机网络、电路设计等领域具有广泛的应用。
在无向图中,如果任意两个顶点之间都存在路径,则称该图是连通的。
对于连通图,一定存在一棵生成树。
Prim算法和Kruskal算法是两种常见的生成树算法,它们分别采用贪心策略和最小生成树算法实现。
三、实验内容1. Prim算法实现生成树(1)初始化:设置一个数组来记录每个顶点与当前生成树的连接情况,以及一个数组来记录每个顶点到生成树的距离。
(2)选择一个顶点作为起始顶点,将其距离设置为0,其他顶点距离设置为无穷大。
(3)在当前生成树上选择距离最小的顶点,将其加入生成树,并将该顶点与其他顶点的距离更新。
(4)重复步骤(3),直到所有顶点都被加入生成树。
2. Kruskal算法实现生成树(1)将所有边按照权值从小到大排序。
(2)创建一个并查集,用于判断两个顶点是否属于同一个集合。
(3)遍历排序后的边,对于每条边,判断其两个顶点是否属于同一个集合:(a)如果属于同一个集合,则跳过该边;(b)如果不属于同一个集合,则将这条边加入生成树,并将两个顶点所属的集合合并。
(4)重复步骤(3),直到生成树包含所有顶点。
四、实验步骤1. 创建一个无向图,包含若干顶点和边。
2. 使用Prim算法实现生成树,记录算法运行时间。
3. 使用Kruskal算法实现生成树,记录算法运行时间。
4. 分析两种算法的时间复杂度和空间复杂度。
五、实验结果与分析1. Prim算法实现生成树(1)顶点集合:V = {A, B, C, D, E, F}(2)边集合:E = {(A, B, 1), (A, C, 3), (A, D, 2), (B, C, 2), (B, D, 2), (C, D, 1), (C, E, 4), (D, E, 3), (D, F, 2), (E, F, 1)}(3)Prim算法运行时间:0.001秒2. Kruskal算法实现生成树(1)顶点集合:V = {A, B, C, D, E, F}(2)边集合:E = {(A, B, 1), (A, C, 3), (A, D, 2), (B, C, 2), (B, D, 2), (C, D, 1), (C, E, 4), (D, E, 3), (D, F, 2), (E, F, 1)}(3)Kruskal算法运行时间:0.001秒通过实验,我们可以得出以下结论:1. Prim算法和Kruskal算法均可以有效地实现生成树,且在时间复杂度和空间复杂度上表现良好。
数据结构课程设计-图的遍历和构建

摘要图(Graph)是一种复杂的非线性结构。
图可以分为无向图、有向图。
若将图的每条边都赋上一个权,则称这种带权图网络。
在人工智能、工程、数学、物理、化学、计算机科学等领域中,图结构有着广泛的应用。
在图结构中,对结点(图中常称为顶点)的前趋和后继个数都是不加以限制的,即结点之间的关系是任意的。
图中任意两个结点之间都可能相关。
图有两种常用的存储表示方法:邻接矩阵表示法和邻接表表示法。
在一个图中,邻接矩阵表示是唯一的,但邻接表表示不唯一。
在表示的过程中还可以实现图的遍历(深度优先遍历和广度优先遍历)及求图中顶点的度。
当然对于图的广度优先遍历还利用了队列的五种基本运算(置空队列、进队、出队、取队头元素、判队空)来实现。
这不仅让我们巩固了之前学的队列的基本操作,还懂得了将算法相互融合和运用。
目录第一章课程设计目的..................................................................................... 错误!未定义书签。
第二章课程设计内容和要求....................................................................... 错误!未定义书签。
2.1课程设计内容.................................................................................. 错误!未定义书签。
2.1.1图的邻接矩阵的建立与输出ﻩ错误!未定义书签。
2.1.2图的邻接表的建立与输出............................................... 错误!未定义书签。
2.1.3图的遍历的实现.................................................................... 错误!未定义书签。
图的遍历实验报告

实验五图的基本操作一、实验目的1、使学生可以巩固所学的有关图的基本知识。
2、熟练掌握图的存储结构。
3、熟练掌握图的两种遍历算法。
二、实验内容[问题描述]对给定图,实现图的深度优先遍历和广度优先遍历。
[基本要求]以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列。
【测试数据】由学生依据软件工程的测试技术自己确定。
三、实验前的准备工作1、掌握图的相关概念。
2、掌握图的逻辑结构和存储结构。
3、掌握图的两种遍历算法的实现。
四、实验报告要求1、实验报告要按照实验报告格式规范书写。
2、实验上要写出多批测试数据的运行结果。
3、结合运行结果,对程序进行分析。
编程思路:深度优先算法:计算机程序的一种编制原理,就是在一个问题出现多种可以实现的方法和技术的时候,应该优先选择哪个更合适的,也是一种普遍的逻辑思想,此种思想在运算的过程中,用到计算机程序的一种递归的思想。
度优先搜索算法:又称广度优先搜索,是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。
Dijkstra单源最短路径算法和Prim 最小生成树算法都采用了和宽度优先搜索类似的思想。
其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。
换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。
以临接链表作为存储结构,结合其存储特点和上面两种算法思想,给出两种遍历步骤:(1)既然图中没有确定的开始顶点,那么可从图中任一顶点出发,不妨按编号的顺序,先从编号小的顶点开始。
(2)要遍历到图中所有顶点,只需多次调用从某一顶点出发遍历图的算法。
所以,下面只考虑从某一顶点出发遍历图的问题。
(3)为了在遍历过程中便于区分顶点是否已经被访问,设置一个访问标志数组visited[n],n为图中顶点的个数,其初值为0,当被访问过后,其值被置为1。
(4)这就是遍历次序的问题,图的遍历通常有深度优先遍历和广度优先遍历两种方式,这两种遍历次序对无向图和有向图都适用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中北大学数据结构课程设计说明书2011年12月19日1设计目的:《数据结构》课程主要介绍最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。
进行数据结构课程设计要达到以下目的:⏹了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;⏹初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;⏹提高综合运用所学的理论知识和方法独立分析和解决问题的能力;训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。
2设计内容和要求设计内容:(1)采用合适的存储结构来创建图,并实现图的遍历;(2)计算图的最小生成树,求联通分量设计要求:(1)先任意创建一个图;(2) 图的DFS,BFS的递归和非递归算法的实现(3) 最小生成树(两个算法)的实现,求连通分量的实现(4) 要求用邻接矩阵、邻接表、十字链表多种结构存储实现3.本设计所采用的数据结构:本程序是采用邻接矩阵、邻接表、十字链表等多种结构存储来实现对图的存储。
对图的遍历分别采用了广度优先遍历和深度优先遍历。
4.1 详细设计思想这次课程设计我们主要是应用以前学习的数据结构与面向对象程序设计知识,结合起来才完成了这个程序。
因为图是一种较线形表和树更为复杂的数据结构。
在线形表中,数据元素之间仅有线性关系,每个元素只有一个直接前驱和一个直接后继,并且在图形结构中,节点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
因此,本程序是采用邻接矩阵、邻接表、十字链表等多种结构存储来实现对图的存储。
采用邻接矩阵即为数组表示法,邻接表和十字链表都是图的一种链式存储结构。
对图的遍历分别采用了广度优先遍历和深度优先遍历。
4.3 核心代码#include <iostream> #include <malloc.h> using namespace std;开始创建图G表存储图IfNY显示图的邻接矩阵KRUSCAL算法显示图的邻接表深度优先遍历广度优先遍历最小生成树PRIM输入字母If结束NY图的连通分量输入一个数2013456#define int_max 10000#define inf 9999#define max 20//…………………………………………邻接矩阵定义……………………typedef struct ArcCell22{int adj;char *info;}ArcCell,AdjMatrix[20][20];typedef struct{char vexs[20];AdjMatrix arcs;int vexnum,arcnum; //有向图的当前顶点数和弧数}MGraph_L;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^int localvex(MGraph_L G,char v)//返回V的位置{int i=0;while(G.vexs[i]!=v){ ++i;}return i;}int creatMGraph_L(MGraph_L &G)//创建图用邻接矩阵表示{char v1,v2;int i,j,w;cout<<"…………创建无向图…………"<<endl<<"请输入图G顶点和弧的个数:(4 6)不包括"<<endl; cin>>G.vexnum>>G.arcnum;for(i=0;i!=G.vexnum;++i){cout<<"输入顶点"<<i<<endl;cin>>G.vexs[i];}for(j=0;j!=G.vexnum;++j){ G.arcs[i][j].adj=int_max;G.arcs[i][j].info=NULL;}for(int k=0;k!=G.arcnum;++k){ cout<<"输入一条边依附的顶点和权:(a b 3)不包括"<<endl; cin>>v1>>v2>>w;//输入一条边依附的两点及权值i=localvex(G,v1);//确定顶点V1和V2在图中的位置j=localvex(G,v2);G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}cout<<"图G邻接矩阵创建成功!"<<endl;return G.vexnum;}void ljjzprint(MGraph_L G){ int i,j;for(i=0;i!=G.vexnum;++i){for(j=0;j!=G.vexnum;++j)cout<<G.arcs[i][j].adj<<" ";cout<<endl;}}int visited[max];//访问标记int we;typedef struct arcnode//弧结点{int adjvex;//该弧指向的顶点的位置struct arcnode *nextarc;//弧尾相同的下一条弧}arcnode;typedef struct vnode//邻接链表顶点头接点{ char data;//结点信息arcnode *firstarc;//指向第一条依附该结点的弧的指针}vnode,adjlist;typedef struct//图的定义{ adjlist vertices[max];int vexnum,arcnum;int kind;}algraph;//…………………………………………队列定义……………………typedef struct qnode{int data;struct qnode *next;}qnode,*queueptr;typedef struct{ queueptr front;queueptr rear;}linkqueue;//………………………………………………………………………typedef struct acr{ int pre;//弧的一结点int bak;//弧另一结点int weight;//弧的权}edg;{ int i=0,j=0;arcnode *arc,*tem,*p;for(i=0;i!=G.vexnum;++i){ gra.vertices[i].data=G.vexs[i];gra.vertices[i].firstarc=NULL;}for(i=0;i!=G.vexnum;++i){ for(j=0;j!=G.vexnum;++j){ if(gra.vertices[i].firstarc==NULL){ if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum) { arc=(arcnode *)malloc(sizeof(arcnode));arc->adjvex=j;gra.vertices[i].firstarc=arc;arc->nextarc=NULL;p=arc;++j;while(G.arcs[i][j].adj!=int_max&&j!=G.vexnum) { tem=(arcnode *)malloc(sizeof(arcnode));tem->adjvex=j;gra.vertices[i].firstarc=tem;tem->nextarc=arc;arc=tem;++j;}--j;}}else{ if(G.arcs[i][j].adj!=int_max&&j!=G.vexnum)arc=(arcnode *)malloc(sizeof(arcnode)); arc->adjvex=j;p->nextarc=arc;arc->nextarc=NULL;p=arc;}}}}gra.vexnum=G.vexnum;gra.arcnum=G.arcnum;/*for(i=0;i!=gra.vexnum;++i){ arcnode *p;cout<<i<<" ";p=gra.vertices[i].firstarc;while(p!=NULL){ cout<<p->adjvex;p=p->nextarc;}cout<<endl;}*/cout<<"图G邻接表创建成功!"<<endl;return 1;}void adjprint(algraph gra){ int i;for(i=0;i!=gra.vexnum;++i){ arcnode *p;cout<<i<<" ";while(p!=NULL){ cout<<p->adjvex;p=p->nextarc;}cout<<endl;}}int firstadjvex(algraph gra,vnode v)//返回依附顶点V的第一个点//即以V为尾的第一个结点{ if(v.firstarc!=NULL)return v.firstarc->adjvex;}int nextadjvex(algraph gra,vnode v,int w)//返回依附顶点V的相对于W的下一个顶点{ arcnode *p;p=v.firstarc;while(p!=NULL&&p->adjvex!=w){ p=p->nextarc;}if(p->adjvex==w&&p->nextarc!=NULL){ p=p->nextarc;return p->adjvex;}if(p->adjvex==w&&p->nextarc==NULL)return -10;}int initqueue(linkqueue &q)//初始化队列{ q.rear=(queueptr)malloc(sizeof(qnode));q.front=q.rear;if(!q.front)q.front->next=NULL;return 1;}int enqueue(linkqueue &q,int e)//入队{ queueptr p;p=(queueptr)malloc(sizeof(qnode));if(!p)return 0;p->data=e;p->next=NULL;q.rear->next=p;q.rear=p;return 1;}int dequeue(linkqueue &q,int &e)//出队{ queueptr p;if(q.front==q.rear)return 0;p=q.front->next;e=p->data;q.front->next=p->next;if(q.rear==p)q.rear=q.front;free(p);return 1;}int queueempty(linkqueue q)//判断队为空{ if(q.front==q.rear)return 1;}void bfstra(algraph gra)//广度优先遍历{ int i,e;linkqueue q;for(i=0;i!=gra.vexnum;++i)visited[i]=0;initqueue(q);for(i=0;i!=gra.vexnum;++i)if(!visited[i]){ visited[i]=1;cout<<gra.vertices[i].data;enqueue(q,i);while(!queueempty(q)){ dequeue(q,e);// cout<<" "<<e<<" ";for(we=firstadjvex(gra,gra.vertices[e]);we>=0;we=nextadjvex(gra,gra.vertices[e],we)) { if(!visited[we]){visited[we]=1;cout<<gra.vertices[we].data;enqueue(q,we);}}}}}int dfs(algraph gra,int i);//声明DFSint dfstra(algraph gra){ int i,j;{ visited[i]=0;}for(j=0;j!=gra.vexnum;++j){ if(visited[j]==0)dfs(gra,j);}return 0;}int dfs(algraph gra,int i){ visited[i]=1;int we1;// cout<<i<<visited[i]<<endl;cout<<gra.vertices[i].data;// cout<<endl;for(we=firstadjvex(gra,gra.vertices[i]);we>=0;we=nextadjvex(gra,gra.vertices[i],we)) {// cout<<we<<visited[we]<<endl;we1=we;// cout<<nextadjvex(gra,gra.vertices[i],we)<<endl;if(visited[we]==0)// cout<<dfs(gra,we);//<<endl;// cout<<i<<we1<<endl;we=we1;// cout<<nextadjvex(gra,gra.vertices[i],we)<<endl;}return 12;}int bfstra_fen(algraph gra)//求连通分量for(i=0;i!=gra.vexnum;++i){ visited[i]=0;}for(j=0;j!=gra.vexnum;++j){ if(visited[j]==0){dfs(gra,j);cout<<endl;}}return 0;}typedef struct{ int adjvex;int lowcost;}closedge;/*int minimum(closedge *p);int minispantree(MGraph_L G,char u){ int k,j,i;closedge closedge_a[20];k=localvex(G,u);// cout<<k<<endl;for(j=0;j!=G.vexnum;++j){ if(j!=k){ closedge_a[j].adjvex=u;closedge_a[j].lowcost=G.arcs[k][j].adj; }for(i=1;i!=G.vexnum;++i){ k=minimum(closedge_a);cout<<closedge_a[k].adjvex<<" "<<G.vexs[k]<<endl;closedge_a[k].lowcost=0;for(j=0;j!=G.vexnum;++j)if(G.arcs[k][j].adj<closedge_a[j].lowcost){ closedge_a[j].adjvex=G.vexs[k];closedge_a[j].lowcost=G.arcs[k][j].adj;}}}return 0;}int minimum(closedge *p){ int s=10000;for(;p!=NULL;++p){ if(s>p->lowcost)s=p->lowcost;}return s;}*/int prim(int g[][max],int n) //最小生成树PRIM算法{ int lowcost[max],prevex[max]; //LOWCOST[]存储当前集合U分别到剩余结点的最短路径 //prevex[]存储最短路径在U中的结点int i,j,k,min;for(i=2;i<=n;i++) //n个顶点,n-1条边{ lowcost[i]=g[1][i]; //初始化prevex[i]=1; //顶点未加入到最小生成树中}lowcost[1]=0; //标志顶点1加入U集合for(i=2;i<=n;i++) //形成n-1条边的生成树k=0;for(j=2;j<=n;j++) //寻找满足边的一个顶点在U,另一个顶点在V的最小边 if((lowcost[j]<min)&&(lowcost[j]!=0)){min=lowcost[j];k=j;}printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);lowcost[k]=0; //顶点k加入Ufor(j=2;j<=n;j++) //修改由顶点k到其他顶点边的权值if(g[k][j]<lowcost[j]){lowcost[j]=g[k][j];prevex[j]=k;}printf("\n");}return 0;}int acrvisited[100];//kruscal弧标记数组int find(int acrvisited[],int f){while(acrvisited[f]>0)f=acrvisited[f];return f;}void kruscal_arc(MGraph_L G,algraph gra){ edg edgs[20];int i,j,k=0;for(i=0;i!=G.vexnum;++i)for(j=i;j!=G.vexnum;++j){if(G.arcs[i][j].adj!=10000)edgs[k].bak=j;edgs[k].weight=G.arcs[i][j].adj; ++k;}}int x,y,m,n;int buf,edf;for(i=0;i!=gra.arcnum;++i)acrvisited[i]=0;for(j=0;j!=G.arcnum;++j){m=10000;for(i=0;i!=G.arcnum;++i){if(edgs[i].weight<m){ m=edgs[i].weight;x=edgs[i].pre;y=edgs[i].bak;n=i;}}// cout<<x<<y<<m;// cout<<endl;buf=find(acrvisited,x);edf=find(acrvisited,y);// cout<<buf<<" "<<edf<<endl;edgs[n].weight=10000;if(buf!=edf){acrvisited[buf]=edf;cout<<"("<<x<<","<<y<<")"<<m;cout<<endl;}}void main(){ algraph gra;MGraph_L G;int i,d,g[20][20];char a='a';d=creatMGraph_L(G);creatadj(gra,G);vnode v;cout<<endl<<"……####注意:若该图为非强连通图(含有多个连通分量)时"<<endl <<" 最小生成树不存在,则显示为非法值。