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

合集下载
  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 20
typedef 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; //Flag
printf("\n输出深度优先遍历顺序:");
printf(" %c ",ag.vertices[start].cData); //访问第一个点
while(1) //正常情况下执行一次,为了打印孤立结点
{
//push stack
pStack->parc = p;
pStack->next = Stack->next; //将p接入链式栈中
Stack->next = pStack;
//push over
while(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 stack
pStack = (LinkNode*)malloc(sizeof(LinkNode));
if(!pStack) return; //结点建立不成功
pStack->parc = p;
pStack->next = Stack->next;
Stack->next = pStack;
//push over
p = ag.vertices[p->adjvex].firstarc;
}
}
//pop stack
temp = 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) //正常情况下执行一次循环
{
//EnQueue
pQueue->parc = p;
Queue->next = pQueue;
pQueue->next = NULL;
last = pQueue; //指向最后一个元素的指针
//EnQueue over
while(p && Queue->next)
{
while(p)
{
if(!Visited[p->adjvex])
{
Visited[p->adjvex] = 1;
printf(" %c ",ag.vertices[p->adjvex].cData); //Visit Function
//EnQueue
pQueue = (LinkNode*)malloc(sizeof(LinkNode));
if(!pQueue) return;
pQueue->parc = p;
pQueue->next = NULL;
last->next = pQueue;
last = last->next; //指向最后一个元素的指针
//EnQueue over
}
p = p->nextarc;
}
//DeQueue
temp = 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的图最多的边的数量为m
while(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)算法。

到现在才真正明白原来专业课都不是很好学的,难度也是相当的大,但是相信这些都难不倒我,从这次数据结构实验课我又学到了不少专业知识,熟悉了实现深度优先搜索与广度优先搜索算法等各种算法。

相关文档
最新文档