数据结构实验报告(三):实现深度优先搜索与广度优先搜索算法

合集下载

数据结构实验报告(三):实现深度优先搜索与广度优先搜索算法

数据结构实验报告(三):实现深度优先搜索与广度优先搜索算法

佛山科学技术学院实验报告课程名称数据结构实验项目实现深度优先搜索与广度优先搜索算法专业班级 10网络工程2 姓名张珂卿学号 2010394212指导教师成绩日期 2011年11月16日一、实验目的1、通过本实验,掌握图,无向图的基本概念,掌握图的遍历;2、掌握图的深度优先搜索(DFS)与广度优先搜索(BFS)算法。

二、实验内容1、建立图的存储方式;2、图的深度优先搜索算法;3、图的广度优先搜索算法。

三、实验原理图的遍历是图的算法中一种非常重要的算法,通过建立图的存储结构,采用深度优先搜索与广度优先搜索算法可以进行图的遍历;深度优先遍历是树的先根遍历的推广,是将某一条枝上的所有节点都搜索到了之后,才转向搜索另一条枝上的所有节点;广度优先遍历与深度优先遍历的区别在于:广度优先遍历是以层为顺序,将某一层上的所有节点都搜索到了之后才向下一层搜索。

四、实验步骤1.建立图的存储结构;2.输入图的基本接点与信息,初始化图;3.编写图的深度优先搜索(DFS)和广度优先搜索算法(BFS)程序;4.采用菜单形式进行显示与选择。

5.测试数据和结果显示(1)从键盘输入顶点数和边数;(2)输入顶点信息;(3)输入边的信息,以(a,b)的形式输入边的信息,构建一个无向图;(4)对此无向图进行深度优先搜索和广度优先搜索,并输出正确的序列。

五、程序源代码及注释/********************************采用邻接表的存储结构*构建无向图*图的创建过程中暂不支持重复验证,因此不能对一条边进行重复定义******************************/#include<stdio.h>#include<malloc.h>#include<windows.h>#define MAX_VERTEX_NUM 20typedef struct ArcNode{int adjvex;struct ArcNode* nextarc;//InfoType* info;}ArcNode;/**********************************链表结点的结构用于创建栈或是队列********************************/typedef struct LinkNode{ArcNode* parc; //存储指针地址struct LinkNode* next; //指向一下个结点}LinkNode;typedef struct VNode{char cData; //顶点元素值ArcNode* firstarc; //指向第一条依附于该点的边}VNode,AdjList[MAX_VERTEX_NUM];typedef struct {AdjList vertices;int vexnum; //图的当前顶点数和弧数int arcnum;}ALGraph;int Visited[MAX_VERTEX_NUM];/**********************************将生成的图打印出来以便确认正确性********************************/int PrintCheck(ALGraph* pag){int i;ArcNode* p;printf("\nCheck the Graph!\n");printf("No\tdata\tnext\tnext\t.....\n");for(i=0; i<pag->vexnum; i++){printf("%d\t%c\t",i,pag->vertices[i].cData);p = pag->vertices[i].firstarc;while(p){printf("%d\t",p->adjvex);p = p->nextarc;}printf("\n");}return 1;}/***************************采用前插法创建邻接表*************************/int CreateGraph(ALGraph* pag,int start,int end){ArcNode* arcNodes = (ArcNode*)malloc(sizeof(ArcNode));ArcNode* arcNodee = (ArcNode*)malloc(sizeof(ArcNode));ArcNode* p;if(!arcNodes || !arcNodee) return 0;//从start->end生成关系arcNodes->adjvex = end; //下一结点的位置p = pag->vertices[start].firstarc;if(!p) //第一个结点单独构造{arcNodes->nextarc = pag->vertices[start].firstarc;pag->vertices[start].firstarc = arcNodes;}else{while(p->nextarc) p = p->nextarc;p->nextarc = arcNodes;arcNodes->nextarc = NULL;}//end->start 的关系生成arcNodee->adjvex = start; //下一结点的位置p = pag->vertices[end].firstarc;if(!p) //第一个结点单独构造{arcNodee->nextarc = pag->vertices[end].firstarc;pag->vertices[end].firstarc = arcNodee;}else{while(p->nextarc) p = p->nextarc;p->nextarc = arcNodee;arcNodee->nextarc = NULL;}return 1;}/*****************************************深度优先遍历,非递归方式*结点先访问再入栈*栈的存储结构直接采用了LinkNode构成的链表*采用前插法进行插入与删除,从而也可以完成栈的功能*栈空条件 Stack->next == NULL***************************************/void DFSTraverse(ALGraph ag,int start){LinkNode* Stack = (LinkNode*)malloc(sizeof(LinkNode)); //链表头结点,用做栈LinkNode* pStack = (LinkNode*)malloc(sizeof(LinkNode)); //对栈操作的指针LinkNode* temp; //临时存储ArcNode* p;int i;if(!pStack||!Stack) return;Stack->next = NULL;p = ag.vertices[start].firstarc;Visited[start]=1; //Flagprintf("\n输出深度优先遍历顺序:");printf(" %c ",ag.vertices[start].cData); //访问第一个点while(1) //正常情况下执行一次,为了打印孤立结点{//push stackpStack->parc = p;pStack->next = Stack->next; //将p接入链式栈中Stack->next = pStack;//push overwhile(p && (Stack->next)) //当并且栈不为空时{while(p){if(Visited[p->adjvex]) p = p->nextarc;else{Visited[p->adjvex]=1;printf(" %c ",ag.vertices[p->adjvex].cData); //Visit Function//push stackpStack = (LinkNode*)malloc(sizeof(LinkNode));if(!pStack) return; //结点建立不成功pStack->parc = p;pStack->next = Stack->next;Stack->next = pStack;//push overp = ag.vertices[p->adjvex].firstarc;}}//pop stacktemp = Stack->next;Stack->next = temp->next;p = temp->parc->nextarc;free(temp);//pop over}for(i=0; i<ag.vexnum; i++) //打印出孤立点{if(!Visited[i]) printf(" %c ",ag.vertices[i].cData);p = ag.vertices[i].firstarc;}if(i = ag.vexnum) break;}printf("\n\n");};/*****************************************广度优先遍历,非递归方式*队列的存储结构直接采用了LinkNode构成的链表*采用后接法进行插入,并用前插法进行删除*从而完成队列的功能,队空条件Queue->next == NULL***************************************/void BFSTraverse(ALGraph ag,int start){LinkNode* Queue = (LinkNode*)malloc(sizeof(LinkNode)); //链表头结点,用做队列LinkNode* pQueue = (LinkNode*)malloc(sizeof(LinkNode)); //对队列操作的指针LinkNode* temp; //临时存储LinkNode* last; //指向最后一个元素的指针ArcNode* p;int i;if(!Queue || !pQueue) return;printf("\n输出广度优先遍历次序:");printf(" %c ",ag.vertices[start].cData);p = ag.vertices[start].firstarc;Visited[start] = 1;while(1) //正常情况下执行一次循环{//EnQueuepQueue->parc = p;Queue->next = pQueue;pQueue->next = NULL;last = pQueue; //指向最后一个元素的指针//EnQueue overwhile(p && Queue->next){while(p){if(!Visited[p->adjvex]){Visited[p->adjvex] = 1;printf(" %c ",ag.vertices[p->adjvex].cData); //Visit Function//EnQueuepQueue = (LinkNode*)malloc(sizeof(LinkNode));if(!pQueue) return;pQueue->parc = p;pQueue->next = NULL;last->next = pQueue;last = last->next; //指向最后一个元素的指针//EnQueue over}p = p->nextarc;}//DeQueuetemp = Queue->next;p = ag.vertices[temp->parc->adjvex].firstarc;Queue ->next = temp->next;//DeQueue over}for(i=0; i<ag.vexnum; i++) //打印出孤立点{if(!Visited[i]) printf(" %c ",ag.vertices[i].cData);p = ag.vertices[i].firstarc;}if(i = ag.vexnum) break;}printf("\n\n");}/*******************************************主函数负责对图的初始化工作*其中包括图的结点初始化,边初始化*其中大部分的while(1)语句用于验证输入数据的有效性******************************************/void main(){ALGraph ag;int i,n,m;int choose; //选择遍历结点int start,end; //边的起点与终点的位置printf("说明: 采用邻接表的存储结构,生成无向图\n 输入数据请回车确认\n\n");while(1) //结点个数有效性验证{printf("请输入图的结点个数,并回车: ");scanf("%d",&n);if(n<MAX_VERTEX_NUM && n>0) break;else printf("\n请注意结点个数不能大于20,并且不能为0!\n");}ag.vexnum = n;printf("\n初始化图的结点,输入字符并回车:\n");for(i=0; i<ag.vexnum; i++) //图的结点数据{printf("No.%d = ",i);fflush(stdin);scanf("%c",&ag.vertices[i].cData);ag.vertices[i].firstarc = NULL;}m = (n-2)*(n+1)/2+1; //顶点数为n的图最多的边的数量为mwhile(1) //边的数量有效性验证{printf("请输入边的数量: ");fflush(stdin);scanf("%d",&i);if(i<=m && i>=0) break;else printf("\n请注意边的数量不能大于%d,并且不能小于1!\n",m); }ag.arcnum = i;printf("\n初始化图的边,结点从0开始计,最大为%d\n",n-1);for(i=1; i<=ag.arcnum; i++){while(1) //起点有效性验证{printf("第<%d>条边的起点: ",i);fflush(stdin);scanf("%d",&start);if(start<n&&start>=0) break;else printf("重新输入 ");}while(1) //终点有效性验证{printf("第<%d>条边的终点: ",i);fflush(stdin);scanf("%d",&end);if(end<n && end>=0 && end!=start) break;else printf("重新输入 ");}printf("\n");CreateGraph(&ag,start,end);}PrintCheck(&ag); //打印出生成的图printf("\n开始进行图的遍历!\n");while(1) //起始点有效性验证{printf("请输入深度优先遍历的开始结点:");fflush(stdin);scanf("%d",&choose);if(choose>=0 && choose<n) break;else printf("重新输入 ");}DFSTraverse(ag,choose); //深度优先遍历i = 0; //重新初始化Visited数组while(Visited[i]!='\0'){Visited[i] = 0;i++;}while(1) //起始点有效性验证{printf("请输入广度优先遍历的开始结点:");fflush(stdin);scanf("%d",&choose);if(choose>=0 && choose<n) break;else printf("重新输入 ");}BFSTraverse(ag,choose); //广度优先遍历system("pause");}程序运行截图六、实验体会这堂实现深度优先搜索与广度优先搜索算法的数据结构实验课难度明显比第二节课要大许多,刚开始有些丈二摸不着头脑,浪费了不少课上的时间,后来回去才慢慢深入,一点点了解了这堂课的内容,经历过不少错误之后,终于算是掌握了图,无向图的基本概念,掌握图的遍历,还有图的深度优先搜索(DFS)与广度优先搜索(BFS)算法。

的遍历算法深度优先搜索与广度优先搜索的实现与应用

的遍历算法深度优先搜索与广度优先搜索的实现与应用

的遍历算法深度优先搜索与广度优先搜索的实现与应用遍历算法是计算机科学中常用的一种算法,其作用是按照一定的规则,对数据结构中的每个节点进行访问,以达到查找、遍历或搜索的目的。

在遍历算法中,深度优先搜索(Depth First Search,简称DFS)和广度优先搜索(Breadth First Search,简称BFS)是两种常见的策略。

它们分别以不同的顺序访问节点,并且在实际应用中具有各自的优势和局限性。

一、深度优先搜索深度优先搜索是一种采用堆栈(Stack)的先进后出策略,将节点的全部子节点遍历完毕后再回溯到上层节点进行进一步的遍历。

通过这种方式,深度优先搜索能够较快地到达树的叶子节点,并可以在较短时间内找到一条从根节点到达目标节点的路径。

深度优先搜索的实现可以使用递归或者显式模拟栈来完成。

下面是一个使用递归实现深度优先搜索的示例:```pythondef dfs(node):if node is None:return# 访问节点visit(node)# 递归遍历子节点for child in node.children:dfs(child)```深度优先搜索广泛应用于图的遍历、迷宫求解、拓扑排序等场景。

由于其递归的特性,深度优先搜索可能会导致堆栈溢出问题,因此在处理大规模数据时需要注意栈空间的限制。

二、广度优先搜索广度优先搜索是一种采用队列(Queue)的先进先出策略,从根节点开始逐层遍历,先访问离根节点最近的节点,再访问离根节点更远的节点。

通过这种方式,广度优先搜索能够逐层地向外扩展,并可以在较短时间内找到根节点到目标节点的最短路径。

广度优先搜索的实现需要使用队列来保存待访问的节点。

下面是一个使用队列实现广度优先搜索的示例:```pythondef bfs(node):if node is None:returnqueue = []# 将根节点入队queue.append(node)while queue:# 出队节点curr_node = queue.pop(0)# 访问节点visit(curr_node)# 将子节点入队for child in curr_node.children:queue.append(child)```广度优先搜索常用于寻找最短路径、社交网络分析等场景。

实验三 图的广度优先遍历和深度优先遍历算法的设计

实验三 图的广度优先遍历和深度优先遍历算法的设计

实验三 图的广度优先遍历和深度优先遍历算法的设计一、实验目的本实验的目的是通过理解图的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。

二、实验内容1.分别编写BFS 、DFS 算法。

2.判断无向图G 是否连通,若连通则返回1,否则返回0。

3.判断无向图G 是否是一棵树。

若是树,返回1;否则返回0。

4.判断有向图中是否存在回路。

5.假设图G 采用邻接表存储,求距离顶点vO 的最短路径长度为k 的所有顶点,要求尽可能节省 时间。

三、实验类型验证性四、实验要求和提示1.实验前充分预习实验指导书内容及相关理论知识内容:实验中严格遵守实验室规范和制度,认真完成实验内容并做好实验纪录:实验后必须按照要求独立完成实验报告。

2.以上6个题中,题1是必做题,题2—5可任意选作l 或2题。

3.提示:(1)最好使用邻接表法建立无向图和有向图的存储结构,然后实现图的遍历。

(2)结点结构:typedef struct node{ int adjvex ; //邻接点域,存放与Vi 邻接的结点在表头数组中的位置 struct node * next ; //链域,指示下一条边或弧)JD :表头接点:typedef struct tnode{ int vexdata ;//存放顶点信息struct node *firstarc ;//指示第一个邻接点}TD ;4.程序实现方面的提示:(1)可采用遍历方式判断无向图是否连通。

先给visited[]数组置初值O,然后从O 开始遍历该图,之后若所有顶点i的visited[i]均为1,则该图是连通的,否则不连通。

(2)一个无向图G是一棵树的条件是:G必须是无回路的连通图或者是有n—l条边的连通图(注:本题可以只给出算法)(3)判断有向图中是否存在回路时,若一个有向图拓扑排序不成功,则一定存在回路;反之,若拓扑排序成功,则一定不存在回路。

(3)采用宽度优先搜索方法,找出第k层的所有顶点即为所求(宽度优先搜索保证找到的路径是最短路径)。

图的遍历的实验报告

图的遍历的实验报告

图的遍历的实验报告图的遍历的实验报告一、引言图是一种常见的数据结构,它由一组节点和连接这些节点的边组成。

图的遍历是指从图中的某个节点出发,按照一定的规则依次访问图中的所有节点。

图的遍历在许多实际问题中都有广泛的应用,例如社交网络分析、路线规划等。

本实验旨在通过实际操作,深入理解图的遍历算法的原理和应用。

二、实验目的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算法需要保存所有已访问过的节点。

实现深度优先搜索和广度优先搜索算法

实现深度优先搜索和广度优先搜索算法

实现深度优先搜索和广度优先搜索算法深度优先(DFS)和广度优先(BFS)是两种最常用的图遍历算法。

它们在图中寻找路径或解决问题时非常有用。

以下是DFS和BFS算法的实现以及它们的应用场景。

首先,我们来实现DFS算法。

深度优先(DFS)是一种不断沿着图的深度方向遍历的算法。

DFS使用堆栈来跟踪遍历的路径。

下面是DFS算法的实现步骤:1.选择一个起始顶点作为当前顶点,并将其标记为已访问。

2.检查当前顶点的邻居顶点:-如果邻居顶点未被访问,则将其标记为已访问,并将其入栈。

-如果邻居顶点已被访问,则继续检查下一个邻居顶点。

3.如果当前顶点没有未访问的邻居顶点,则出栈一个顶点作为新的当前顶点。

4.重复步骤2和步骤3,直到栈为空。

下面是DFS算法的Python实现:```pythondef dfs(graph, start):visited = set( # 用于存储已访问的顶点stack = [start] # 用于存储待访问的顶点while stack:vertex = stack.popif vertex not in visited:visited.add(vertex)for neighbor in graph[vertex]:stack.append(neighbor)return visited```接下来,我们来实现BFS算法。

广度优先(BFS)是一种逐层遍历图的算法。

BFS使用队列来跟踪遍历的顺序。

下面是BFS算法的实现步骤:1.选择一个起始顶点作为当前顶点,并将其标记为已访问。

2.将当前顶点入队。

3.检查队列中下一个顶点的邻居顶点:-如果邻居顶点未被访问,则将其标记为已访问,并将其入队。

-如果邻居顶点已被访问,则继续检查下一个邻居顶点。

4.重复步骤3,直到队列为空。

下面是BFS算法的Python实现:```pythonfrom collections import dequedef bfs(graph, start):visited = set( # 用于存储已访问的顶点queue = deque([start]) # 用于存储待访问的顶点while queue:vertex = queue.popleftif vertex not in visited:visited.add(vertex)for neighbor in graph[vertex]:queue.append(neighbor)return visited```DFS和BFS算法在许多问题和应用场景中都有广泛的应用。

深度优先搜索实验报告

深度优先搜索实验报告

深度优先搜索实验报告引言深度优先搜索(Depth First Search,DFS)是图论中的一种重要算法,主要用于遍历和搜索图的节点。

在实际应用中,DFS被广泛用于解决迷宫问题、图的连通性问题等,具有较高的实用性和性能。

本实验旨在通过实际编程实现深度优先搜索算法,并通过实际案例验证其正确性和效率。

实验中我们将以迷宫问题为例,使用深度优先搜索算法寻找从入口到出口的路径。

实验过程实验准备在开始实验之前,我们需要准备一些必要的工具和数据。

1. 编程环境:我们选择使用Python语言进行编程实验,因其语法简洁而强大的数据处理能力。

2. 迷宫地图:我们需要设计一个迷宫地图,包含迷宫的入口和出口,以及迷宫的各个路径和墙壁。

实验步骤1. 首先,我们需要将迷宫地图转化为计算机可处理的数据结构。

我们选择使用二维数组表示迷宫地图,其中0表示墙壁,1表示路径。

2. 接着,我们将编写深度优先搜索算法的实现。

在DFS函数中,我们将使用递归的方式遍历迷宫地图的所有路径,直到找到出口或者遇到墙壁。

3. 在每次遍历时,我们将记录已经访问过的路径,以防止重复访问。

4. 当找到出口时,我们将输出找到的路径,并计算路径的长度。

实验结果经过实验,我们成功地实现了深度优先搜索算法,并在迷宫地图上进行了测试。

以下是我们的实验结果:迷宫地图:1 1 1 1 11 0 0 0 11 1 1 0 11 0 0 0 11 1 1 1 1最短路径及长度:(1, 1) -> (1, 2) -> (1, 3) -> (1, 4) -> (2, 4) -> (3, 4) -> (4, 4) -> (5, 4)路径长度:7从实验结果可以看出,深度优先搜索算法能够准确地找到从入口到出口的最短路径,并输出了路径的长度。

实验分析我们通过本实验验证了深度优先搜索算法的正确性和有效性。

然而,深度优先搜索算法也存在一些缺点:1. 只能找到路径的一种解,不能确定是否为最优解。

数据结构与算法实验报告 图的深度优先与广度优先遍历

数据结构与算法实验报告 图的深度优先与广度优先遍历
if(visited[w]==0){
visit(w);
EnQueue(q,w);
visited[w]=1;
}
w=NextAdj(g,v);
}
}
}
void Travel_BFS(VNode g[],int visited[],int n){
int i;
for(i=0;i<n;i++){
visited[i]=0;
vertexType data;
Arcnode *firstarc;
}VNode;
//VNode G[MAX_VERTEX_NUM];
void getdata(VNode v);
//图的创建
void createGraph(int n,VNode G[]){
int i,e;
Arcnode *p,*q;
scanf("%d",&e);
while(e!=-1){
p=(Arcnode *)malloc(sizeof(Arcnode));
p->next=NULL;
p->adjvex=e;
if(G[i].firstarc==NULL){
G[i].firstarc=p;
}else{
q->next=p;
}
q=p;
}
}
//图的遍历(2)--广度优先搜索
void BFS(VNode G[],int v,int visited[]){
int w;
visit(v);
visited[v]=1;
EnQueue(q,v);
while(!emptyA(q)){
Dequeue(&q,&v);

广度优先实验报告

广度优先实验报告

一、实验目的1. 了解广度优先搜索(BFS)算法的基本原理和步骤。

2. 掌握使用广度优先搜索算法解决图的遍历问题的方法。

3. 比较广度优先搜索算法与深度优先搜索算法的优缺点。

二、实验原理广度优先搜索(BFS)是一种图遍历算法,它按照从源点到目标点的距离来搜索图中的节点。

在BFS中,算法首先访问源点,然后将其邻接点按照距离顺序访问,接着访问邻接点的邻接点,以此类推,直到找到目标点或遍历完所有节点。

BFS算法的基本步骤如下:1. 创建一个队列,用于存储待访问的节点。

2. 将源点入队。

3. 当队列不为空时,执行以下操作:a. 从队列中取出一个节点,访问它。

b. 将该节点的邻接点按照距离顺序入队。

4. 重复步骤3,直到找到目标点或遍历完所有节点。

三、实验环境与工具1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 20194. 图表示方法:邻接表四、实验内容与步骤1. 创建一个图的邻接表表示。

2. 使用广度优先搜索算法遍历图,并记录遍历过程。

3. 比较广度优先搜索算法与深度优先搜索算法的遍历结果。

五、实验结果与分析1. 实验结果以下是一个图的邻接表表示,以及使用广度优先搜索算法遍历图的结果:```图:A --B -- C| |D --E -- F邻接表表示:Graph g;g.addVertex('A');g.addVertex('B');g.addVertex('C');g.addVertex('D');g.addVertex('E');g.addVertex('F');g.addEdge('A', 'B');g.addEdge('B', 'C');g.addEdge('A', 'D');g.addEdge('D', 'E');g.addEdge('E', 'F');g.addEdge('B', 'E');g.addEdge('E', 'F');广度优先搜索遍历结果:A ->B ->C ->D ->E -> F```2. 分析(1)广度优先搜索算法的优点:- 按照距离顺序遍历图中的节点,便于理解节点之间的层次关系。

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

佛山科学技术学院实验报告课程名称数据结构实验项目实现深度优先搜索与广度优先搜索算法专业班级 10网络工程2 姓名张珂卿学号 2010394212指导教师成绩日期 2011年11月16日一、实验目的1、通过本实验,掌握图,无向图的基本概念,掌握图的遍历;2、掌握图的深度优先搜索(DFS)与广度优先搜索(BFS)算法。

二、实验内容1、建立图的存储方式;2、图的深度优先搜索算法;3、图的广度优先搜索算法。

三、实验原理图的遍历是图的算法中一种非常重要的算法,通过建立图的存储结构,采用深度优先搜索与广度优先搜索算法可以进行图的遍历;深度优先遍历是树的先根遍历的推广,是将某一条枝上的所有节点都搜索到了之后,才转向搜索另一条枝上的所有节点;广度优先遍历与深度优先遍历的区别在于:广度优先遍历是以层为顺序,将某一层上的所有节点都搜索到了之后才向下一层搜索。

四、实验步骤1.建立图的存储结构;2.输入图的基本接点与信息,初始化图;3.编写图的深度优先搜索(DFS)和广度优先搜索算法(BFS)程序;4.采用菜单形式进行显示与选择。

5.测试数据和结果显示(1)从键盘输入顶点数和边数;(2)输入顶点信息;(3)输入边的信息,以(a,b)的形式输入边的信息,构建一个无向图;(4)对此无向图进行深度优先搜索和广度优先搜索,并输出正确的序列。

五、程序源代码及注释/********************************采用邻接表的存储结构*构建无向图*图的创建过程中暂不支持重复验证,因此不能对一条边进行重复定义******************************/#include<stdio.h>#include<malloc.h>#include<windows.h>#define MAX_VERTEX_NUM 20typedef struct ArcNode{int adjvex;struct ArcNode* nextarc;//InfoType* info;}ArcNode;/**********************************链表结点的结构用于创建栈或是队列********************************/typedef struct LinkNode{ArcNode* parc; //存储指针地址struct LinkNode* next; //指向一下个结点}LinkNode;typedef struct VNode{char cData; //顶点元素值ArcNode* firstarc; //指向第一条依附于该点的边}VNode,AdjList[MAX_VERTEX_NUM];typedef struct {AdjList vertices;int vexnum; //图的当前顶点数和弧数int arcnum;}ALGraph;int Visited[MAX_VERTEX_NUM];/**********************************将生成的图打印出来以便确认正确性********************************/int PrintCheck(ALGraph* pag){int i;ArcNode* p;printf("\nCheck the Graph!\n");printf("No\tdata\tnext\tnext\t.....\n");for(i=0; i<pag->vexnum; i++){printf("%d\t%c\t",i,pag->vertices[i].cData);p = pag->vertices[i].firstarc;while(p){printf("%d\t",p->adjvex);p = p->nextarc;}printf("\n");}return 1;}/***************************采用前插法创建邻接表*************************/int CreateGraph(ALGraph* pag,int start,int end){ArcNode* arcNodes = (ArcNode*)malloc(sizeof(ArcNode));ArcNode* arcNodee = (ArcNode*)malloc(sizeof(ArcNode));ArcNode* p;if(!arcNodes || !arcNodee) return 0;//从start->end生成关系arcNodes->adjvex = end; //下一结点的位置p = pag->vertices[start].firstarc;if(!p) //第一个结点单独构造{arcNodes->nextarc = pag->vertices[start].firstarc;pag->vertices[start].firstarc = arcNodes;}else{while(p->nextarc) p = p->nextarc;p->nextarc = arcNodes;arcNodes->nextarc = NULL;}//end->start 的关系生成arcNodee->adjvex = start; //下一结点的位置p = pag->vertices[end].firstarc;if(!p) //第一个结点单独构造{arcNodee->nextarc = pag->vertices[end].firstarc;pag->vertices[end].firstarc = arcNodee;}else{while(p->nextarc) p = p->nextarc;p->nextarc = arcNodee;arcNodee->nextarc = NULL;}return 1;}/*****************************************深度优先遍历,非递归方式*结点先访问再入栈*栈的存储结构直接采用了LinkNode构成的链表*采用前插法进行插入与删除,从而也可以完成栈的功能*栈空条件 Stack->next == NULL***************************************/void DFSTraverse(ALGraph ag,int start){LinkNode* Stack = (LinkNode*)malloc(sizeof(LinkNode)); //链表头结点,用做栈LinkNode* pStack = (LinkNode*)malloc(sizeof(LinkNode)); //对栈操作的指针LinkNode* temp; //临时存储ArcNode* p;int i;if(!pStack||!Stack) return;Stack->next = NULL;p = ag.vertices[start].firstarc;Visited[start]=1; //Flagprintf("\n输出深度优先遍历顺序:");printf(" %c ",ag.vertices[start].cData); //访问第一个点while(1) //正常情况下执行一次,为了打印孤立结点{//push stackpStack->parc = p;pStack->next = Stack->next; //将p接入链式栈中Stack->next = pStack;//push overwhile(p && (Stack->next)) //当并且栈不为空时{while(p){if(Visited[p->adjvex]) p = p->nextarc;else{Visited[p->adjvex]=1;printf(" %c ",ag.vertices[p->adjvex].cData); //Visit Function//push stackpStack = (LinkNode*)malloc(sizeof(LinkNode));if(!pStack) return; //结点建立不成功pStack->parc = p;pStack->next = Stack->next;Stack->next = pStack;//push overp = ag.vertices[p->adjvex].firstarc;}}//pop stacktemp = Stack->next;Stack->next = temp->next;p = temp->parc->nextarc;free(temp);//pop over}for(i=0; i<ag.vexnum; i++) //打印出孤立点{if(!Visited[i]) printf(" %c ",ag.vertices[i].cData);p = ag.vertices[i].firstarc;}if(i = ag.vexnum) break;}printf("\n\n");};/*****************************************广度优先遍历,非递归方式*队列的存储结构直接采用了LinkNode构成的链表*采用后接法进行插入,并用前插法进行删除*从而完成队列的功能,队空条件Queue->next == NULL***************************************/void BFSTraverse(ALGraph ag,int start){LinkNode* Queue = (LinkNode*)malloc(sizeof(LinkNode)); //链表头结点,用做队列LinkNode* pQueue = (LinkNode*)malloc(sizeof(LinkNode)); //对队列操作的指针LinkNode* temp; //临时存储LinkNode* last; //指向最后一个元素的指针ArcNode* p;int i;if(!Queue || !pQueue) return;printf("\n输出广度优先遍历次序:");printf(" %c ",ag.vertices[start].cData);p = ag.vertices[start].firstarc;Visited[start] = 1;while(1) //正常情况下执行一次循环{//EnQueuepQueue->parc = p;Queue->next = pQueue;pQueue->next = NULL;last = pQueue; //指向最后一个元素的指针//EnQueue overwhile(p && Queue->next){while(p){if(!Visited[p->adjvex]){Visited[p->adjvex] = 1;printf(" %c ",ag.vertices[p->adjvex].cData); //Visit Function//EnQueuepQueue = (LinkNode*)malloc(sizeof(LinkNode));if(!pQueue) return;pQueue->parc = p;pQueue->next = NULL;last->next = pQueue;last = last->next; //指向最后一个元素的指针//EnQueue over}p = p->nextarc;}//DeQueuetemp = Queue->next;p = ag.vertices[temp->parc->adjvex].firstarc;Queue ->next = temp->next;//DeQueue over}for(i=0; i<ag.vexnum; i++) //打印出孤立点{if(!Visited[i]) printf(" %c ",ag.vertices[i].cData);p = ag.vertices[i].firstarc;}if(i = ag.vexnum) break;}printf("\n\n");}/*******************************************主函数负责对图的初始化工作*其中包括图的结点初始化,边初始化*其中大部分的while(1)语句用于验证输入数据的有效性******************************************/void main(){ALGraph ag;int i,n,m;int choose; //选择遍历结点int start,end; //边的起点与终点的位置printf("说明: 采用邻接表的存储结构,生成无向图\n 输入数据请回车确认\n\n");while(1) //结点个数有效性验证{printf("请输入图的结点个数,并回车: ");scanf("%d",&n);if(n<MAX_VERTEX_NUM && n>0) break;else printf("\n请注意结点个数不能大于20,并且不能为0!\n");}ag.vexnum = n;printf("\n初始化图的结点,输入字符并回车:\n");for(i=0; i<ag.vexnum; i++) //图的结点数据{printf("No.%d = ",i);fflush(stdin);scanf("%c",&ag.vertices[i].cData);ag.vertices[i].firstarc = NULL;}m = (n-2)*(n+1)/2+1; //顶点数为n的图最多的边的数量为mwhile(1) //边的数量有效性验证{printf("请输入边的数量: ");fflush(stdin);scanf("%d",&i);if(i<=m && i>=0) break;else printf("\n请注意边的数量不能大于%d,并且不能小于1!\n",m); }ag.arcnum = i;printf("\n初始化图的边,结点从0开始计,最大为%d\n",n-1);for(i=1; i<=ag.arcnum; i++){while(1) //起点有效性验证{printf("第<%d>条边的起点: ",i);fflush(stdin);scanf("%d",&start);if(start<n&&start>=0) break;else printf("重新输入 ");}while(1) //终点有效性验证{printf("第<%d>条边的终点: ",i);fflush(stdin);scanf("%d",&end);if(end<n && end>=0 && end!=start) break;else printf("重新输入 ");}printf("\n");CreateGraph(&ag,start,end);}PrintCheck(&ag); //打印出生成的图printf("\n开始进行图的遍历!\n");while(1) //起始点有效性验证{printf("请输入深度优先遍历的开始结点:");fflush(stdin);scanf("%d",&choose);if(choose>=0 && choose<n) break;else printf("重新输入 ");}DFSTraverse(ag,choose); //深度优先遍历i = 0; //重新初始化Visited数组while(Visited[i]!='\0'){Visited[i] = 0;i++;}while(1) //起始点有效性验证{printf("请输入广度优先遍历的开始结点:");fflush(stdin);scanf("%d",&choose);if(choose>=0 && choose<n) break;else printf("重新输入 ");}BFSTraverse(ag,choose); //广度优先遍历system("pause");}程序运行截图六、实验体会这堂实现深度优先搜索与广度优先搜索算法的数据结构实验课难度明显比第二节课要大许多,刚开始有些丈二摸不着头脑,浪费了不少课上的时间,后来回去才慢慢深入,一点点了解了这堂课的内容,经历过不少错误之后,终于算是掌握了图,无向图的基本概念,掌握图的遍历,还有图的深度优先搜索(DFS)与广度优先搜索(BFS)算法。

相关文档
最新文档