当前位置:文档之家› 数据结构图及其应用实验报告+代码

数据结构图及其应用实验报告+代码

附件2:北京理工大学珠海学院实验报告ZHUHAI CAMPAUS OF BEIJING INSTITUTE OF TECHNOLOGY 实验题目图及其应用实验时间 2011.5.10一、实验目的、意义(1)熟悉图的邻接矩阵(或邻接表)的表示方法;(2)掌握建立图的邻接矩阵(或邻接表)算法;(3)掌握图的基本运算,熟悉对图遍历算法;(4)加深对图的理解,逐步培养解决实际问题的编程能力二、实验内容及要求说明1:学生在上机实验时,需要自己设计出所涉及到的函数,同时设计多组输入数据并编写主程序分别调用这些函数,调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。

具体要求:(1)建立图的邻接矩阵(或邻接表);(2)对其进行深度优先及广度优先遍历。

三、实验所涉及的知识点1.创建一个图: CreateUDN(MGraph &G)2.查找v顶点的第一个邻接点: FirstAdjVex(MGraph G,int v)3. 查找基于v顶点的w邻接点的下一个邻接点: NextAdjVex(MGraph G,int v,int w)4.图的矩阵输出: printArcs(MGraph G)5:顶点定位: LocateVex(MGraph G,char v)6. 访问顶点v输出: printAdjVex(MGraph G,int v)7. 深度优先遍历: DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))8. 广度优先遍历BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v))9. DFS,从第v个顶点出发递归深度优先遍历图G: DFS(MGraph G,int v)四、实验记录1.对顶点的定位其数组下标,利用了找到之后用return立即返回,在当图顶点多的情况下节省了搜索时间,程序如下//对顶点v定位,返回该顶点在数组的下标索引,若找不到则返回-1int LocateVex(MGraph G,char v){for (int i=0;i<G.vexnum;i++){if(v == G.vexs[i])return i;}return -1;}2,定义里一个全局的函数指针变量,同时在深度优先遍历中加入一个函数指针参,调用时,将传如的函数赋值给全局的函数指针,这样在之后循环调用DFS的时候就不用将函数传给DFS函数了,程序如下://深度优先遍历void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//将函数复制给全局的函数指针变量,待调用DFS时使用VisitFunc = Visit;int v;//将访问标记初始化为falsefor (v=0;v<G.vexnum;v++)visited[v] = false;for (v=0;v<G.vexnum;v++)//对尚未访问即访问标记为false的顶点调用DFSif (!visited[v]) DFS(G,v);}五、实验结果及分析预备输入的图结构如下:顶点为:a ,b ,c ,d ,e弧及其权值为:a,b,2a,c,3 b,d,4 b,e,2 d,e,1结果如下:1.图的创建,先输入顶点个数与边数,如图 4.1.1,接着输入各顶点的值,如图4.1.2,最后输入三条边依附的顶点以及权值,当输入的顶点不在图中时,会提示重新输入,如图4.1.3图4.1.1图4.1.2图4.1.3 abc d e2 31 422.图的矩阵输出,如图4.2图4.23.深度优先遍历图,输出序列,如图4.3图4.34.广度优先遍历图,输出序列,如图4.4图4.4六、总结与体会图,是一种较线性表和树更为复杂的数据结构将其用深度遍历后,可以变成一棵树,或者一个森林。

和树的遍历相类似,都利用了递归的方法,逐个搜索输出。

用邻接矩阵表示图,形象地体现出顶点与顶点之间的紧密关系。

七、程序清单(包含注释)#include "stdio.h"#include "limits.h" //INT_MAX头文件#include "windows.h" //boolean头文件#define INFINITY INT_MAX#define MAX_VERTEX_NUM 20#define OVERFLOW -1#define OK 1#define ERROR 0typedef int Status;typedef enum {DG,DN,UDG,UDN} GraphKind;typedef int VRType;typedef char VertexType;typedef char* InfoType;typedef int QElemType;//边信息typedef struct ArcCell{VRType adj; //1或0表示是否邻接,对带权图,则为权值类型InfoType *info;}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//图结构typedef struct {VertexType vexs[MAX_VERTEX_NUM]; //定点向量AdjMatrix arcs; //邻接矩阵,为一二维数组int vexnum,arcnum; //图的当前顶点数和弧数GraphKind kind; //图的种类标志}MGraph;//辅助队列typedef struct QNode{QElemType data; //数值域struct QNode *next; //指针域}QNode, *QueuePtr;typedef struct{QueuePtr front; //队头QueuePtr rear; //队尾}LinkQueue;//初始化队列Status InitQueue(LinkQueue &Q){Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if (!Q.front){printf("内存分配失败!");exit(OVERFLOW);}Q.front->next = NULL;return OK;}//插入元素到队尾Status EnQueue(LinkQueue &Q,QElemType e){QueuePtr p = (QueuePtr)malloc(sizeof(QNode));if (!p){printf("\n内存分配失败!");exit(OVERFLOW);}p->data = e;p->next = NULL;Q.rear->next = p;Q.rear = p;return OK;}//队列判空Status QueueEmpty(LinkQueue Q){return Q.front == Q.rear;}//销毁队列Status DestroyQueue(LinkQueue &Q){while (Q.front){Q.rear = Q.front->next;free(Q.front);Q.front = Q.rear;}return OK;}//删除队头元素Status DeQueue(LinkQueue &Q,QElemType &e){if (QueueEmpty(Q)){printf("\n队列为空!");return ERROR;}QueuePtr p = Q.front->next;e = p->data;Q.front->next = p->next;if(Q.rear==p) Q.rear = Q.front;free(p);return OK;}//对顶点v定位,返回该顶点在数组的下标索引,若找不到则返回-1 int LocateVex(MGraph G,char v){for (int i=0;i<G.vexnum;i++){if(v == G.vexs[i])return i;}return -1;}//create a graphStatus CreateUDN(MGraph &G){G.kind = UDN;printf("输入顶点个数和边数(如:4,3):");scanf("%d,%d",&G.vexnum,&G.arcnum);//判断是否超过顶点最大个数while(G.vexnum>MAX_VERTEX_NUM){printf("最大顶点为20,重新输入(如:4,3):");scanf("%d,%d",&G.vexnum,&G.arcnum);}printf("\n依次输入顶点向量值\n");int i;for (i=0;i<G.vexnum;i++){//清空缓冲区fflush(stdin);printf("第%d个:",i+1);scanf("%c",&G.vexs[i]);}//初始化邻接矩阵for (i=0;i<G.vexnum;i++){for (int j=0;j<G.vexnum;j++){G.arcs[i][j].adj = INFINITY;G.arcs[i][j].info = NULL;}}char front,rear;int values;printf("\n输入依附两个顶点的边及其权值<如,a,b,1>\n");for(i=0;i<G.arcnum;i++){printf("第%d条:",i+1);//清空缓冲区fflush(stdin);scanf("%c,%c,%d",&rear,&front,&values);int m,n;//定位两顶点在vexs数组中的索引m = LocateVex(G,rear);n = LocateVex(G,front);if(m==-1||n==-1){printf("输入顶点或不在此图中,请重新输入!\n");i--;continue;}//赋予对应矩阵位置的权值,以及对称弧的权值G.arcs[m][n].adj = values;G.arcs[n][m].adj = values;}return OK;} //CreateUDG//矩阵输出void printArcs(MGraph G){int i;printf(" ");//输出第一行的顶点向量for (i=0;i<G.vexnum;i++){printf(" %c",G.vexs[i]);}for (i=0;i<G.vexnum;i++){printf("\n\n%c",G.vexs[i]);for (int j=0;j<G.vexnum;j++){if(G.arcs[i][j].adj==INFINITY)printf(" ∞");elseprintf(" %d",G.arcs[i][j].adj);}}printf("\n");}//访问顶点v输出Status printAdjVex(MGraph G,int v){printf("%c ",G.vexs[v]);return OK;}//查找v顶点的第一个邻接点Status FirstAdjVex(MGraph G,int v){//查找与顶点v的第一个邻接点,找到后立即返回其索引,若找不到,则返回-1 for (int i=1;i<G.vexnum;i++){if(G.arcs[v][i].adj!=INFINITY)return i;}return -1;}//查找基于v顶点的w邻接点的下一个邻接点Status NextAdjVex(MGraph G,int v,int w){//查找基于顶点v的w邻接点的下一个邻接点,找到之后立即返回其索引,若找不到,则返回-1for (int i=w+1;i<G.vexnum;i++){if (G.arcs[v][i].adj!=INFINITY)return i;}return -1;}//创建访问标志全局变量boolean visited[MAX_VERTEX_NUM];//函数指针变量Status (* VisitFunc)(MGraph G,int v);//DFS,从第v个顶点出发递归深度优先遍历图Gvoid DFS(MGraph G,int v){visited[v] = TRUE;//访问第v个顶点VisitFunc(G,v);for (int w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){if (!visited[w])DFS(G,w);}}//深度优先遍历void DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//将函数复制给全局的函数指针变量,待调用DFS时使用VisitFunc = Visit;int v;//将访问标记初始化为falsefor (v=0;v<G.vexnum;v++)visited[v] = false;for (v=0;v<G.vexnum;v++)//对尚未访问即访问标记为false的顶点调用DFSif (!visited[v]) DFS(G,v);}//广度优先遍历void BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)){//按广度优先非递归遍历图G,使用辅助队列Q和访问标志数组Visitedint v;int u;//将访问标记数组初始化为falsefor (v = 0;v<G.vexnum;v++)visited[v] = FALSE;//创建辅助队列QLinkQueue Q;InitQueue(Q);for (v = 0;v<G.vexnum;v++)//判断顶点V是否被访问if (!visited[v]){//将第一次访问的顶点对应的访问标记数组位置赋值为TRUEvisited[v] = TRUE;//输出顶点vVisit(G,v);EnQueue(Q,v);while (!QueueEmpty(Q)){//按入队序列取出顶点,便于查找此顶点的邻接点DeQueue(Q,u);//查找当前顶点邻接点for (int w=FirstAdjVex(G,u);w>=0;w = NextAdjVex(G,u,w))if (!visited[w]){visited[w] =TRUE;Visit(G,w);EnQueue(Q,w);}}}//销毁队列DestroyQueue(Q);}void main(){printf("====图的创建及其应用====\n");//创建一个图MGraph G;CreateUDN(G);//用邻接矩阵输出图printf("\n图的邻接矩阵输出如下:\n");printArcs(G);//深度优先遍历printf("\n深度优先遍历序列:\n");DFSTraverse(G,printAdjVex);printf("\n");//广度优先遍历printf("\n广度优先遍历序列:\n");BFSTraverse(G,printAdjVex);printf("\n");}11。

相关主题