软件综合实习-图遍历
- 格式:doc
- 大小:25.00 KB
- 文档页数:6
图的遍历实验报告一、引言图是一种非线性的数据结构,由一组节点(顶点)和节点之间的连线(边)组成。
图的遍历是指按照某种规则依次访问图中的每个节点,以便获取或处理节点中的信息。
图的遍历在计算机科学领域中有着广泛的应用,例如在社交网络中寻找关系紧密的人员,或者在地图中搜索最短路径等。
本实验旨在通过实际操作,掌握图的遍历算法。
在本实验中,我们将实现两种常见的图的遍历算法:深度优先搜索(DFS)和广度优先搜索(BFS),并比较它们的差异和适用场景。
二、实验目的1. 理解和掌握图的遍历算法的原理与实现;2. 比较深度优先搜索和广度优先搜索的差异;3. 掌握图的遍历算法在实际问题中的应用。
三、实验步骤实验材料1. 计算机;2. 编程环境(例如Python、Java等);3. 支持图操作的相关库(如NetworkX)。
实验流程1. 初始化图数据结构,创建节点和边;2. 实现深度优先搜索算法;3. 实现广度优先搜索算法;4. 比较两种算法的时间复杂度和空间复杂度;5. 比较两种算法的遍历顺序和适用场景;6. 在一个具体问题中应用图的遍历算法。
四、实验结果1. 深度优先搜索(DFS)深度优先搜索是一种通过探索图的深度来遍历节点的算法。
具体实现时,我们可以使用递归或栈来实现深度优先搜索。
算法的基本思想是从起始节点开始,选择一个相邻节点进行探索,直到达到最深的节点为止,然后返回上一个节点,再继续探索其他未被访问的节点。
2. 广度优先搜索(BFS)广度优先搜索是一种逐层遍历节点的算法。
具体实现时,我们可以使用队列来实现广度优先搜索。
算法的基本思想是从起始节点开始,依次遍历当前节点的所有相邻节点,并将这些相邻节点加入队列中,然后再依次遍历队列中的节点,直到队列为空。
3. 时间复杂度和空间复杂度深度优先搜索和广度优先搜索的时间复杂度和空间复杂度如下表所示:算法时间复杂度空间复杂度深度优先搜索O(V+E) O(V)广度优先搜索O(V+E) O(V)其中,V表示节点的数量,E表示边的数量。
图的遍历实验报告1.实验题目试写一个程序,演示无向图的遍历操作。
2.需求分析:①输入的形式和输入值的范围:每一条边的起点和终点序号。
②输出的形式:图遍历的深度优先遍历序列和广度优先遍历序列。
③程序能实现的功能:以邻接多重表为存储结构,实现连通和非连通的无向图的深度优先和广度优先遍历;利用栈实现无向图的广度和深度优先遍历;以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和生成树的边集;求出从一个结点到另外一个结点,但不经过另外一个指定结点的所有简单路径。
3.概要设计CreatGraph(&G,V,VR)初始条件:V是图的顶点集,VR是图中弧的集合.操作结果:按V和VR是定义构造图G.DestroyGraph(&G)初始条件:图G存在操作结果:销毁图GLocateVex(G,u)初始条件: 图G存在,u和G中顶点有相同的特征操作结果:若图G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息GetVex(G,v)初始条件: 图G存在,v是G中顶点操作结果:返回v的值FirstAjvex(G,v)初始条件: 图G存在,v是G中顶点操作结果:返回v的第一个邻接顶点,若顶在图中没有邻接顶点,则返回为空NextAjvex(G,v,w)初始条件: 图G存在,v是G中顶点,w是v的邻接顶点操作结果:返回v的下一个邻接顶点,若w是v的最后一个邻接顶点,则返回空DeleteVexx(&G,v)初始条件: 图G存在,v是G中顶点操作结果:删除顶点v已经其相关的弧DFSTraverse(G,visit())初始条件: 图G存在,visit的顶点的应用函数操作结果: 对图进行深度优先遍历,在遍历过程中对每个结点调用visit函数一次,一旦visit失败,则操作失败BFSTraverse(G,visit())初始条件: 图G存在,visit的顶点的应用函数操作结果:对图进行广度优先遍历,在遍历过程中对每个结点调用visit函数一次,一旦visit失败,则操作失败1)主程序模块void main ()InitGAdjoin(gl,n);CreateAdjoin(gl,n,m);cout<<"图的深度优先遍历序列:"<<endl;dfsAdjoin(gl,visited,1,n);cout<<"图的广度优先遍历序列:"<<endl;bfsAdjoin(gl,visited,1,n);4.详细设计顶点,边和图类型#ifndef GRAPH_H#define GRAPH_H#define MAX_VRTEX_NUM 20struct edgenode{int adjvex;edgenode * next;}; //定义邻接表的边结点类typedef edgenode **adjlist;//定义邻接表类型void InitGAdjoin(adjlist &GL,int n);//初始化图的邻接表void CreateAdjoin(adjlist &GL,int n,int m);//建立图的邻接表void dfsAdjoin(adjlist GL,bool*&visited,int i,int n);//从初始点出发深度优先搜索由邻接表GL表示的图void bfsAdjoin(adjlist GL,bool*&visited,int i,int n);//从初始点出发广度优先搜索由邻接表GL表示的图5.调试分析(略)6.使用说明1) 本程序开发环境为VC 6.0运行环境为dos操作系统2)首先输入顶点数和边的个数。
-实验三、图的遍历操作一、目的掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储构造;掌握DFS及BFS对图的遍历操作;了解图构造在人工智能、工程等领域的广泛应用。
二、要求采用邻接矩阵和邻接链表作为图的存储构造,完成有向图和无向图的DFS 和BFS操作。
三、DFS和BFS 的根本思想深度优先搜索法DFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后选择一个与Vo相邻且没被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且没被访问过的顶点Vj访问,……依次继续。
如果当前被访问过的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样方法向前遍历。
直到图中所有的顶点都被访问。
广度优先算法BFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后访问与Vo相邻的所有未被访问过的顶点V1,V2,……,Vt;再依次访问与V1,V2,……,Vt相邻的起且未被访问过的的所有顶点。
如此继续,直到访问完图中的所有顶点。
四、例如程序1.邻接矩阵作为存储构造的程序例如#include"stdio.h"#include"stdlib.h"#define Ma*Verte*Num 100 //定义最大顶点数typedef struct{char ve*s[Ma*Verte*Num]; //顶点表int edges[Ma*Verte*Num][Ma*Verte*Num]; //邻接矩阵,可看作边表int n,e; //图中的顶点数n和边数e}MGraph; //用邻接矩阵表示的图的类型//=========建立邻接矩阵=======void CreatMGraph(MGraph *G){int i,j,k;char a;printf("Input Verte*Num(n) and EdgesNum(e): ");scanf("%d,%d",&G->n,&G->e); //输入顶点数和边数scanf("%c",&a);printf("Input Verte* string:");for(i=0;i<G->n;i++){scanf("%c",&a);G->ve*s[i]=a; //读入顶点信息,建立顶点表}for(i=0;i<G->n;i++)for(j=0;j<G->n;j++)G->edges[i][j]=0; //初始化邻接矩阵printf("Input edges,Creat Adjacency Matri*\n");for(k=0;k<G->e;k++) { //读入e条边,建立邻接矩阵 scanf("%d%d",&i,&j); //输入边〔Vi,Vj〕的顶点序号G->edges[i][j]=1;G->edges[j][i]=1; //假设为无向图,矩阵为对称矩阵;假设建立有向图,去掉该条语句}}//=========定义标志向量,为全局变量=======typedef enum{FALSE,TRUE} Boolean;Boolean visited[Ma*Verte*Num];//========DFS:深度优先遍历的递归算法======void DFSM(MGraph *G,int i){ //以Vi为出发点对邻接矩阵表示的图G进展DFS搜索,邻接矩阵是0,1矩阵 int j;printf("%c",G->ve*s[i]); //访问顶点Vivisited[i]=TRUE; //置已访问标志for(j=0;j<G->n;j++) //依次搜索Vi的邻接点if(G->edges[i][j]==1 && ! visited[j])DFSM(G,j); //〔Vi,Vj〕∈E,且Vj未访问过,故Vj为新出发点}void DFS(MGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)if(!visited[i]) //Vi未访问过DFSM(G,i); //以Vi为源点开场DFS搜索}//===========BFS:广度优先遍历=======void BFS(MGraph *G,int k){ //以Vk为源点对用邻接矩阵表示的图G进展广度优先搜索 int i,j,f=0,r=0;int cq[Ma*Verte*Num]; //定义队列for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)cq[i]=-1; //队列初始化printf("%c",G->ve*s[k]); //访问源点Vkvisited[k]=TRUE;cq[r]=k; //Vk已访问,将其入队。
数据结构实验报告实验:图的遍历一、实验目的:1、理解并掌握图的逻辑结构和物理结构——邻接矩阵、邻接表2、掌握图的构造方法3、掌握图的邻接矩阵、邻接表存储方式下基本操作的实现算法4、掌握图的深度优先遍历和广度优先原理二、实验内容:1、输入顶点数、边数、每个顶点的值以及每一条边的信息,构造一个无向图G,并用邻接矩阵存储改图。
2、输入顶点数、边数、每个顶点的值以及每一条边的信息,构造一个无向图G,并用邻接表存储该图3、深度优先遍历第一步中构造的图G,输出得到的节点序列4、广度优先遍历第一部中构造的图G,输出得到的节点序列三、实验要求:1、无向图中的相关信息要从终端以正确的方式输入;2、具体的输入和输出格式不限;3、算法要具有较好的健壮性,对错误操作要做适当处理;4、程序算法作简短的文字注释。
四、程序实现及结果:1、邻接矩阵:#include <stdio.h>#include <malloc.h>#define VERTEX_MAX 30#define MAXSIZE 20typedef struct{intarcs[VERTEX_MAX][VERTEX_MAX] ;int vexnum,arcnum;} MGraph; void creat_MGraph1(MGraph *g) { int i,j,k;int n,m;printf("请输入顶点数和边数:");scanf("%d%d",&n,&m);g->vexnum=n;g->arcnum=m;for (i=0;i<n;i++)for (j=0;j<n;j++)g->arcs[i][j]=0;while(1){printf("请输入一条边的两个顶点:\n");scanf("%d%d",&i,&j);if(i==-1 || j==-1)break;else if(i==j || i>=n || j>=n){printf("输入错误,请重新输入!\n");}else{g->arcs[i][j]=1;g->arcs[j][i]=1;}}}void printMG(MGraph *g) {int i,j;for (i=0;i<g->vexnum;i++){for (j=0;j<g->vexnum;j++)printf(" %d",g->arcs[i][j]);printf("\n");}printf("\n");}main(){int i,j;int fg;MGraph *g1;g1=(MGraph*)malloc(sizeof(MGraph));printf("1:创建无向图的邻接矩阵\n\n");creat_MGraph1(g1);printf("\n此图的邻接矩阵为:\n"); printMG(g1);}2、邻接链表:#include<stdio.h>#include<malloc.h>#define MAX_SIZE 10typedef struct node{int vertex;struct node *next;}node,adjlist[MAX_SIZE];adjlist g;int visited[MAX_SIZE+1];int que[MAX_SIZE+1];void creat(){int n,e;int i;int start,end;node *p,*q,*pp,*qq;printf("输入无向图的顶点数和边数:");scanf("%d%d",&n,&e);for(i = 1; i <= n ; i++){visited[i] = 0;g[i].vertex = i;g[i].next = NULL;}printf("依次输入边:\n");for(i = 1; i <= e ; i++){scanf("%d%d",&start,&end);p=(node *)malloc(sizeof(node));p->vertex = end;p->next = NULL;q = &g[start];while(q->next)q = q->next;q->next = p;p1=(node*)malloc(sizeof(node));p1->vertex = start;p1->next = NULL;q1 = &g[end];while(qq->next)q1 = q1->next;q1->next = p1;}}void bfs(int vi){int front,rear,v;node *p;front =0;rear = 1;visited[vi] = 1;que[0] = vi;printf("%d ",vi);while(front != rear){v = que[front];p = g[v].next;while(p){if(!visited[p->vertex]){visited[p->vertex]= 1;printf("%d",p->vertex);que[rear++] = p->vertex;}p = p->next;}front++;}}int main(){creat();bfs(1);printf("\n");return 0;}五.实验心得与体会:(1)通过这次实验,使我基本上掌握了图的存储和遍历,让我弄清楚了如何用邻接矩阵和邻接链表对图进行存储(2)深度优先遍历和广度优先遍历都有着各自的优点,通过程序逐步调试,可以慢慢的理解这两种遍历方法的内涵和巧妙之处。
图的遍历的实验报告图的遍历的实验报告一、引言图是一种常见的数据结构,它由一组节点和连接这些节点的边组成。
图的遍历是指从图中的某个节点出发,按照一定的规则依次访问图中的所有节点。
图的遍历在许多实际问题中都有广泛的应用,例如社交网络分析、路线规划等。
本实验旨在通过实际操作,深入理解图的遍历算法的原理和应用。
二、实验目的1. 掌握图的遍历算法的基本原理;2. 实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法;3. 比较并分析DFS和BFS算法的时间复杂度和空间复杂度。
三、实验过程1. 实验环境本实验使用Python编程语言进行实验,使用了networkx库来构建和操作图。
2. 实验步骤(1)首先,我们使用networkx库创建一个包含10个节点的无向图,并添加边以建立节点之间的连接关系。
(2)接下来,我们实现深度优先搜索算法。
深度优先搜索从起始节点开始,依次访问与当前节点相邻的未访问过的节点,直到遍历完所有节点或无法继续访问为止。
(3)然后,我们实现广度优先搜索算法。
广度优先搜索从起始节点开始,先访问与当前节点相邻的所有未访问过的节点,然后再访问这些节点的相邻节点,依此类推,直到遍历完所有节点或无法继续访问为止。
(4)最后,我们比较并分析DFS和BFS算法的时间复杂度和空间复杂度。
四、实验结果经过实验,我们得到了如下结果:(1)DFS算法的时间复杂度为O(V+E),空间复杂度为O(V)。
(2)BFS算法的时间复杂度为O(V+E),空间复杂度为O(V)。
其中,V表示图中的节点数,E表示图中的边数。
五、实验分析通过对DFS和BFS算法的实验结果进行分析,我们可以得出以下结论:(1)DFS算法和BFS算法的时间复杂度都是线性的,与图中的节点数和边数呈正比关系。
(2)DFS算法和BFS算法的空间复杂度也都是线性的,与图中的节点数呈正比关系。
但是,DFS算法的空间复杂度比BFS算法小,因为DFS算法只需要保存当前路径上的节点,而BFS算法需要保存所有已访问过的节点。
1.问题描述:不少涉及图上操作的算法都是以图的遍历操作为基础的。
试写一个程序,演示在连通的无向图上访问全部结点的操作。
2.基本要求:以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。
3.测试数据:教科书图7.33。
暂时忽略里程,起点为北京。
4.实现提示:设图的结点不超过30个,每一个结点用一个编号表示(如果一个图有n个结点,则它们的编号分别为1,2,…,n)。
通过输入图的全部边输入一个图,每一个边为一个数对,可以对边的输入顺序作出某种限制,注意,生成树的边是有向边,端点顺序不能颠倒。
5.选作内容:(1) .借助于栈类型(自己定义和实现),用非递归算法实现深度优先遍历。
(2) .以邻接表为存储结构,建立深度优先生成树和广度优先生成树,再按凹入表或者树形打印生成树。
1.为实现上述功能,需要有一个图的抽象数据类型。
该抽象数据类型的定义为:ADT Graph{V 是具有相同特性的数据元素的集合,称为顶点集。
R={VR}VR={<v,w> | v ,w v 且P(v,w),<v,w>表示从v 到w 得弧,谓词P(v,w)定义了弧<v,w>的意义或者信息}} ADT Graph2.此抽象数据类型中的一些常量如下:#define TRUE 1#define FALSE 0#define OK 1#define max_n 20 //最大顶点数typedef char VertexType[20];typedef enum{DG, DN, AG, AN} GraphKind;enum BOOL{False,True};3.树的结构体类型如下所示:typedef struct{ //弧结点与矩阵的类型int adj; //VRType为弧的类型。
图--0,1;网--权值int *Info; //与弧相关的信息的指针,可省略}ArcCell, AdjMatrix[max_n][max_n];typedef struct{VertexType vexs[max_n]; //顶点AdjMatrix arcs; //邻接矩阵int vexnum, arcnum; //顶点数,边数}MGraph;//队列的类型定义typedef int QElemType;typedef struct QNode{QElemType data;struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;4.本程序包含三个模块1).主程序模块void main( ){创建树;深度优先搜索遍历;广度优先搜索遍历;}2).树模块——实现树的抽象数据类型3).遍历模块——实现树的深度优先遍历和广度优先遍历各模块之间的调用关系如下:主程序模块树模块遍历模块#include "stdafx.h"#include<iostream>using namespace std;#define TRUE 1#define FALSE 0#define OK 1#define max_n 20 //最大顶点数typedef char VertexType[20];typedef enum{DG, DN, AG, AN} GraphKind;enum BOOL{False,True};typedef struct{ //弧结点与矩阵的类型int adj; //VRType为弧的类型。
图的遍历算法实验报告图的遍历算法实验报告一、引言图是一种常用的数据结构,用于描述事物之间的关系。
在计算机科学中,图的遍历是一种重要的算法,用于查找和访问图中的所有节点。
本实验旨在探究图的遍历算法,并通过实验验证其正确性和效率。
二、实验目的1. 理解图的基本概念和遍历算法的原理;2. 实现图的遍历算法,并验证其正确性;3. 比较不同遍历算法的效率。
三、实验方法1. 实验环境:使用Python编程语言进行实验;2. 实验步骤:a. 构建图的数据结构,包括节点和边的定义;b. 实现深度优先搜索(DFS)算法;c. 实现广度优先搜索(BFS)算法;d. 验证算法的正确性,通过给定的图进行遍历;e. 比较DFS和BFS的效率,记录运行时间。
四、实验结果1. 图的构建:我们选择了一个简单的无向图作为实验对象,包含6个节点和7条边。
通过邻接矩阵表示图的关系。
```0 1 1 0 0 01 0 1 1 0 01 1 0 0 1 10 1 0 0 0 00 0 1 0 0 00 0 1 0 0 0```2. DFS遍历结果:从节点0开始,遍历结果为0-1-2-4-5-3。
3. BFS遍历结果:从节点0开始,遍历结果为0-1-2-3-4-5。
4. 算法效率比较:我们记录了DFS和BFS算法的运行时间。
经实验发现,在这个图的规模下,DFS算法的运行时间为0.001秒,BFS算法的运行时间为0.002秒。
可以看出,DFS算法相对于BFS算法具有更高的效率。
五、讨论与分析1. 图的遍历算法能够帮助我们了解图中的节点之间的关系,有助于分析和解决实际问题。
2. DFS算法和BFS算法都可以实现图的遍历,但其遍历顺序和效率有所不同。
DFS算法会优先访问深度较大的节点,而BFS算法会优先访问离起始节点最近的节点。
3. 在实验中,我们发现DFS算法相对于BFS算法具有更高的效率。
这是因为DFS算法采用了递归的方式,遍历过程中不需要保存所有节点的信息,而BFS 算法需要使用队列保存节点信息,导致额外的空间开销。
实验六图遍历操作的实现一、实验学时:2学时二、实验目的1.实现图的基本操作2.实现图的遍历操作三、实验内容(2,3选做)1. 深度优先和广度优先搜索图2. 求图的关键路径3.求图的最短路径四、主要仪器设备及耗材硬件:计算机一台软件:VC++ 6.0,MSDN2003或者以上版本五、实验步骤1. 分析问题2. 写出算法3. 编制程序4. 上机调试5. 分析结果六、程序清单#include <iostream>#include <stdlib.h>using namespace std;#define MaxInt 32767 //权值的最大值#define MVNum 100 //最大顶点数#define max 50//邻接矩阵存储结构定义typedef struct{char vexs[MVNum]; //存放顶点的数组int arcs[MVNum][MVNum]; //存放邻接矩阵的数组int vexnum,arcnum; //顶点数和边(弧)数}AMGraph;//边(弧)结点结构定义typedef struct ArcNode{int adjvex;struct ArcNode* nextarc;int weight;}ArcNode;//顶点类型定义typedef struct VNode{char data;ArcNode* firstarc;}VNode,AdjList[MVNum]; //顶点数组类型定义//邻接表结构定义typedef struct{AdjList vertices; //顶点数组int vexnum,arcnum; //顶点数和边(弧)数}ALGraph;//顺序队列结构定义typedef struct{int front; //队头int rear; //队尾char base[MVNum]; //存放队列元素的数组}SqQueue;bool visited[MVNum]; //存放图中顶点访问标志的数组//初始化队列void InitQueue(SqQueue &Q){Q.front = Q.rear = 0;}//判断队列Q是否为空,为空返回true,非空返回falsebool QueueEmpty(SqQueue Q){if(Q.rear == Q.front )return true;elsereturn false;}//入队操作,将n插入顺序队列Q的尾部void EnQueue(SqQueue &Q,int n){if(Q.rear-Q.front == MVNum) //队满时,不能执行入队操作exit(-1);else{Q.base[Q.rear] = n;Q.rear++;}}//出队操作,删除队列Q的队头元素,被删元素用n返回void DeQueue(SqQueue &Q,int &n){if(QueueEmpty(Q)) //若队列为空,不能执行出队操作exit(-1);else{n = Q.base [Q.front];Q.front++;}}//在以邻接表方式存储的图G中,查找值为ch的顶点的位置int LocateVex(ALGraph G,char ch){for(int i=0;i<G.vexnum;++i){if(G.vertices[i].data == ch)return i;}}//在以邻接矩阵方式存储的图G中,查找值为ch的顶点的位置int LocateVex1(AMGraph G,char ch){for(int i=0;i<G.vexnum;i++){if(G.vexs[i] == ch)return i;}}//以邻接表为存储结构,创建无向图Gvoid CreateUDG_AL(ALGraph &G){int i, j, k;char v1, v2;ArcNode *p1,*p2;cout<<"请输入要创建的无向图的顶点数和边数,中间用空格分隔:"<<endl;cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数cout<<"请输入图中的顶点"<<endl;for(i=0;i<G.vexnum;i++) //将顶点依次存储在数组G.vertices中{cin>>G.vertices[i].data; //输入顶点值G.vertices[i].firstarc=NULL; //初始化第i个表头结点的指针域为NULL}for(k=0;k<G.arcnum;k++) //输入各边,构造邻接表{cout<<"请输入第"<<k+1<<"条边的两个顶点"<<endl;cin >> v1 >> v2; //输入一条边依附的两个顶点i = LocateVex(G, v1); //查找顶点v1在图中的位置j = LocateVex(G, v2); //查找顶点v2在图中的位置,即顶点在G.vertices中的序号p1=new ArcNode; //创建一个新的边结点p1p1->adjvex=j; //设置p1的邻接点域为jp1->nextarc= G.vertices[i].firstarc; //把边结点p1插入到第i个边链表中(前插法)G.vertices[i].firstarc=p1; //将新结点p1插入顶点vi的边表头部p2=new ArcNode; //创建另一个对称的新的边结点p2p2->adjvex=i; //设置p1的邻接点域为ip2->nextarc= G.vertices[j].firstarc;G.vertices[j].firstarc=p2; //将新结点p2插入顶点vj的边表头部}}//以邻接矩阵为存储结构,创建有向图Gvoid CreateDG_AM(AMGraph &G){int i, j, k;char v1, v2;cout<<"请输入要创建的有向网的顶点数和边数,中间用空格分隔:"<<endl;cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数cout<<"请输入顶点"<<endl;for(i=0;i<G.vexnum ;i++) //将顶点依次存储在数组G.vexs中{cin>>G.vexs [i];}for(i=0;i<G.vexnum;++i) //初始化邻接矩阵,将邻接矩阵中的值初始化为极大值0 {for(j=0;j<G.vexnum;j++){G.arcs[i][j]=0;}}//依次输入每条弧及权值,建立邻接矩阵for(k=0;k<G.arcnum;k++){//构造邻接矩阵cout<<"请输入第"<<k+1<<"条弧的弧尾、弧头和权值(输入示例:a到b的一条弧,权值为20,输入方式:a b 20)"<<endl;cin>>v1>>v2; //输入弧尾v1,弧头v2和权值weighti = LocateVex1(G,v1); //确定v1和v2在G中的位置,即顶点数组的下标j = LocateVex1(G,v2);G.arcs[i][j]=1; //将邻接矩阵中第i行第j列的值修改为权值}}//以邻接矩阵为存储结构,创建有向网Gvoid CreateDN_AM(AMGraph &G){int i, j, k, w;char v1, v2;cout<<"请输入要创建的有向网的顶点数和边数,中间用空格分隔:"<<endl;cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数cout<<"请输入顶点"<<endl;for(i=0;i<G.vexnum ;i++) //将顶点依次存储在数组G.vexs中{cin>>G.vexs [i];}for(i=0;i<G.vexnum;++i)//初始化邻接矩阵,将邻接矩阵中的值初始化为极大值MaxInt {for(j=0;j<G.vexnum;j++){G.arcs[i][j]=MaxInt;}}//依次输入每条弧及权值,建立邻接矩阵for(k=0;k<G.arcnum;k++){//构造邻接矩阵cout<<"请输入第"<<k+1<<"条弧的弧尾、弧头和权值(输入示例:a到b的一条弧,权值为20,输入方式:a b 20)"<<endl;cin>>v1>>v2>>w; //输入弧尾v1,弧头v2和权值wi = LocateVex1(G,v1); //确定v1和v2在G中的位置,即顶点数组的下标j = LocateVex1(G,v2);G.arcs[i][j]=w; //将邻接矩阵中第i行第j列的值修改为权值}}//从图中的第v个顶点出发,深度遍历图G(以邻接表为存储结构)void DFS(ALGraph G,int v){ArcNode *p;int w;cout << G.vertices[v].data << " "; //输出第v个顶点visited[v] = true; //设置第v个顶点的访问标志//依次从v的未被访问过的邻接点出发,深度遍历图Gp = G.vertices[v].firstarc; //p指向v的边链表的第一个边结点while(p) //边结点非空{w = p->adjvex; //表示w是v的邻接点if(!visited[w]) DFS(G, w); //如果w未访问,则递归调用DFSp = p->nextarc; //p指向下一个边结点}}//深度遍历图Gvoid DFSTraverse(ALGraph G){int v;for(v=0;v<G.vexnum ;v++) //初始化所有顶点的访问标志位falsevisited[v] = false;for(v=0;v<G.vexnum ;v++) //逐一检查每个顶点的访问标志,找一个未被访问过的顶点v为出发点,对图G进行深度遍历{if(visited[v] == false)DFS(G,v);}}//从图中的第v个顶点出发,广度遍历图G(以邻接表为存储结构)void BFS(ALGraph G,int v){SqQueue Q; //Q为顺序队列ArcNode *p;int w,u;InitQueue(Q); //初始化队列Qcout<<G.vertices [v].data<<" "; //输出第v个顶点visited[v] = true; //设置第v个顶点的访问标志EnQueue(Q,v); //将第v个顶点入队while(!QueueEmpty(Q)){DeQueue(Q, u); //删除队头元素u,开始依次访问顶点u的未被访问过的邻接点p = G.vertices[u].firstarc;while(p){w = p->adjvex; //取得邻接点wif(!visited[w]){cout<<G.vertices[w].data<<" ";visited[w] = true;EnQueue(Q,w);}p = p->nextarc; //处理下一个边(弧)结点}}}//广度遍历图Gvoid BFSTraverse(ALGraph G){int v;for(v=0;v<G.vexnum;v++) //初始化所有顶点的访问标志位falsevisited[v] = false;for(v=0;v<G.vexnum;v++){if(visited[v] == false)BFS(G,v);}}//使用迪杰斯特拉算法求第v0个顶点到其它顶点的最短路径void ShortestPath_DIJ(AMGraph G,int v0){int D[MVNum],Path[MVNum],i,v,w,min;bool S[MVNum];for(v=0;v<G.vexnum;v++){S[v] = false; //S初始为空集D[v] = G.arcs[v0][v]; //将v0到各个终点的最短路径长度初始化为弧上的权值if(D[v] < MaxInt)Path[v] = v0; //如果v0和v之间有弧,则将v的前驱置为v0 elsePath[v] = -1; //如果v0和v之间无弧,则将v的前驱置为-1 }//将第v0个顶点设置为源点S[v0] = true;D[v0] = 0;//循环G.vexnum-1次,求第v0个顶点到图中其它顶点的最短距离for(i=1;i<G.vexnum;i++){min= MaxInt; //寻找距离源点最近的第v个顶点for(w=0;w<G.vexnum;++w){if(!S[w] && D[w] < min){ //选择一条当前的最短路径,终点为vv = w;min = D[w];}}S[v] = true; //将第v个顶点加入到S中,S表示已求得最短路径的顶点集合for(w=0;w<G.vexnum ;w++) //更新源点到其它顶点的最短距离{if(!S[w] && (D[v] + G.arcs[v][w] < D[w])){D[w] = D[v] + G.arcs[v][w]; //更新D[w]Path[w] = v; //更改w的前驱为v}}}//输出源点到其它顶点的最短路径及路径长度for(int i=0;i<G.vexnum ;i++){cout<<"顶点"<<G.vexs[v0]<<"到顶点"<<G.vexs[i]<<"的最短路径长度为"<<D[i]<<",路径为:";int temp = i;int temp1, temp2;int flag[max], m = 0;while (temp!= -1){flag[m++] = temp;temp1 = temp ;temp2 = Path[temp1];temp = temp2;}cout << G.vexs[flag[m-1]];for (int i = m-2; i >= 0; i--){cout << "->";cout <<G.vexs[flag[i]];}cout<<endl;}}void AdjacentMatrix(AMGraph &G){for(int i = 0 ; i < G.vexnum ; ++i){for( int j = 0; j < G.vexnum; ++j){if(j != G.vexnum - 1){if(G.arcs[i][j] != MaxInt)cout << G.arcs[i][j] << "\t";elsecout << "∞" << "\t";}else{if(G.arcs[i][j] != MaxInt)cout << G.arcs[i][j] <<endl;elsecout << "∞" <<endl;}}}}void AdjacencyList(ALGraph &G){for(int i = 0 ; i < G.vexnum ; ++i){VNode temp = G.vertices[i];ArcNode *p = temp.firstarc;if(p == NULL){cout << G.vertices[i].data;cout << endl;}else{cout << temp.data;while(p){cout << "->";cout << p->adjvex;p = p->nextarc;}}cout << endl;}}int main(){ALGraph G;AMGraph G1;char ch;int k;//以下操作完成无向图G的创建(基于邻接表存储方式)、G的深度遍历和广度遍历cout<<"以下操作完成无向图G的创建(基于邻接表存储方式)、G的深度遍历和广度遍历"<<endl;CreateUDG_AL(G); //创建无向图Gcout << "*****邻接表表示法创建的无向图*****" << endl;AdjacencyList(G);cout<<"图G的深度遍历序列为:";DFSTraverse(G); //深度优先遍历图Gcout<<endl;cout<<"图G的广度遍历序列为:";BFSTraverse(G); //广度优先遍历图Gcout<<endl<<endl;//以下操作完成有向网G1的创建(基于邻接矩阵存储方式),并在G1中求最短路径cout<<"******************************************************************** ********"<<endl;cout<<"以下操作完成有向网G1的创建(基于邻接矩阵存储方式),并在G1中求最短路径"<<endl;CreateDN_AM(G1); //创建有向网G1cout << "*****邻接矩阵表示法创建的有向网*****" << endl;AdjacentMatrix(G1);cout<<"请输入源点:";cin>>ch; //输入源点k=LocateVex1(G1,ch); //求源点在G1中的位置kShortestPath_DIJ(G1,k); //使用迪杰斯特拉算法求第k个顶点到其它顶点的最短路径return 0;}七、运行结果及分析一、无向图G的邻接表和深度、广度遍历:下图是一种解法:二、无向网G1的邻接矩阵和迪杰斯特拉求最短路径:下图是一种解法:三、问题与解决方法:问题一:广度遍历序列和预想的不一样。
图的遍历实验报告图的遍历实验报告一、引言图是一种常见的数据结构,广泛应用于计算机科学和其他领域。
图的遍历是指按照一定规则访问图中的所有节点。
本实验通过实际操作,探索了图的遍历算法的原理和应用。
二、实验目的1. 理解图的遍历算法的原理;2. 掌握深度优先搜索(DFS)和广度优先搜索(BFS)两种常用的图遍历算法;3. 通过实验验证图的遍历算法的正确性和效率。
三、实验过程1. 实验环境准备:在计算机上安装好图的遍历算法的实现环境,如Python编程环境;2. 实验数据准备:选择合适的图数据进行实验,包括图的节点和边的信息;3. 实验步骤:a. 根据实验数据,构建图的数据结构;b. 实现深度优先搜索算法;c. 实现广度优先搜索算法;d. 分别运行深度优先搜索和广度优先搜索算法,并记录遍历的结果;e. 比较两种算法的结果,分析其异同点;f. 对比算法的时间复杂度和空间复杂度,评估其性能。
四、实验结果与分析1. 实验结果:根据实验数据和算法实现,得到了深度优先搜索和广度优先搜索的遍历结果;2. 分析结果:a. 深度优先搜索:从起始节点出发,一直沿着深度方向遍历,直到无法继续深入为止。
该算法在遍历过程中可能产生较长的路径,但可以更快地找到目标节点,适用于解决一些路径搜索问题。
b. 广度优先搜索:从起始节点出发,按照层次顺序逐层遍历,直到遍历完所有节点。
该算法可以保证找到最短路径,但在遍历大规模图时可能需要较大的时间和空间开销。
五、实验总结1. 通过本次实验,我们深入理解了图的遍历算法的原理和应用;2. 掌握了深度优先搜索和广度优先搜索两种常用的图遍历算法;3. 通过实验验证了算法的正确性和效率;4. 在实际应用中,我们需要根据具体问题的需求选择合适的遍历算法,权衡时间复杂度和空间复杂度;5. 进一步研究和优化图的遍历算法,可以提高算法的性能和应用范围。
六、参考文献[1] Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.[2] Sedgewick, R., & Wayne, K. (2011). Algorithms (4th ed.). Addison-Wesley Professional.。
#ifndef GRAPH_H
#define GRAPH_H
#define MAX_VRTEX_NUM 20
struct edgenode{
int adjvex;
edgenode * next;
}; //定义邻接表的边结点类型
typedef edgenode **adjlist;
//定义邻接表类型
void InitGAdjoin(adjlist &GL,int n);
//初始化图的邻接表
void CreateAdjoin(adjlist &GL,int n,int m);
//建立图的邻接表
void dfsAdjoin(adjlist GL,bool*&visited,int i,int n);
//从初始点出发深度优先搜索由邻接表GL表示的图void bfsAdjoin(adjlist GL,bool*&visited,int i,int n);
//从初始点出发广度优先搜索由邻接表GL表示的图#endif
#include<iostream.h>
#include<stdio.h>
#include"图.h"
void Check(int n,int& i,int& j);
void InitGAdjoin(adjlist&GL,int n)
//初始化图的邻接表
{
GL=new edgenode*[n];
for(int i=1;i<=n;i++)GL[i]=NULL;
}
void CreateAdjoin(adjlist &GL,int n,int m)
//建立图的邻接表
{
int i,j,k,e;
cout<<"输入图的总边数:";
cin>>e;
if(m==0){
//建立无向图
for(k=0;k<e;k++){
cout<<"输入第"<<k<<"条边的起点和终点序号!"<<endl;
cin>>i>>j;
Check(n,i,j);
edgenode*p=new edgenode;
p->adjvex=j;
p->next=GL[i];
GL[i]=p;
//向序号为i的单链表的表头插入一个边结点
p=new edgenode;
p->adjvex=i;
p->next=GL[j];
GL[j]=p;
//向序号为j的单链表的表头插入一个边结点
}
cout<<endl<<"=============="<<endl;
cout<<"图的邻接表为:"<<endl;
for(i=1;i<=n;i++){
edgenode*p=GL[i];
cout<<i-1<<" |"<<"V"<<i;
for(p=GL[i];p!=NULL;p=p->next)
cout<<"|-|->|"<<p->adjvex;
cout<<"|^|";
cout<<endl;
}
//输出邻接表
}
else if(m==1){//建立有向图
for(k=1;k<=e;k++){
cout<<"输入第"<<k<<"条边的起点和终点序号!"<<endl;
cin>>i>>j;
Check(n,i,j);
//向序号为i的表头插入一个边结点
edgenode*p=new edgenode;
p->adjvex=j;
p->next=GL[i];
GL[i]=p;
}
cout<<"图的邻接表为:"<<endl;
for(i=1;i<=n;i++){
edgenode*p=GL[i];
cout<<i-1<<" |"<<"V"<<i;
for(p=GL[i];p!=NULL;p=p->next)
cout<<"|-|->|"<<p->adjvex;
cout<<"|^|";
cout<<endl;
}
//输出邻接表
}
}
void dfsAdjoin(adjlist GL,bool*& visited,int i,int n)
//从初始点出发深度优先搜索邻接表GL表示的图
{
cout<<i<<' ';
visited[i]=true;
edgenode* p=GL[i];
while(p!=NULL){
int j=p->adjvex;
//j为Vi的一个邻接点的序号
if(!visited[j])
dfsAdjoin(GL,visited,j,n);
p=p->next;
//使p指向Vi单链表的下一个边结点
}
}
void bfsAdjoin(adjlist GL,bool*& visited,int i,int n) //从初始点出发广度优先搜索邻接表GL表示的图{
const int MaxLength=30;
int q[MaxLength]={0};
//定义一个队列q,其元素类型为整形
int front=0,rear=0;
//定义队首和队尾指针
cout<<i<<' ';
//访问Vi
visited[i]=true;
//标记初始点Vi已访问过
q[++rear]=i;
//将已访问过的初始点序号i入队
while(front!=rear){
//当队列非空时进行循环处理
front=(front+1)%MaxLength;
//删除队首元素,第一次执行时k的值为i
int k=q[front];
edgenode* p=GL[k];
//取Vk邻接表的表头指针
while(p!=NULL){
//依次搜索Vk的每一个结点
int j=p->adjvex;
//Vj为Vk的一个邻接点
if(!visited[j]){
//若Vj没有被访问过则进行处理
cout<<j<<' ';
visited[j]=true;
rear=(rear+1)%MaxLength;
q[rear]=j;
}
p=p->next;
}
}
}
void Check(int n,int & i,int & j)
//检查输入的边序号是否越界,若越界则重输{
while(1){
if(i<=0||i>n||j<=0||j>n)
cout<<"输入有误,请重新输入!";
else return;
cin>>i>>j;
}
}
#include<iostream.h>
#include"图.h"
void main()
{
int i,n,m;
cout<<"=============="<<endl;
cout<<"输入图的顶点数:";
cin>>n;
cout<<"输入是否有向(0为无,1为有):";
cin>>m;
bool*visited=new bool[n];
adjlist gl;
InitGAdjoin(gl,n);
CreateAdjoin(gl,n,m);
cout<<"=============="<<endl;
cout<<"图的深度优先遍历序列:"<<endl;
for(i=1;i<=n;i++)visited[i]=false;
dfsAdjoin(gl,visited,1,n);
cout<<endl<<"=============="<<endl;
cout<<"图的广度优先遍历序列:"<<endl;
for(i=1;i<=n;i++)visited[i]=false;
bfsAdjoin(gl,visited,1,n);
cout<<endl;
}。