数据结构实验———图实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构
实
验
报
告
目的要求
1.掌握图的存储思想及其存储实现..
2.掌握图的深度、广度优先遍历算法思想及其程序实现..
3.掌握图的常见应用算法的思想及其程序实现..
实验内容
1.键盘输入数据;建立一个有向图的邻接表..
2.输出该邻接表..
3.在有向图的邻接表的基础上计算各顶点的度;并输出..
4.以有向图的邻接表为基础实现输出它的拓扑排序序列..
5.采用邻接表存储实现无向图的深度优先递归遍历..
6.采用邻接表存储实现无向图的广度优先遍历..
7.在主函数中设计一个简单的菜单;分别调试上述算法..
源程序:
主程序的头文件:队列
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int QElemType;
typedef struct QNode{ //队的操作
QElemType data;
struct QNode *next;
}QNode;*QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
void InitQueueLinkQueue &Q{ //初始化队列
Q.front =Q.rear =QueuePtrmallocsizeofQNode;
ifQ.front exitOVERFLOW; //存储分配失败
Q.front ->next =NULL;
}
int EnQueueLinkQueue &Q;QElemType e //插入元素e为Q的新的队尾元素{
QueuePtr p;
p=QueuePtrmallocsizeofQNode;
ifp exitOVERFLOW;
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear =p;
return OK;
}
int DeQueueLinkQueue &Q;QElemType &e //删除Q的队头元素;用e返回其值{ ifQ.front ==Q.rear return ERROR;
QueuePtr p;
p=Q.front ->next;
e=p->data;
Q.front->next=p->next ;
ifQ.rear==p Q.rear =Q.front ;
freep;
return OK;
}
主程序:
#include <stdio.h>
#include<stdlib.h>
#include"duilie.h"
#define TRUE 1
#define FALSE 0
#define Status int
#define MAX_VERTEX_NUM 8 /*顶点最大个数*/
#define VertexType char /*顶点元素类型*/
enum BOOlean {False;True};
BOOlean visitedMAX_VERTEX_NUM; //全局变量——访问标志数组
typedef struct ArcNode
{int adjvex;
struct ArcNode *nextarc;
int weight; /*边的权*/
}ArcNode; /*表结点*/
typedef struct VNode
{ int degree;indegree;/*顶点的度;入度*/
V ertexType data;
ArcNode *firstarc;
}VNode/*头结点*/;AdjListMAX_VERTEX_NUM;
typedef struct
{ AdjList vertices;
int vexnum;arcnum;/*顶点的实际数;边的实际数*/
}ALGraph;
//建立图的邻接表
void creat_linkALGraph *G
{ int i;j;
ArcNode *s;
printf"请依次输入顶点数、边数:";
scanf"%d%d";&G->vexnum;&G->arcnum;
for i=0;i<G->vexnum;i++
{ G->verticesi.data='A'+i;
G->verticesi.firstarc=NULL;
}
for i=0;i<G->vexnum;
{ printf"请输入顶点的数组坐标若退出;请输入-1:";
scanf"%d";&i;
ifi==-1 break;
printf"请输入顶点所指向下一个顶点的数组坐标:";
scanf"%d";&j;
s=ArcNode *mallocsizeofArcNode;
s->adjvex=j;
s->nextarc=G->verticesi.firstarc;
G->verticesi.firstarc=s;
}
}
// 输出邻接表
void visitALGraph G
{ int i;
ArcNode *p;
printf"%4s%6s%18s\n";"NO";"data";"adjvexs of arcs";
for i=0;i<G.vexnum;i++
{
printf"%4d%5c ";i;G.verticesi.data;
forp=G.verticesi.firstarc;p;p=p->nextarc
printf"%3d";p->adjvex;
printf"\n";
}
}
// 计算各顶点的度及入度
void cacuALGraph *G
{
ArcNode *p;
int i;
for i=0;i<G->vexnum;i++
{G->verticesi.degree=0;G->verticesi.indegree=0;}//度与初度初始化为零for i=0;i<G->vexnum;i++
forp=G->verticesi.firstarc;p;p=p->nextarc
{G->verticesi.degree++;
G->verticesp->adjvex.degree++;
G->verticesp->adjvex.indegree++;
}
}
void print_degreeALGraph G
{
int i;
printf"\n Nom data degree indegree\n";
for i=0;i<G.vexnum;i++
printf"\n%4d%5c%7d%8d";i;G.verticesi.data;
G.verticesi.degree;G.verticesi.indegree;
printf"\n";
}
// 拓扑排序
Status TopologiSortALGraph G
{int i;count;top=0;stack50;
ArcNode *p;
cacu&G;
print_degreeG;
printf"\nTopologiSort is \n";
fori=0;i<G.vexnum;i++
ifG.verticesi.indegree stacktop++=i;
count=0;
whiletop=0
{
i=stack--top;
if count==0 printf"%c";G.verticesi.data;
else printf"-->%c";G.verticesi.data;
count++;
forp=G.verticesi.firstarc;p;p=p->nextarc
if --G.verticesp->adjvex.indegreestacktop++=p->adjvex;
}
if count<G.vexnumreturnFALSE; else returnTRUE;
}
//在图G中寻找第v个顶点的第一个邻接顶点
int FirstAdjVexALGraph G;int v
{
ifG.verticesv.firstarc return 0;
else returnG.verticesv.firstarc->adjvex;
}
//在图G中寻找第v个顶点的相对于u的下一个邻接顶点
int NextAdjVexALGraph G;int v;int u
{
ArcNode *p;
p=G.verticesv.firstarc;
whilep->adjvex=u p=p->nextarc; //在顶点v的弧链中找到顶点u ifp->nextarc==NULL return 0; //若已是最后一个顶点;返回0
else returnp->nextarc->adjvex; //返回下一个邻接顶点的序号
}
//采用邻接表存储实现无向图的深度优先递归遍历
void DFSALGraph G;int i
{ int w;
visitedi=True; //访问第i个顶点
printf"%d->";i;
forw=FirstAdjVexG;i;w;w=NextAdjVexG;i;w
ifvisitedw DFSG;w; //对尚未访问的邻接顶点w调用DFS
}
void DFSTraverseALGraph G
{ int i;
printf"DFSTraverse:";
fori=0;i<G.vexnum;i++ visitedi=False; //访问标志数组初始化
fori=0;i<G.vexnum;i++
ifvisitedi DFSG;i; //对尚未访问的顶点调用DFS
}
//按广度优先非递归的遍历图G;使用辅助队列Q和访问标志数组visited void BFSTraverseALGraph G
{
int i;u;w;
LinkQueue Q;
printf"BFSTreverse:";
fori=0;i<G.vexnum;i++ visitedi=False; //访问标志数组初始化
InitQueueQ; //初始化队列
fori=0;i<G.vexnum;i++
ifvisitedi
{visitedi=True; //访问顶点i
printf"%d->";i;
EnQueueQ;i; //将序号i入队列
whileQ.front ==Q.rear //若队列不空;继续
{DeQueueQ;u; //将队头元素出队列并置为u
forw=FirstAdjVexG;u;w;w=NextAdjV exG;u;w
ifvisitedw //对u的尚未访问的邻接顶点w进行访问并入队列
{ visitedw=True;
printf"%d->";w;
EnQueueQ;w;
}
}
}
}
void main
{
ALGraph G;
int select;
printf" 图的有关操作实验\n ";
do{
printf"\n1 创建一个有向图的邻接表 2 输出该邻接表\n";
printf"3.输出该有向图的度和入度 4.输出该有向图拓扑排序序列\n";
printf"5.创建一个无向图的邻接表 6.深度优先递归遍历该无向图\n";
printf"7.广度优先遍历该无向图0.退出\n";
printf"请输入选择:";
scanf"%d";&select;
switchselect{
case 1:
printf"\n创建一个有向图的邻接表:\n";
creat_link&G;
break;
case 2:
printf"\n输出该邻接表:\n";
visitG;
break;
case 3:
printf"\n输出该有向图的度和入度:\n";
cacu&G;
print_degreeG;
break;
case 4:
printf"\n输出该有向图拓扑排序序列:\n";
ifTopologiSortGprintf"Toposort is not success";
break;
case 5:
printf"\n创建一个无向图的邻接表: \n";
creat_link&G;
break;
case 6:
printf"\n深度优先递归遍历该无向图: \n";
DFSTraverseG;
break;
case 7:
printf"\n广度优先遍历该无向图:\n";
BFSTraverseG;
break;
case 0:
break;
default:
printf"输入选项错误重新输入\n";
}
}whileselect;
}
运行结果截图:
1.主菜单界面:
2.创建一个有向图的领接表
3.输出该邻接表
4. 在有向图的邻接表的基础上计算各顶点的度;并输出..
5. 输出它的拓扑排序序列
6. 输出所建无向图的邻接表
7. 深度优先递归遍历该无向图
8. 广度优先遍历该无向图
说明:
本实验用的有向图是课本182页图7.28;无向图为课本168页图a
实验总结
这次的图的操作实验;与树的操作类似;但又比树复杂;包含更多的存储结构和遍历方法的操作;而且图的遍历需要沿着弧进行;以便输出弧上的信息..本实验中图的遍历采用邻接表的存储结构;在输入图的信息时;首先要画出图的邻接表信息..图有两种遍历的形式;一种为深度优先搜索;另一种为广度优先搜索..由于能力有限;没能实现图的深度非递归优先搜索;而是实现了图的深度递归优先搜索..本实验基本完成了图的操作;也学到了很多关于图的知识和算法..。