实验7 图的表示与遍历
数据结构实验报告图的遍历讲解
数据结构实验报告图的遍历讲解一、引言在数据结构实验中,图的遍历是一个重要的主题。
图是由顶点集合和边集合组成的一种数据结构,常用于描述网络、社交关系等复杂关系。
图的遍历是指按照一定的规则,挨次访问图中的所有顶点,以及与之相关联的边的过程。
本文将详细讲解图的遍历算法及其应用。
二、图的遍历算法1. 深度优先搜索(DFS)深度优先搜索是一种常用的图遍历算法,其基本思想是从一个顶点出发,沿着一条路径向来向下访问,直到无法继续为止,然后回溯到前一个顶点,再选择此外一条路径继续访问。
具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问。
(2)从v出发,选择一个未被访问的邻接顶点w,将w标记为已访问,并将w入栈。
(3)如果不存在未被访问的邻接顶点,则出栈一个顶点,继续访问其它未被访问的邻接顶点。
(4)重复步骤(2)和(3),直到栈为空。
2. 广度优先搜索(BFS)广度优先搜索是另一种常用的图遍历算法,其基本思想是从一个顶点出发,挨次访问其所有邻接顶点,然后再挨次访问邻接顶点的邻接顶点,以此类推,直到访问完所有顶点。
具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问,并将v入队。
(2)从队首取出一个顶点w,访问w的所有未被访问的邻接顶点,并将这些顶点标记为已访问,并将它们入队。
(3)重复步骤(2),直到队列为空。
三、图的遍历应用图的遍历算法在实际应用中有广泛的应用,下面介绍两个典型的应用场景。
1. 连通分量连通分量是指图中的一个子图,其中的任意两个顶点都是连通的,即存在一条路径可以从一个顶点到达另一个顶点。
图的遍历算法可以用来求解连通分量的个数及其具体的顶点集合。
具体步骤如下:(1)对图中的每一个顶点进行遍历,如果该顶点未被访问,则从该顶点开始进行深度优先搜索或者广度优先搜索,将访问到的顶点标记为已访问。
(2)重复步骤(1),直到所有顶点都被访问。
2. 最短路径最短路径是指图中两个顶点之间的最短路径,可以用图的遍历算法来求解。
图的遍历 实验报告
图的遍历实验报告一、引言图是一种非线性的数据结构,由一组节点(顶点)和节点之间的连线(边)组成。
图的遍历是指按照某种规则依次访问图中的每个节点,以便获取或处理节点中的信息。
图的遍历在计算机科学领域中有着广泛的应用,例如在社交网络中寻找关系紧密的人员,或者在地图中搜索最短路径等。
本实验旨在通过实际操作,掌握图的遍历算法。
在本实验中,我们将实现两种常见的图的遍历算法:深度优先搜索(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表示边的数量。
图的遍历操作实验报告
-实验三、图的遍历操作一、目的掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储构造;掌握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)掌握图的常见应用算法的思想及其程序实现。
(4)理解有向无环图、最短路径等算法二、实验要求1.将算法中的横线内容填写完整,使程序能正常运行2.在主函数中设计一个简单的菜单,具有如下功能。
(1)建立有向图的邻接表;(2)输出邻接表;3.实现图的深度优先遍历的算法(选做)4.完成实际应用(选做)三、实验原理1、图(GRAPH )是一种复杂的数据结构,结点之间的关系可以是任意的,由此图的应用极为广泛,已经渗透到如物理、化学、电讯工程、计算机科学等领域。
2、图存储结构:邻接矩阵表示法和邻接表表示法,本次实验图主要以邻接表进行存储。
用邻接矩阵表示法表示图如下图所示:0 1 0 1 A = 1 0 1 10 1 0 01 0 0 1一个无向图的邻接矩阵表示无向图对应的邻接表表示如下图所示:序号一个无向图的的邻接表表示四、实验程序说明图类型定义typedef struct Node{int dest; //邻接边的弧头结点序号struct Node *next;}Edge; //邻接边单链表的结点的结构体typedef struct{DataType data; //图顶点Edge *adj; //邻接边的头指针}AdjLHeight; //数组的数据元素类型结构体typedef struct{AdjLHeight a[MaxVertices]; //邻接表数组int numOfVerts; //结点个数int numOfEdges; //边个数}AdjLGraph; //邻接表结构体五、参考程序#include<malloc.h> /* malloc()等*/#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<process.h> /* exit() */typedef char DataType;#define MaxVertices 10void AdjInitiate(AdjLGraph *G)//初始化图{int i;G->numOfEdges=0;G->numOfVerts=0;for(i=0;i<MaxVertices;i++){G->a[i].adj = NULL ;//设置邻接边单链表头指针初值}}void InsertVertex(AdjLGraph *G,int i,DataType vertex)//在图中的第i个位置插入顶点数据元素vertex{if(i>=0&&i<MaxVertices){G->a[i].data =vertex; //存储顶点数据元素vertexG->numOfVerts++ ; //个数加1 }else printf("结点越界");}void InsertEdge(AdjLGraph *G,int v1,int v2)//在图中加入边<v1,v2>的信息{Edge *p;if(v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts){printf("参数v1和v2越界出错!");exit(0);}p=(Edge*)malloc(sizeof(Edge));//申请邻接边单链表结点空间p->dest=v2; //设置邻接边弧头序号p->next = G->a[v1].adj ; //新结点插入邻接表的表头G->a[v1].adj = p ; //头指针指向新的单链表表头G->numOfEdges++; //边个数加1}int GetFirstVex(AdjLGraph G,int v)//取图G中结点v的第一个邻接结点{Edge *p;if(v<0||v>=G.numOfVerts){printf("参数出错!");exit(0);}p=G.a[v].adj;if(p!=NULL)return p->dest;else return -1;}int GetNextVex(AdjLGraph G,int v1,int v2)//取图G中结点v1的邻接结点v2的下一个邻接结点{Edge *p;if(v1<0||v1>=G.numOfVerts||v2<0||v2>=G.numOfVerts){printf("参数v1和v2越界出错!");exit(0);}p=G.a[v1].adj;while(p!=NULL){if(p->dest!=v2){p = p->next ;continue;}else break;}p=p->next;if(p!=NULL) return p->dest;else return -1;}void main(void){int i,k,n,e,v1,v2;char c1;Edge *p;AdjLGraph G;AdjInitiate(&G);printf("输入图的顶点数\n");scanf("%d",&n);getchar();printf("输入图顶点为(请输入字母)\n");for(i=0;i<n;i++){scanf("%c",&c1); //通过键盘,输入图的顶点getchar();InsertVertex(&G,i,c1) ; //插入顶点}printf("输入图的边数\n");scanf("%d",&e);printf("如果边v1->v2,则输入0,1\n");for(k=0;k<e;k++){printf("输入边的顶点为(请输入数字):");scanf("%d,%d",&v1,&v2); //通过键盘,输入图的邻接边的两个顶点InsertEdge(&G,v1,v2) ; //插入边}for(i=0;i<n;i++)//输出邻接表{printf("%c\t",G.a[i].data);p=G.a[i].adj;if(p==NULL) printf("数据为空");else{ while(p!=NULL){printf("%d->",p->dest);p=p->next;}printf("^");}printf("\n");}}序号六、应用题(一)校园导游图实验内容:1、设计学生所在学校的校园平面图,所含景点不少于10个。
图的遍历算法实验报告
图的遍历算法实验报告图的遍历算法实验报告一、引言图是一种常用的数据结构,用于描述事物之间的关系。
在计算机科学中,图的遍历是一种重要的算法,用于查找和访问图中的所有节点。
本实验旨在探究图的遍历算法,并通过实验验证其正确性和效率。
二、实验目的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 算法需要使用队列保存节点信息,导致额外的空间开销。
图的遍历实验报告
图的遍历实验报告图的遍历实验报告一、引言图是一种常见的数据结构,广泛应用于计算机科学和其他领域。
图的遍历是指按照一定规则访问图中的所有节点。
本实验通过实际操作,探索了图的遍历算法的原理和应用。
二、实验目的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.。
实验7 图的表示与遍历
实验五图的表示与遍历一、实验目的1、掌握图的邻接矩阵和邻接表表示2、掌握图的深度优先和广度优先搜索方法3、理解图的应用方法二、实验预习说明以下概念1、深度优先搜索遍历:从根开始一个一个搜索2、广度优先搜索遍历:从根的邻接点出发依次访问3、拓扑排序:一个无指向的点开始排序4、最小生成树:最小权的生成树5、最短路径:路径权数最小三、实验内容和要求1、阅读并运行下面程序,根据输入写出运行结果.#include〈stdio。
h>#define N 20#define TRUE 1#define FALSE 0int visited[N];typedef struct /*队列的定义*/{int data[N];int front,rear;}queue;typedef struct /*图的邻接矩阵*/{int vexnum,arcnum;char vexs[N];int arcs[N][N];}graph;void createGraph(graph *g); /*建立一个无向图的邻接矩阵*/ void dfs(int i,graph *g); /*从第i个顶点出发深度优先搜索*/ void tdfs(graph *g); /*深度优先搜索整个图*/void bfs(int k,graph *g); /*从第k个顶点广度优先搜索*/void tbfs(graph *g); /*广度优先搜索整个图*/void init_visit(); /*初始化访问标识数组*/void createGraph(graph *g) /*建立一个无向图的邻接矩阵*/ { int i,j;char v;g->vexnum=0;g—〉arcnum=0;i=0;printf("输入顶点序列(以#结束):\n");while((v=getchar())!='#'){g—〉vexs[i]=v; /*读入顶点信息*/i++;}g-〉vexnum=i; /*顶点数目*/for(i=0;i<g->vexnum;i++) /*邻接矩阵初始化*/for(j=0;j<g—〉vexnum;j++)g—〉arcs[i][j]=0;printf(”输入边的信息:\n");scanf("%d,%d",&i,&j); /*读入边i,j*/while(i!=—1) /*读入i,j为-1时结束*/{g->arcs[i][j]=1;g—〉arcs[j][i]=1;scanf(”%d,%d",&i,&j);}}void dfs(int i,graph *g) /*从第i个顶点出发深度优先搜索*/ {int j;printf(”%c”,g—〉vexs[i]);visited[i]=TRUE;for(j=0;j<g-〉vexnum;j++)if((g—〉arcs[i][j]==1)&&(!visited[j]))dfs(j,g);}void tdfs(graph *g) /*深度优先搜索整个图*/{int i;printf(”\n从顶点%C开始深度优先搜索序列:",g-〉vexs[0]); for(i=0;i<g->vexnum;i++)if(visited[i]!=TRUE)dfs(i,g);}void bfs(int k,graph *g) /*从第k个顶点广度优先搜索*/{int i,j;queue qlist,*q;q=&qlist;q—〉rear=0;q—〉front=0;printf(”%c”,g-〉vexs[k]);visited[k]=TRUE;q-〉data[q-〉rear]=k;q-〉rear=(q—〉rear+1)%N;while(q-〉rear!=q—〉front){i=q—〉data[q—〉front];q—>front=(q->front+1)%N;for(j=0;j〈g—〉vexnum;j++)if((g-〉arcs[i][j]==1)&&(!visited[j])){printf(”%c",g—〉vexs[j]);visited[j]=TRUE;q—〉data[q->rear]=j;q->rear=(q-〉rear+1)%N;}}}void tbfs(graph *g) /*广度优先搜索整个图*/{int i;printf(”\n从顶点%C开始广度优先搜索序列:”,g—〉vexs[0]); for(i=0;i〈g—>vexnum;i++)if(visited[i]!=TRUE)bfs(i,g);}void init_visit() /*初始化访问标识数组*/{int i;for(i=0;i〈N;i++)visited[i]=FALSE;}int main(){graph ga;int i,j;createGraph(&ga);printf("无向图的邻接矩阵:\n ”);for(i=0;i<ga.vexnum;i++){for(j=0;j 〈ga 。
数据结构实验七 图及图的操作实验
实验报告七图及图的操作实验班级: 2010XXX 姓名: HoogLe 学号: 2010XXXX 专业: XXXX*****************一、实验目的:1、掌握图的基本概念和术语2、掌握图的存储结构及创建算法。
3、掌握图的遍历算法(递归算法)。
二、实验内容:1、图邻接矩阵存储结构表示及基本操作算法实现[实现提示] (同时可参见教材及ppt上的算法)函数、类名称等可自定义,部分变量请加上学号后3位。
也可自行对类中所定义的操作进行扩展。
所加载的库函数或常量定义及类的定义:(1)邻接矩阵存储结构类定义:自定义如下:#include <iostream>using namespace std;const int MaxSize=12;const int INFINITY=65535;template<class T>class Mgraph{public:Mgraph(T a[],int n,int e);//构造函数,a[]表示节点数组,n表示顶点个数,e表示边数void printGraph(); //输出void BFS(int v,int visited[]); //广度优先搜索private:T vertex[MaxSize];int arc[MaxSize][MaxSize];int vertexNum,arcNum;void createUG(T a[],int n,int e); //无向图void createUW(T a[],int n,int e); //无向网void createHG(T a[],int n,int e); //有向图void createHW(T a[],int n,int e); //有向网};template<class T>Mgraph<T>::Mgraph(T a[],int n,int e){int kind;cout<<"请输入所需创建的图的类型:"<<endl;cout<<"1.无向图"<<endl;cout<<"2.无向网"<<endl;cout<<"3.有向图"<<endl;cout<<"4.有向网"<<endl;cin>>kind;switch(kind){case 1:createUG(a,n,e);break;case 2:createUW(a,n,e);break;case 3:createHG(a,n,e);break;case 4:createHW(a,n,e);break;default:cout<<"输入错误!"<<endl;}}(2)创建邻接矩阵算法创建无向图邻接矩阵算法:template <class T>void Mgraph<T>::createUG(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{ cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2):";cin>>i>>j; //边依附的两个顶点的序号arc[i-1][j-1]=1; //置有边标志arc[j-1][i-1]=1;}}创建无向网邻接矩阵算法:无向网的创建:template <class T>void Mgraph<T>::createUW(T a[],int n,int e){//创建无向网int w;//权值vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=INFINITY;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2 权值):";cin>>i>>j>>w;//边依附的两个顶点的序号arc[i-1][j-1]=w; //置有边标志arc[j-1][i-1]=w;}}创建有向图邻接矩阵算法:template <class T>void Mgraph<T>::createHG(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{ cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2):";cin>>i>>j; //边依附的两个顶点的序号arc[i-1][j-1]=1; //置有边标志}}创建有向网邻接矩阵算法:template <class T>void Mgraph<T>::createHW(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;int w;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2 权值):";cin>>i>>j>>w; //边依附的两个顶点的序号arc[i-1][j-1]=w; //置有边标志}}(3)输出邻接矩阵结果算法template <class T>void Mgraph<T>::printGraph(){//输出邻接矩阵int i,j;for(i=0;i<vertexNum;i++){for(j=0;j<vertexNum;j++)cout<<arc[i][j]<<ends;cout<<endl;}}测试结果粘贴如下:void main(){int a[6]={1,2,3,4,5,6};Graph<int> graph1(a,6,5);graph1.printGraph();}2、图邻接表存储结构表示及基本操作算法实现[实现提示]函数、类名称等可自定义,部分变量请加上学号后3位。
实验7 图及其应用
实验7 图及其应用
1.实验目的
1)了解图的特点、掌握图的主要存储结构。
2)学会对几种常见的图的存储结构进行基本操作。
3)掌握复杂的数据结构设计方法。
4)通过对图的遍历操作,理解主要存储结构的特点。
2.实验内容
(1)用图的邻接矩阵存储结构表示图,实现下列基本操作,通过数据测试每个操作的正确性,包括:
1. GreateGraph(&G,n): 建立一个n个顶点的图G。
2. DestoryGraph(&G): 销毁一个已存在的图G。
3. FirstAdjVex(G,v): 求出图G中顶点v的第一个邻接点。
4. GrahDegree(G): 求出图G 中所有顶点的度。
5. DFSTraverse(G,v):从G中顶点v开始的深度优先搜索序列。
6. BFSTraverse(G,v): 从G中顶点v开始的广度优先搜索序列。
7. PrintGraph(G): 输出图G的结构示意,输出相应的二维数组。
(2)用图的邻接矩阵存储结构表示下图,并用Prim算法构造最小生成树。
3.实验要求
(1)上机前编写实验源程序(要求手写,不允许打印),上机前老师检查,没有预先编写实验程序的同学不允许上实验课,按旷课一次处理。
旷课次数超过2次的同学实验成绩不及格,且没有补考资格。
(2)用一切你能想到的办法解决遇到的问题,培养解决问题的能力。
(3)实验报告(于下次实验时交)
报告内容包括:实验目的、实验内容、实验代码、实验输入输出结果以及实验体会供五部分。
数据结构实验报告图的遍历
数据结构实验报告图的遍历数据结构实验报告:图的遍历引言在计算机科学中,图是一种重要的数据结构,它由节点和边组成,用于表示不同实体之间的关系。
图的遍历是一种重要的操作,它可以帮助我们了解图中节点之间的连接关系,以及找到特定节点的路径。
在本实验中,我们将讨论图的遍历算法,并通过实验验证其正确性和效率。
深度优先搜索(DFS)深度优先搜索是一种常用的图遍历算法,它通过递归或栈的方式来遍历图中的节点。
在实验中,我们实现了深度优先搜索算法,并对其进行了测试。
实验结果表明,深度优先搜索算法能够正确地遍历图中的所有节点,并找到指定节点的路径。
此外,我们还对算法的时间复杂度进行了分析,验证了其在不同规模图上的性能表现。
广度优先搜索(BFS)广度优先搜索是另一种常用的图遍历算法,它通过队列的方式来遍历图中的节点。
在实验中,我们也实现了广度优先搜索算法,并对其进行了测试。
实验结果显示,广度优先搜索算法同样能够正确地遍历图中的所有节点,并找到指定节点的路径。
我们还对算法的时间复杂度进行了分析,发现其在不同规模图上的性能表现与深度优先搜索算法相近。
实验结论通过本次实验,我们深入了解了图的遍历算法,并验证了其在不同规模图上的正确性和效率。
我们发现深度优先搜索和广度优先搜索算法都能够很好地应用于图的遍历操作,且在不同情况下都有良好的性能表现。
这些算法的实现和测试为我们进一步深入研究图的相关问题提供了重要的基础。
总结图的遍历是图算法中的重要操作,它为我们提供了了解图结构和节点之间关系的重要手段。
本次实验中,我们实现并测试了深度优先搜索和广度优先搜索算法,验证了它们的正确性和效率。
我们相信这些算法的研究和应用将为我们在图相关问题的研究中提供重要的帮助。
图算法表示及遍历方法详解
图算法表示及遍历方法详解图是计算机科学中常用的数据结构之一,用于表示和解决各种实际问题。
本文将详细介绍图的算法表示以及遍历方法,帮助读者更深入了解和应用图算法。
一、图的定义和表示方法图是由节点(顶点)和边构成的一种数据结构。
常见的图表示方法有两种:邻接矩阵和邻接表。
1. 邻接矩阵表示法邻接矩阵是一个二维矩阵,其中的元素表示图中各个节点之间的连接关系。
对于一个有n个节点的图,邻接矩阵是一个n x n的矩阵,用0和1表示节点之间是否有边相连。
例如,对于一个有4个节点的图,邻接矩阵可以表示为:1 2 3 41[0, 1, 1, 0]2[1, 0, 0, 1]3[1, 0, 0, 0]4[0, 1, 0, 0]邻接矩阵表示法简单直观,适用于节点数量相对较小、边的数量相对较大时。
2. 邻接表表示法邻接表是通过链表的形式,将每个节点的邻接顶点存储起来,用于表示图的连接关系。
对于一个有n个节点的图,可以使用一个长度为n 的数组,数组中的每个元素都是一个链表,链表中存储了与该节点相连的其他节点。
例如,对于一个有4个节点的图,邻接表可以表示为:1->2->32->1->43->14->2邻接表表示法相对节省存储空间,适用于节点数量较大、边的数量相对较小的情况。
二、图的遍历方法图的遍历是指按一定规则依次访问图中的每个节点,以达到查找、搜索或其他操作的目的。
常见的图遍历方法有深度优先搜索(DFS)和广度优先搜索(BFS)。
1. 深度优先搜索(DFS)深度优先搜索从某个节点开始,沿着一条路径一直访问到最后一个节点,然后回溯到上一个节点,再选择另一条未访问过的路径,重复上述过程,直到遍历完整个图。
DFS可以使用递归或栈来实现。
以下是使用递归实现DFS的示例代码:```pythondef dfs(graph, start, visited):visited[start] = Trueprint(start)for neighbor in graph[start]:if not visited[neighbor]:dfs(graph, neighbor, visited)```2. 广度优先搜索(BFS)广度优先搜索从某个节点开始,先访问其所有邻接节点,然后再访问邻接节点的邻接节点,依次类推,直到遍历完整个图。
《数据结构》实验指导及实验报告图的表示与遍历
实验八图的表示与遍历一、实验目的1、掌握图的邻接矩阵和邻接表表示2、掌握图的深度优先和广度优先搜索方法3、理解图的应用方法二、实验预习说明以下概念1、深度优先搜索遍历:2、广度优先搜索遍历:3、拓扑排序:4、最小生成树:5、最短路径:三、实验内容和要求1、阅读并运行下面程序,根据输入写出运行结果。
#include<stdio.h>#define N 20#define TRUE 1#define FALSE 0int visited[N];typedef struct /*队列的定义*/{int data[N];int front,rear;}queue;typedef struct /*图的邻接矩阵*/{int vexnum,arcnum;char vexs[N];int arcs[N][N];}graph;void createGraph(graph *g); /*建立一个无向图的邻接矩阵*/ void dfs(int i,graph *g); /*从第i个顶点出发深度优先搜索*/ void tdfs(graph *g); /*深度优先搜索整个图*/void bfs(int k,graph *g); /*从第k个顶点广度优先搜索*/ void tbfs(graph *g); /*广度优先搜索整个图*/void init_visit(); /*初始化访问标识数组*/void createGraph(graph *g) /*建立一个无向图的邻接矩阵*/ { int i,j;char v;g->arcnum=0;i=0;printf("输入顶点序列(以#结束):\n");while((v=getchar())!='#'){g->vexs[i]=v; /*读入顶点信息*/i++;}g->vexnum=i; /*顶点数目*/for(i=0;i<g->vexnum;i++) /*邻接矩阵初始化*/for(j=0;j<g->vexnum;j++)g->arcs[i][j]=0;printf("输入边的信息:\n");scanf("%d,%d",&i,&j); /*读入边i,j*/while(i!=-1) /*读入i,j为-1时结束*/{g->arcs[i][j]=1;g->arcs[j][i]=1;scanf("%d,%d",&i,&j);}}void dfs(int i,graph *g) /*从第i个顶点出发深度优先搜索*/ {int j;printf("%c",g->vexs[i]);visited[i]=TRUE;for(j=0;j<g->vexnum;j++)if((g->arcs[i][j]==1)&&(!visited[j]))dfs(j,g);}void tdfs(graph *g) /*深度优先搜索整个图*/{int i;printf("\n从顶点%C开始深度优先搜索序列:",g->vexs[0]); for(i=0;i<g->vexnum;i++)if(visited[i]!=TRUE)dfs(i,g);}void bfs(int k,graph *g) /*从第k个顶点广度优先搜索*/{int i,j;queue qlist,*q;q=&qlist;q->front=0;printf("%c",g->vexs[k]);visited[k]=TRUE;q->data[q->rear]=k;q->rear=(q->rear+1)%N;while(q->rear!=q->front){i=q->data[q->front];q->front=(q->front+1)%N;for(j=0;j<g->vexnum;j++)if((g->arcs[i][j]==1)&&(!visited[j])){printf("%c",g->vexs[j]);visited[j]=TRUE;q->data[q->rear]=j;q->rear=(q->rear+1)%N;}}}void tbfs(graph *g) /*广度优先搜索整个图*/{int i;printf("\n从顶点%C开始广度优先搜索序列:",g->vexs[0]); for(i=0;i<g->vexnum;i++)if(visited[i]!=TRUE)bfs(i,g);}void init_visit() /*初始化访问标识数组*/{int i;for(i=0;i<N;i++)visited[i]=FALSE;}int main(){graph ga;int i,j;createGraph(&ga);printf("无向图的邻接矩阵:\n");for(i=0;i<ga.vexnum;i++){for(j=0;j<ga.vexnum;j++)printf("%3d",ga.arcs[i][j]);printf("\n");}init_visit();tdfs(&ga);init_visit();tbfs(&ga);return 0;}▪根据右图的结构验证实验,输入:ABCDEFGH#0,10,20,51,31,42,52,63,74,7-1,-1▪运行结果:2.指定从某个顶点开始进行深度优先搜索遍历和广度优先搜索遍历,把结果输出输入结果6 81 55 22 61 44 52 33 64 3输出结果1 4 32 5 6AB CD E F GH12345671 4 5 32 6▪实验小结:输出输入结果#include<stdio.h>定义函数库<stdio.h>便于后面程序中的函数可以被使用;#define N 20定义大写字母N为20是后面程序简洁并且提高运算效率;#define TRUE 1定义TRUE用1表示使得后面输出结果是简洁并且便于理解;#define FALSE 0定义FALSE用1表示使得后面输出结果是简洁并且便于理解;int visited[N];定义访问空间并且定义其大小为N;typedef struct建立队列结构体;{int data[N];初始化int类型数组;int front,rear;定义对头指针和队尾指针;}queue;队列结构建立完成;typedef struct建立矩阵结构体;{int vexnum,arcnum;定义顶点数和边数;char vexs[N];定义顶点数为一维数组;int arcs[N][N];定义边数为二维数组;}graph;void createGraph(graph *g);建立一个无向图的邻接矩阵;void dfs(int i,graph *g);从第i个顶点出发深度优先搜索,dfs表示深度优先搜索;void tdfs(graph *g);深度优先搜索整个图;void bfs(int k,graph *g);从第k个顶点出发广度优先搜索,bfs表示广度优先搜索;void tbfs(graph *g);广度优先搜索整个图;void init_visit();初始化访问标识数组;以上是对邻接矩阵的声明;void createGraph(graph *g)建立一个无向图的邻接矩阵;{int i,j;定义i与j两个整型值;char v;定义v字符变量;g->vexnum=0;g指针引用的顶点初始为0;g->arcnum=0;g指针引用的边数初始为0;i=0;i值初始为0;printf("输入顶点序列(以#结束):\n");printf()函数可以输出()中的标题提示语;while((v=getchar())!='#')while循环函数{g->vexs[i]=v;引用指针g指向顶点被赋值为v的一维数组;i++;让i值进行自加;}g->vexnum=i;引用指针g指向被赋值为i的顶点,顶点数目;for(i=0;i<g->vexnum;i++)for()使i值初始为0,当i值小于g,引用指针g指向的顶点并且i自加,邻接矩阵初始化;for(j=0;j<g->vexnum;j++)for()使j值初始为0,当j值小于g,引用指针g指向的顶点并且j自加,邻接矩阵初始化;g->arcs[i][j]=0; 引用指针g指向的边数的二维数组将其赋值为0表示没有连接;printf("输入边的信息:\n");提示输入语句;scanf("%d,%d",&i,&j);输入函数输入二个十进制的数字将其存入i与j的两个地址,读入边i,j;while(i!=-1)while循环当i读入i,j为-1时结束;{g->arcs[i][j]=1;引用指针g指向的边数的二维数组将其赋值为1表示有连接;g->arcs[j][i]=1;引用指针g指向的边数的二维数组对应另外点将其赋值为1表示有连接;scanf("%d,%d",&i,&j);输入二个十进制的数值并将其放在i与j两个地址中;}}以上是通广度优先和深度优先搜索遍历输出得到的矩阵;void dfs(int i,graph *g)从第i个顶点出发深度优先搜索(从顶点i出发对图进行dfs遍历),类似于树的先序遍历;{int j;定义整型量j;printf("%c",g->vexs[i]); 输出单字符指针顶点i;visited[i]=TRUE;修改顶点i的访问标志为TRUE;for(j=0;j<g->vexnum;j++)for()函数循环初始j值为0当j小于g所引用的顶点数值时对j进行自加;if((g->arcs[i][j]==1)&&(!visited[j]))如果同时满足g所引导的边数二维数组的值为1进行访问操作且对i的尚未访问的邻接顶点j递归调用dfs;dfs(j,g);则得到深度搜索的j值与g指针;}void tdfs(graph *g)深度优先搜索整个图;{int i;定义整型数值i;printf("\n从顶点%C开始深度优点搜索序列;”,g->vexs[0]);输出提示标语从顶点%C开始深度优点搜索序列for(i=0;i<g->vexnum;i++)for()循环初始i为0当i值小于指针g所引用的顶点时,对i进行自加进行访问操作;if(visited[i]!=TRUE)判断i的尚未访问的顶点是否被修改为TRUE;dfs(i,g);则得到深度搜索的i值与g指针;}void bfs(int k,graph *g)从第k个顶点出发广度优先搜索(从顶点k出发对图进行bfs遍历),类似于树的按层遍历,算法借助队列;{int i,j;定义两个整型变量i,j;queue qlist,*q;建立一个队列链表和一个指针;q=&qlist;将q赋值于一个链表地址;q->rear=0;q引用为队尾且队尾为空;q->front=0;q引用为队头且队头为空;printf("%c",g->vexs[k]);输出单字符指针顶点k;visited[k]=TRUE;修改顶点k的访问标志为TRUE;q->data[q->rear]=k;q引用为数据类型的队尾指针k;q->rear=(q->rear+1)%N;q引用为队尾的后一位;while(q->rear!=q->front)while循环q引用的队尾指针不等于q引用的队头指针;{i=q->data[q->front];i赋值为q引用为q引用对头指针的数据类型;q->front=(q->front+1)%N;q引用被赋值到下一位的队头指针且对其取余数操作;for(j=0;j<g->vexnum;j++)for()初始j为0当j小于g引用的顶点时对j进行自加便于完成对整的数据的计算;if((g->arcs[i][j]==1)&&(!visited[j]))如果g引用的二维数组的值为1并且对i的尚未访问的邻接顶点j递归调用bfs广度优先操作;{printf("%c",g->vexs[j]);输出g引用的一维数组的单个字符;visited[j]=TRUE;修改顶点访问指针为TRUE;q->data[q->rear]=j;将q引用为队尾指针数据j;q->rear=(q->rear+1)%N;将q引用为下一位队尾指针数据并且对其取余;}}}void tbfs(graph *g)广度优先搜索整个图;{int i;定义一个整型变量i;printf("\n从顶点%C开始广度优先搜索序列;”,g->vexs[0]);输出提示标语并且输出g引用的初始地址;for(i=0;i<g->vexnum;i++)for()循环i初始为0,当i小于顶点项目数时,变量i进行自加;if(visited[i]!=TRUE) 判断i的尚未访问的顶点是否被修改为TRUE递归调用bfs;bfs(i,g);得到i与g的结果遍历完成;}void init_visit()初始化访问标识数组;{int i;定义一个整型变量i;for(i=0;i<N;i++)for()循环初始i为0,当i小于数组所定义的长度时对i进行自加以达到完成整个数组的访问;visited[i]=FALSE;访问i未被访问的顶点;}int main()函数调用提高算法效率;{graph ga;矩阵ga建立声明;int i,j;定义两个整型变量;createGraph(&ga);创建矩阵并且创建了地址ga;printf(“无向图的邻接矩阵:\n”);输出提示语;for(i=0;i<ga.vexnum;i++)for()循环初始变量i为0,当变量i小于矩阵中顶点项目数时对i进行自加; {for(j=0;j<ga.vexnum;j++)for()循环j初始为0开始当j小于矩阵中顶点项目数时对j进行自加; printf("%3d",ga.arcs[i][j]);输出三位整数型数据分别是ga和二维数组中的数值;printf("\n");输出结果}init_visit();访问顶点;tdfs(&ga);深度优先遍历init_visit();访问顶点;tbfs(&ga);广度优先遍历;return 0;返回0算法结束;}。
实验报告:图的存储结构和遍历
武汉东湖学院
实验报告
学院:计算机科学学院专业计算机科学与技术2016年11月18日
姓名付磊学号2015040131042
班级计科一班指导老师吴佳芬
课程名称数据结构成
绩
实验名称图的存储结构和遍历
1.实验目的
(1)了解邻接矩阵存储法和邻接表存储法的实现过程。
(2)了解图的深度优先遍历和广度优先遍历的实现过程。
2.实验内容
1. 采用图的邻接矩阵存储方法,实现下图的邻接矩阵存储,并输出该矩阵.
2. 设计一个将第1小题中的邻接矩阵转换为邻接表的算法,并设计一个在屏幕上显示邻接表的算法
3. 实现基于第2小题中邻接表的深度优先遍历算法,并输出遍历序列
4. 实现基于第2小题中邻接表的广度优先遍历算法,并输出遍历序列
3.实验环境
Visual C++ 6.0
4.实验方法和步骤(含设计)
我们通过二维数组中的值来表示图中节点与节点的关系。
通过上图可知,其邻接矩阵示意图为如下:
V0 v1 v2 v3 v4 v5
V0 0 1 0 1 0 1
V1 1 0 1 1 1 0
V2 0 1 0 0 1 0
V3 1 1 0 0 1 1
V4 0 1 1 1 0 0
V5 1 0 0 1 0 0
此时的“1”表示这两个节点有关系,“0”表示这两个节点无关系。
我们通过邻接表来在计算机中存储图时,其邻接表存储图如下:
}。
数据结果实验图的表示与遍历 报告
实验课程名称数据结构实验项目名称图的表示与遍历年级 08 级 2 班专业数学类姓名学号理学院实验时间:学生实验室守则一、按教学安排准时到实验室上实验课,不得迟到、早退和旷课。
二、进入实验室必须遵守实验室的各项规章制度,保持室内安静、整洁,不准在室内打闹、喧哗、吸烟、吃食物、随地吐痰、乱扔杂物,不准做与实验内容无关的事,非实验用品一律不准带进实验室。
三、实验前必须做好预习(或按要求写好预习报告),未做预习者不准参加实验。
四、实验必须服从教师的安排和指导,认真按规程操作,未经教师允许不得擅自动用仪器设备,特别是与本实验无关的仪器设备和设施,如擅自动用或违反操作规程造成损坏,应按规定赔偿,严重者给予纪律处分。
五、实验中要节约水、电、气及其它消耗材料。
六、细心观察、如实记录实验现象和结果,不得抄袭或随意更改原始记录和数据,不得擅离操作岗位和干扰他人实验。
七、使用易燃、易爆、腐蚀性、有毒有害物品或接触带电设备进行实验,应特别注意规范操作,注意防护;若发生意外,要保持冷静,并及时向指导教师和管理人员报告,不得自行处理。
仪器设备发生故障和损坏,应立即停止实验,并主动向指导教师报告,不得自行拆卸查看和拼装。
八、实验完毕,应清理好实验仪器设备并放回原位,清扫好实验现场,经指导教师检查认可并将实验记录交指导教师检查签字后方可离去。
九、无故不参加实验者,应写出检查,提出申请并缴纳相应的实验费及材料消耗费,经批准后,方可补做。
十、自选实验,应事先预约,拟订出实验方案,经实验室主任同意后,在指导教师或实验技术人员的指导下进行。
十一、实验室内一切物品未经允许严禁带出室外,确需带出,必须经过批准并办理手续。
学生所在学院:理学院专业:数学类班级:08级(2)班姓名学号实验组实验时间指导教师成绩实验项目名称图的表示与遍历实验目的及要求:目的:(1)掌握邻接矩阵和邻接表存储一个图或网络;(2)学会图的DFS遍历和BFS遍历;(3)图的运用,最小生成树,拓扑排序,最短路径。
实验七 图
实验七图一、实验目的熟悉图的两种常用的存储结构,以及在这两种存储结构上的两种遍历图的方法,即深度优先遍历和广度优先遍历。
进一步掌握递归算法的设计方法。
关于各种典型著名的复杂算法,在上机实习方面不做基本要求。
更适合于安排大型课程设计。
二、实例1.图的邻接矩阵存储(数组表示)、简单输出。
本题的目的是给出一个无向图数组表示的简单启示,在此基础上稍加改动可以实现网(边上带权值的图)的邻接矩阵表示。
# include <stdio.h># include <stdlib.h># define MAX 20typedef int VexType;typedef VexType Mgraph[MAX][MAX]; /* Mgraph是二维数组类型标识符 *//* 函数原形声明 */void creat_mg(Mgraph G);void out_mg(Mgraph G);Mgraph G1; /* G1是邻接矩阵的二维数组名 */int n,e,v0;/* 主函数 */main(){ creat_mg(G1); out_mg(G1);}/* main *//* 建立邻接矩阵 */void creat_mg(Mgraph G){ int i,j,k;printf(“\n n,e=?”); scanf(“%d%d”, &n,&e); /* 输入顶点数n,边数e */for(i=1; i<=n;i++)for(j=1;j<=n;j++) G[i][j]=0;/* 如果是网,G[i][j]=0该为G[i][j]=32767(无穷)*/for(k=1;k<=e;k++) /* 组织边数的循环 */{ printf(“\n vi,vj=?”);scanf(“%d%d”, &i,&j); /* 输入一条边的两个顶点编号i,j */G[i][j]=1; G[j][i]=1; /* 无向图的邻接矩阵是对称矩阵 */ /* 如果是网,还要输入边的权值w,再让G[i][j]=w */}} /* creat_mg *//* 邻接矩阵简单输出,为了检查输入是否正确 */void out_mg(Mgraph G){ int i,j,k; char ch;for(i=1; i<=n;i++) /* 矩阵原样输出 */{ printf(“\n “);for(j=1;j<=n;j++) printf(“%5d”,G[i][j]);}/* 输出所存在的边 */for(i=1; i<=n;i++)for(j=1;j<=n;j++)if(G[i][j]==1)printf(“\n 存在边< %d,%d >”,i,j);printf("\n\n 打回车键,继续。
7图的遍历
数据结构
广度优先搜索算法
void BFSTraverse(Graph G, Status (* visit)(int v)) { for(v=0; v<G.vexnum; ++v) visited[v] = FALSE; IntiQueque(Q); for(v=0; v<G.vexnum; ++v) if(!visited[v]) { visited[v] = TRUE; Visit (v); EnQueue(Q,v); while(!QueueEmpty(Q)){ DeQueue(Q,u); for(w=FirstAdjVex(G, u);w;w = NextAdjVex(G,u,w)) if(!visited[w]) {visited[w]=TRUE; visited(w); EnQueue(G,w); } } } 7 数据结构 }
void DFSTree(Graph G,int v ,CSTree &T) { //从第 个顶点出发深度优先遍历图G 建立以T //从第v个顶点出发深度优先遍历图G,建立以T为根的生成 从第v 树 visited[v]=TRUE; first=TRUE; for(w=FirstAdjVex(G,v);w>=0; w=NextAdjVex(G,v,w)) if(!visited[w]) p=(CSTree)malloc(sizeof)CSNode));//分配孩子结点 { p=(CSTree)malloc(sizeof)CSNode));//分配孩子结点 *p={GetVex(G,w),NULL,NULL}; //w 的第一个未被访问的邻接顶点, if (first) //w是v的第一个未被访问的邻接顶点,作 为 根的左孩子结点 T{ T->lchild=p; first=FALSE; } //w 的其它未被访问的邻接顶点, else { //w是v的其它未被访问的邻接顶点,作为上一 邻 接顶点的右兄弟 q->nextsibling=p; } q=p; D 从第w //从第 DFSTree(G,w,q); //从第w个顶点出发深度优先遍历 A 图 G,建立生成子树q 建立生成子树q 12 数据结构 B C E }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验五图的表示与遍历一、实验目的1、掌握图的邻接矩阵和邻接表表示2、掌握图的深度优先和广度优先搜索方法3、理解图的应用方法二、实验预习说明以下概念1、深度优先搜索遍历:从根开始一个一个搜索2、广度优先搜索遍历:从根的邻接点出发依次访问3、拓扑排序:一个无指向的点开始排序4、最小生成树:最小权的生成树5、最短路径:路径权数最小三、实验内容和要求1、阅读并运行下面程序,根据输入写出运行结果。
#include<stdio.h>#define N 20#define TRUE 1#define FALSE 0int visited[N];typedef struct /*队列的定义*/{int data[N];int front,rear;}queue;typedef struct /*图的邻接矩阵*/{int vexnum,arcnum;char vexs[N];int arcs[N][N];}graph;void createGraph(graph *g); /*建立一个无向图的邻接矩阵*/ void dfs(int i,graph *g); /*从第i个顶点出发深度优先搜索*/void tdfs(graph *g); /*深度优先搜索整个图*/void bfs(int k,graph *g); /*从第k个顶点广度优先搜索*/ void tbfs(graph *g); /*广度优先搜索整个图*/void init_visit(); /*初始化访问标识数组*/void createGraph(graph *g) /*建立一个无向图的邻接矩阵*/ { int i,j;char v;g->vexnum=0;g->arcnum=0;i=0;printf("输入顶点序列(以#结束):\n");while((v=getchar())!='#'){g->vexs[i]=v; /*读入顶点信息*/i++;}g->vexnum=i; /*顶点数目*/for(i=0;i<g->vexnum;i++) /*邻接矩阵初始化*/for(j=0;j<g->vexnum;j++)g->arcs[i][j]=0;printf("输入边的信息:\n");scanf("%d,%d",&i,&j); /*读入边i,j*/while(i!=-1) /*读入i,j为-1时结束*/{g->arcs[i][j]=1;g->arcs[j][i]=1;scanf("%d,%d",&i,&j);}}void dfs(int i,graph *g) /*从第i个顶点出发深度优先搜索*/ {int j;printf("%c",g->vexs[i]);visited[i]=TRUE;for(j=0;j<g->vexnum;j++)if((g->arcs[i][j]==1)&&(!visited[j]))dfs(j,g);}void tdfs(graph *g) /*深度优先搜索整个图*/{int i;printf("\n从顶点%C开始深度优先搜索序列:",g->vexs[0]); for(i=0;i<g->vexnum;i++)if(visited[i]!=TRUE)dfs(i,g);}void bfs(int k,graph *g) /*从第k个顶点广度优先搜索*/{int i,j;queue qlist,*q;q=&qlist;q->rear=0;q->front=0;printf("%c",g->vexs[k]);visited[k]=TRUE;q->data[q->rear]=k;q->rear=(q->rear+1)%N;while(q->rear!=q->front){i=q->data[q->front];q->front=(q->front+1)%N;for(j=0;j<g->vexnum;j++)if((g->arcs[i][j]==1)&&(!visited[j])){printf("%c",g->vexs[j]);visited[j]=TRUE;q->data[q->rear]=j;q->rear=(q->rear+1)%N;}}}void tbfs(graph *g) /*广度优先搜索整个图*/{int i;printf("\n从顶点%C开始广度优先搜索序列:",g->vexs[0]); for(i=0;i<g->vexnum;i++)if(visited[i]!=TRUE)bfs(i,g);}void init_visit() /*初始化访问标识数组*/{int i;for(i=0;i<N;i++)visited[i]=FALSE;}int main(){graph ga;int i,j;createGraph(&ga);printf("无向图的邻接矩阵:\n");for(i=0;i<ga.vexnum;i++){for(j=0;j<ga.vexnum;j++)printf("%3d",ga.arcs[i][j]); printf("\n");}init_visit();tdfs(&ga);init_visit();tbfs(&ga);return 0;}▪根据右图的结构验证实验,输入:ABCDEFGH#0,10,20,51,31,42,52,63,74,7-1,-1▪运行结果:362、阅读并运行下面程序,补充拓扑排序算法。
#include<stdio.h>#include<malloc.h>#define N 20typedef struct edgenode{ /*图的邻接表:邻接链表结点*/int adjvex; /*顶点序号*/struct edgenode *next; /*下一个结点的指针*/}edgenode;typedef struct vnode{ /*图的邻接表:邻接表*/char data; /*顶点信息*/int ind; /*顶点入度*/struct edgenode *link; /*指向邻接链表指针*/}vnode;void createGraph_list(vnode adjlist[],int *p); /*建立有向图的邻接表*/ void topSort(vnode g[],int n); /*拓扑排序*/void createGraph_list(vnode adjlist[],int *p){ /*建立有向图的邻接表*/ int i,j,n,e;char v;edgenode *s;i=0;n=0;e=0;printf("输入顶点序列(以#结束):\n");while((v=getchar())!='#'){adjlist[i].data=v; /*读入顶点信息*/adjlist[i].link=NULL;adjlist[i].ind=0;i++;}n=i;*p=n;/*建立邻接链表*/printf("\n请输入弧的信息(i=-1结束):i,j:\n");scanf("%d,%d",&i,&j);while(i!=-1){s=(struct edgenode*)malloc(sizeof(edgenode));s->adjvex=j;s->next=adjlist[i].link;adjlist[i].link=s;adjlist[j].ind++; /*顶点j的入度加1*/e++;scanf("%d,%d",&i,&j);}printf("邻接表:");for(i=0;i<n;i++){ /*输出邻接表*/printf("\n%c,%d:",adjlist[i].data,adjlist[i].ind); s=adjlist[i].link;while(s!=NULL){printf("->%d",s->adjvex);s=s->next;}}}void topSort(vnode g[],int n){ /*拓扑排序*/}int main(){vnode adjlist[N];int n,*p;p=&n;createGraph_list(adjlist,p);return 0;}▪根据输入,输出有向图的拓扑排序序列。
并画出有向图。
输入: ABCDEF#0,11,22,34,14,5-1,-1▪运行结果:3、阅读并运行下面程序。
#include<stdio.h>#define N 20#define TRUE 1#define INF 32766 /*邻接矩阵中的无穷大元素*/ #define INFIN 32767 /*比无穷大元素大的数*/typedef struct{ /*图的邻接矩阵*/int vexnum,arcnum;char vexs[N];int arcs[N][N];}graph;void createGraph_w(graph *g,int flag);void prim(graph *g,int u);void dijkstra(graph g,int v);void showprim();void showdij();/*建带权图的邻接矩阵,若flag为1则为无向图,flag为0为有向图*/ void createGraph_w(graph *g,int flag){int i,j,w;char v;g->vexnum=0;g->arcnum=0;i=0;printf("输入顶点序列(以#结束):\n");while((v=getchar())!='#'){g->vexs[i]=v; /*读入顶点信息*/i++;}g->vexnum=i;for(i=0;i<6;i++) /*邻接矩阵初始化*/for(j=0;j<6;j++)g->arcs[i][j]=INF;printf("输入边的信息:\n");scanf("%d,%d,%d",&i,&j,&w); /*读入边(i,j,w)*/while(i!=-1) /*读入i为-1时结束*/{g->arcs[i][j]=w;if(flag==1)g->arcs[j][i]=w;scanf("%d,%d,%d",&i,&j,&w);}}void prim(graph *g,int u)/*出发顶点u*/{int lowcost[N],closest[N],i,j,k,min;for(i=0;i<g->vexnum;i++) /*求其他顶点到出发顶点u的权*/{lowcost[i]=g->arcs[u][i];closest[i]=u;}lowcost[u]=0;for(i=1;i<g->vexnum;i++) /*循环求最小生成树中的各条边*/{ min=INFIN;for(j=0;j<g->vexnum;j++) /*选择得到一条代价最小的边*/if(lowcost[j]!=0&&lowcost[j]<min){min=lowcost[j];k=j;}printf("(%c,%c)--%d\n",g->vexs[closest[k]],g->vexs[k],lowcost[k]); /*输出该边*/lowcost[k]=0; /*顶点k纳入最小生成树 */for(j=0;j<g->vexnum;j++) /*求其他顶点到顶点k 的权*/if(g->arcs[k][j]!=0&&g->arcs[k][j]<lowcost[j]){lowcost[j]=g->arcs[k][j];closest[j]=k;}}}void printPath(graph g,int startVex,int EndVex){int stack[N],top=0; /*堆栈*/int i,k,j;int flag[N]; /*输出路径顶点标志*/k=EndVex;for (i=0;i<g.vexnum;i++) flag[i]=0;j=startVex;printf("%c",g.vexs[j]);flag[j]=1;stack[top++]=k;while (top>0) /*找j到k的路径*/{for (i=0;i<g.vexnum;i++){if (path[k][i]==1 && flag[i]==0) /*j到k的路径含有i顶点*/ {if (g.arcs[j][i]!=INF ) /*j到i的路径含有中间顶点*/{printf("-> %c(%d) ",g.vexs[i],g.arcs[j][i]);/*输出j到k的路径的顶点i*/flag[i]=1;j=i;k=stack[--top];break;}else{if (i!=k) stack[top++]=i; /*break;*/}}}}void dijkstra(graph g,int v){ /*dijkstra算法求单源最短路径*/int path[N][N],dist[N],s[N];int mindis,i,j,u,k;for(i=0;i<g.vexnum;i++){dist[i]=g.arcs[v][i];s[i]=0;for(j=0;j<g.vexnum;j++)path[i][j]=0;if(dist[i]<INF){path[i][v]=1;path[i][i]=1;}}dist[v]=0;s[v]=1;for(i=0,u=1;i<g.vexnum;i++){mindis=INFIN;for(j=0;j<g.vexnum;j++)if(s[j]==0)if(dist[j]<mindis){u=j;mindis=dist[j];}s[u]=1;for(j=0;j<g.vexnum;j++)if((s[j]==0)&&dist[u]+g.arcs[u][j]<dist[j]){dist[j]=dist[u]+g.arcs[u][j];for(k=0;k<g.vexnum;k++)path[j][k]=path[u][k];path[j][j]=1;}}printf("\n顶点%c->到各顶点的最短路径\n",g.vexs[v]);for(i=0;i<g.vexnum;i++){printf("\n顶点%c->顶点%c:",g.vexs[v],g.vexs[i]);if(dist[i]==INF||dist[i]==0)printf("无路径");else{printf("%d ",dist[i]);printf("经过顶点:");printPath(g,v,i); /*输出v到i的路径*/}}}void showprim()/*最小生成树prim算法演示*/{graph ga;createGraph_w(&ga,1);prim(&ga,0);}void showdij(){ /*dijstra算法演示*/graph ga;createGraph_w(&ga,0);dijkstra(ga,0);}int main(){showprim(); /*prim算法演示*/getchar();showdij(); /*dijstra算法演示*/return 0;}▪下面的输入分别验证prim算法和dijstra算法。