___《数据结构》课程实验报告(实验5——图的存储方式和应用)参考答案
数据结构实验五实验报告

数据结构实验报告实验五图子系统实验题目:图的遍历问题专业班级:网络工程 1002班组长:王星(30)组员:郭坤铭(43)张磊(44)2012年 5月 18日实验报告实验类型__综合__实验室_软件实验室二__一、实验题目图的遍历问题二、实验目的和要求1、掌握图的存储思想及其存储实现2、掌握图的深度、广度优先遍历算法思想及其程序实现3、掌握图的常见应用算法的思想及其程序实现三、需求分析本演示程序用c++6.0编写,完成用户用键盘输入以下结点数据:太原、成都、北京、上海、天津、大连、河北。
(1)建立一个有向图或无向图(自定)的邻接表并输出该邻接表。
(2)在图的邻接表的基础上计算各顶点的度,并输出。
(3)以有向图的邻接表为基础实现输出它的拓扑排序序列。
(4)采用邻接表存储实现无向图的深度优先遍历。
(5)采用邻接表存储实现无向图的广度优先遍历。
(6)采用邻接矩阵存储实现无向图的最小生成树的 PRIM 算法。
最后,在主函数中设计一个简单的菜单,分别调试上述算法。
四、概要设计为了实现上述程序功能,需要定义如下内容基本数据类型定义如下:typedef struct node{ //边表结点int adj; //边表结点数据域struct node *next;}node;typedef struct vnode //顶点表结点{ char name[20];node *fnext;}vnode,AList[20];typedef struct{ AList List; //邻接表int v,e; //顶点树和边数}*Graph;Graph CreatDG(){ } //建立无向邻接表Graph CreatAG(){ } //有向邻接图void Print(Graph G){} //输出图的邻接表void CreateAN(AGraph *G1){} //构造邻接矩阵结构的图G void Du(Graph G){} //输出各顶点的度数void DFSTravel(Graph G){} //深度优先遍历void BFSTravel(Graph G){} //广度优先遍历五、详细设计#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct node{//边表结点int adj;//边表结点数据域struct node *next;}node;typedef struct vnode{//顶点表结点char name[20];node *fnext;}vnode,AList[20];typedef struct{AList List;//邻接表int v,e;//顶点树和边数}*Graph;//建立无向邻接表Graph CreatDG(){Graph G;int i,j,k;node *s;G=malloc(20*sizeof(vnode));printf("请输入图的顶点数和边数(空格隔开):");scanf("%d%d",&G->v,&G->e);//读入顶点数和边数for(i=0;i<G->v;i++){printf("请输入图中第%d元素:",i+1);scanf("%s",G->List[i].name);//读入顶点信息G->List[i].fnext=NULL;//边表置为空表}for(k=0;k<G->e;k++){printf("请请输入第%d条边的两顶点序号(空格隔开):",k+1);scanf("%d%d",&i,&j);//读入边(Vi,Vj)的顶点对序号;s=(node *)malloc(sizeof(node));//生成边表结点s->adj=j;s->next=G->List[i].fnext;G->List[i].fnext=s;//将新结点*s插入顶点Vi的边表头部s=(node *)malloc(sizeof(node));s->adj=i;//邻接点序号为is->next=G->List[j].fnext;G->List[j].fnext=s;// 将新结点*s插入顶点Vj的边表头部}return G;}//有向邻接图Graph CreatAG(){Graph G;int i,j,k;node *q;G=malloc(20*sizeof(vnode));printf("请输入图的顶点数和边数【空格隔开】:");scanf("%d%d",&G->v,&G->e);for (i=0;i<G->v;i++){printf("请输入图中第%d元素:",i+1);scanf("%s",&G->List[i].name); //读入顶点信息G->List[i].fnext=NULL;}for (k=0;k<G->e;k++){printf("请请输入第%d边的两顶点序号【空格隔开】:",k+1);scanf("%d%d",&i,&j);q=(node *)malloc(sizeof(node)); //生成新边表结点sq->adj=j; //邻接点序号为jq->next=G->List[i].fnext;G->List[i].fnext=q;}return G;}//输出图的邻接表void Print(Graph G){int i;node *p;printf("\t=======邻接表========\n");for(i=0;i<G->v;i++){p=G->List[i].fnext;printf("%d | %3s",i,G->List[i].name);while(p){printf("->%3s",G->List[p->adj].name);printf("->%d",p->adj);p=p->next;}printf("\n");}}typedef struct {char vex[20];}Lists[20];typedef struct{Lists l;int edge[20][20];//邻接矩阵int v1,e1;//顶点数和弧数}AGraph;typedef struct{int data; /* 某顶点与已构造好的部分生成树的顶点之间权值最小的顶点 */int lowcost; /* 某顶点与已构造好的部分生成树的顶点之间的最小权值 */}ClosEdge[20]; /* 用普里姆算法求最小生成树时的辅助数组 */ void CreateAN(AGraph *G1){/* 构造邻接矩阵结构的图G */int i,j,k,w;printf("请输入图的顶点数和边数(空格隔开):");scanf("%d%d",&G1->v1,&G1->e1);//读入顶点数和边数for(i=1;i<=G1->v1;i++){printf("请输入图%d号元素:",i);scanf("%s",&G1->l[i].vex);//读入顶点信息}for(i=1;i<=G1->v1;i++)//初始化邻接矩阵for(j=1;j<=G1->v1;j++)G1->edge[i][j] = 9;for(k=1;k<=G1->e1;k++){printf("请输入两顶点及边的权值(空格隔开):");scanf("%d%d%d",&i,&j,&w);G1->edge[i][j]=w;G1->edge[j][i]=w;}}void PrintAN(AGraph *G1){int i,j;printf("\t=======邻接矩阵========\n");for(i=1;i<=G1->v1;i++){for(j=1;j<=G1->v1;j++)printf("%3d",G1->edge[i][j]);printf("\n");}}//输出各顶点的度数void Du(Graph G){int i,j;printf("\n<----各点度数---->\n");for(i=0;i<G->v;i++){p=G->List[i].fnext;printf("顶点%2s的度为:",G->List[i].name);j=0;while(p){j++;p=p->next;}printf("%d\n",j);}}//栈typedef struct stack{int x;struct stack *next;}stack;int push(stack *s,int i){stack *p;p=(stack *)malloc(sizeof(stack));p->x=i;p->next=s->next;s->next=p;return 1;}int pop(stack *s,int j){stack *p=s->next;//保存栈顶指针j=p->x;s->next=p->next; //将栈顶元素摘下free(p);//释放栈顶空间return j;}//拓扑排序void Topo(Graph G,stack *s){int i,k, count;int j=0;int indegree[20]={0};for(i=0;i<G->v;i++){p=G->List[i].fnext;;while(p!=NULL){indegree[p->adj]++;p=p->next;}}for(i=0;i<G->v;i++)if(indegree[i]==0)push(s,i);count=0;while(s->next!=NULL){i=pop(s,j);printf("%2s ",G->List[i].name);++count;for(p=G->List[i].fnext;p!=NULL;p=p->next){ k=p->adj;if(!(--indegree[k]))push(s,k);}}if(count<G->v) printf("有回路!");}void DFS(Graph G,int i,int flag[]){node *p;printf("%2s ",G->List[i].name);flag[i]=1;p=G->List[i].fnext;while(p){if(!flag[p->adj])DFS(G,p->adj,flag);p=p->next;}}//深度优先遍历void DFSTravel(Graph G){int i;int flag[20];//标志数组for(i=0;i<G->v;i++)flag[i]=0;for(i=0;i<G->v;i++)if(!flag[i])DFS(G,i,flag);}//建立队列typedef struct{int *elem;int front, rear;}*Queue;//队列初始化void InitQueue(Queue Q){Q->elem=(int *)malloc(20*sizeof(int));if(!Q->elem)exit(0);Q->front=Q->rear=0;}//入队void Enter(Queue Q, int e){if((Q->rear + 1)%20!= Q->front)Q->elem[Q->rear ]=e;elseprintf("队列满!\n");Q->rear=(Q->rear+1)%20;}//出队void Leave(Queue Q, int e){if(Q->rear != Q->front)e=Q->elem[Q->front];elseprintf("队列空!\n");Q->front=(Q->front+1)%20;}//广度优先遍历void BFSTravel(Graph G){Queue Q;node *p;int i,j=0;int flag[20];//标志数组Q=malloc(sizeof(20));InitQueue(Q);for(i=0;i<G->v;i++)flag[i]=0;for(i=0;i<G->v;i++)if(flag[i]==0){flag[i]=1;printf("%2s",G->List[i].name);Enter(Q,i);while(Q->front!=Q->rear){Leave(Q,j);//队头元素出队并置为jp=G->List[j].fnext;while(p!=NULL){if(flag[p->adj]==0){printf("%2s ",G->List[p->adj].name);flag[p->adj]=1;Enter(Q,p->adj);}p=p->next;}}}}int minimum(ClosEdge cl,int vnum){int i;int w,p;w=1000;for(i=1;i<=vnum;i++)if(cl[i].lowcost!=0&&cl[i].lowcost<w){w=cl[i].lowcost;p=i;}return p;}void Prim(AGraph *G1,int u){ClosEdge closedge;int i,j,k;for(j=1;j<=G1->v1;j++) /* 辅助数组初始化 */if(j!=u){closedge[j].data=u;closedge[j].lowcost=G1->edge[u][j];}closedge[u].lowcost=0; /* 初始,U={u} */for(i=1;i<G1->v1;i++){k=minimum(closedge,G1->v1); /* 求出生成树的下一个顶点*/printf("%d-----%d\n",closedge[k].data,k); /* 输出生成树的边 */closedge[k].lowcost=0; /* 第k顶点并入U集 */for(j=1;j<=G1->v1;j++) /* 新顶点并入U后,修改辅助数组*/if(G1->edge[k][j]<closedge[j].lowcost){closedge[j].data=k;closedge[j].lowcost=G1->edge[k][j];}}}//菜单列表void menu(){printf("\t**********************图的遍历问题**********************\n");printf("\t\t------- 1.建立无向邻接图---------\n");printf("\t\t------- 2.建立有向邻接图---------\n");printf("\t\t------- 3.建立无向邻接矩阵---------\n");printf("\t\t------- 4.输出各顶点的度---------\n");printf("\t\t------- 5.拓扑排序---------\n");printf("\t\t------- 6.深度优先遍历---------\n");printf("\t\t------- 7.广度优先遍历---------\n");printf("\t\t------- 8.prim算法生成最小生成树---------\n");printf("\t\t------- 9-退出---------\n");printf("\t********************************************** **********\n");}//主函数void main(){Graph G;AGraph G1;int choice,u;stack *s=(stack *)malloc(sizeof(stack));s->next =NULL;while(1){menu();printf("请输入选择:");scanf("%d",&choice);switch(choice){case1:G=CreatDG();Print(G);printf("\n\n");break;case2:G=CreatAG();Print(G);printf("\n\n");break;case3:CreateAN(&G1);PrintAN(&G1);printf("\n\n");break; case4:Du(G);printf("\n\n");break;case5:printf("拓扑排序:");Topo(G,s);printf("\n\n");break;case6:printf("深度优先遍历:");DFSTravel(G);printf("\n\n");break;case7:printf("广度优先遍历:");BFSTravel(G);printf("\n\n");break;case 8:printf("请输入起点序号:");scanf("%d",&u);printf("Prim算法:\n");Prim(&G1,u);printf("\n");break;case 9: exit(0);default: printf("输入错误,请重新输入:\n\n ");}}}六、使用说明1、程序名为实验5.exe,运行坏境为DOS.程序执行后显示如图所示:2、建立无向邻接图3、输出各顶点的度4、进行深度优先遍历5、进行广度优先遍历6、建立有向邻接图7、拓扑排序8、建立无向邻接矩阵9、prim算法生成最小生成树七、实验总结本次实验对我们来说有不小的难度,花费了很长的时间,在大家的商量讨论和共同努力下,最终完成了实验的内容,组长在此过程中很认真负责,使组员一步一步前进。
数据结构-实验5-图的应用

实验报告
开课学院及实验室: 年月日
五实验方法
1 对问题进展需求分析, 选取详细城市结点, 通过调研获取城市间的交通网络, 选取主要的通行道路抽象为图的无向带权边。
2 进展概要设计和详细设计, 形成模块间的调用构造图和模块的算法。
3 编写程序, 设计测试用例进展测试。
4 完成开发文档。
六实验结果
1需求分析: 在中国城市, 电子地图的认知度和使用率正在飞快递增, 随着用户量不断增加, 纸质地图逐渐被电子地图取而代之。
在大中型城市, 电子地图已经成为绝大多数用户出行前首选的参照工具和查询途径。
电子地图强调准确性、简单易用以及查询速度。
电子地图的另外一个特点是使用方便, 无论是通过互联网还是手机都可以方便接触到并使用。
出行前用电脑通过互联网地图规划道路、查找目的地, 路上那么可以用手机连接无线网络, 通过手机地图随时修正道路和辨识方向。
2概要设计:
3详细设计:
4编程遇到的问题和调试分析:
5用户手册:
概述: 简单的交通咨询系统
功能:
1.珠三角地区交通查询;
2.珠三角地区各城市信息查询。
使用说明:
1.翻开方法: 翻开命令行窗口, 进入map.exe文件所在目录〔如: cd e:/map〕, 输入map, 进入程序。
2.构造地图信息, 按提示输入map.txt.
3.交通查询功能的使用: 输入1进入查询, 按要求输入起点城市编号和终点城市编号, 回车即可。
4.城市信息查询功能的使用:输入2进入查询, 按要求输入城市编号, 回车即可。
6 测试结果:
7 附录〔源程序清单〕。
数据结构实验报告实验5

数据结构实验报告实验5一、实验目的本次实验的主要目的是深入理解和掌握常见的数据结构,如链表、栈、队列、树和图等,并通过实际编程实现,提高对数据结构的操作和应用能力。
同时,培养解决实际问题的思维和编程能力,提高代码的可读性、可维护性和效率。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
三、实验内容1、链表的基本操作创建链表插入节点删除节点遍历链表2、栈的实现与应用用数组实现栈用链表实现栈栈的应用:括号匹配3、队列的实现与应用用数组实现队列用链表实现队列队列的应用:排队模拟4、二叉树的遍历前序遍历中序遍历后序遍历5、图的表示与遍历邻接矩阵表示法邻接表表示法深度优先遍历广度优先遍历四、实验步骤1、链表的基本操作创建链表:首先定义一个链表节点结构体,包含数据域和指向下一个节点的指针域。
然后通过动态内存分配创建链表节点,并将节点逐个连接起来,形成链表。
插入节点:根据插入位置的不同,分为在表头插入、在表尾插入和在指定位置插入。
在指定位置插入时,需要先找到插入位置的前一个节点,然后进行节点的连接操作。
删除节点:同样需要根据删除位置的不同进行处理。
删除表头节点时,直接将头指针指向下一个节点;删除表尾节点时,找到倒数第二个节点,将其指针置为空;删除指定位置节点时,找到要删除节点的前一个节点,然后调整指针。
遍历链表:通过从链表头开始,依次访问每个节点,输出节点的数据。
2、栈的实现与应用用数组实现栈:定义一个固定大小的数组作为栈的存储空间,同时用一个变量记录栈顶位置。
入栈操作时,先判断栈是否已满,如果未满则将元素放入栈顶位置,并更新栈顶位置;出栈操作时,先判断栈是否为空,如果不空则取出栈顶元素,并更新栈顶位置。
用链表实现栈:与链表的操作类似,将新元素添加在链表头部作为栈顶。
括号匹配:输入一个包含括号的字符串,使用栈来判断括号是否匹配。
遇到左括号入栈,遇到右括号时与栈顶的左括号进行匹配,如果匹配成功则出栈,否则括号不匹配。
《数据结构》实验报告

《数据结构》实验报告实验一一、实验目的及要求理解线性表的顺序存储结构;熟练掌握顺序表结构及其有关算法的设计;理解线性表的链式存储结构;熟练掌握动态链表结构及其有关算法的设计;根据具体问题的需要,设计出合理的表示数据的链表结构,并设计相关算法;深入了解栈和队列的特性,以便在实际问题背景下灵活运用他们;同时巩固对这两种结构的构造方法的理解。
二、实验环境硬件:计算机软件:Microsoft Visual C++三、实验内容1.以顺序表作存储结构,实现线性表的插入、删除;2.以单链表作存储结构,实现有序表的合并;3.利用栈(以顺序栈作存储结构)实现进制转换,并用队列(以链队列作存储结构)计算并打印杨辉三角。
四、源程序清单五、实验结果六、总结实验二一、实验目的及要求掌握二叉树的动态存储结构--二叉链表,掌握二叉树的三种遍历方法,会运用三种遍历的方法求解有关问题。
二、实验环境硬件:计算机软件:Microsoft Visual C++三、实验内容1.以二叉链表作存储结构,建立一棵二叉树;2.输出其先序、中序、后序遍历序列;3.求出它的深度;4.统计其叶子结点数四、源程序清单五、实验结果六、总结实验三一、实验目的及要求掌握图的存储结构及其建立算法,熟练掌握图的两种遍历算法及其应用。
二、实验环境硬件:计算机软件:Microsoft Visual C++三、实验内容1.以邻接矩阵法作存储结构,建立一个无向图;2.输出该图的深度优先搜索序列;3.输出该图的广度优先搜索序列;4. 设计算法求出该图的连通分量个数及边的数目。
四、源程序清单五、实验结果六、总结实验四一、实验目的及要求掌握顺序表的查找方法,尤其是折半查找方法。
掌握二叉排序树的查找算法。
二、实验环境硬件:计算机软件:Microsoft Visual C++三、实验内容1.建立一个顺序表,用顺序查找的方法对其实施查找;2.建立一个有序表,用折半查找的方法对其实施查找;3.建立一个二叉排序树,根据给定值对其实施查找;4.对同一组数据,试用三种方法查找某一相同数据,并尝试进行性能分析。
数据结构试验报告-图的基本操作

中原工学院《数据结构》实验报告学院:计算机学院专业:计算机科学与技术班级:计科112姓名:康岩岩学号:201100814220 指导老师:高艳霞2012-11-22实验五图的基本操作一、实验目的1、使学生可以巩固所学的有关图的基本知识。
2、熟练掌握图的存储结构。
3、熟练掌握图的两种遍历算法。
二、实验内容[问题描述]对给定图,实现图的深度优先遍历和广度优先遍历。
[基本要求]以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的结点为起点,分别输出每种遍历下的结点访问序列。
【测试数据】由学生依据软件工程的测试技术自己确定。
三、实验前的准备工作1、掌握图的相关概念。
2、掌握图的逻辑结构和存储结构。
3、掌握图的两种遍历算法的实现。
四、实验报告要求1、实验报告要按照实验报告格式规范书写。
2、实验上要写出多批测试数据的运行结果。
3、结合运行结果,对程序进行分析。
【设计思路】【代码整理】#include "stdafx.h"#include <iostream>#include <malloc.h>using namespace std;typedef int Status;#define OK 1#define ERROR 0#define OVERFLOW -1#define MAX_SIZE 20typedef enum{DG,DN,UDG,UDN}Kind;typedef struct ArcNode{int adjvex; //顶点位置struct ArcNode *nextarc; //下一条弧int *info; //弧信息};typedef struct{char info[10]; //顶点信息ArcNode *fistarc; //指向第一条弧}VNode,AdjList[MAX_SIZE];typedef struct{AdjList vertices;int vexnum,arcnum; //顶点数,弧数int kind; //图的种类,此为无向图}ALGraph;//这是队列的节点,仅用于广度优先搜索typedef struct Node{int num;struct Node* next;};//队列的头和尾typedef struct{Node * front;Node *rear;}PreBit;int LocateV ex(ALGraph G,char info[]);//定位顶点的位置Status addArcNode(ALGraph &G,int adjvex); //图中加入弧Status CreatGraph(ALGraph&G);//创建图的邻接表Status DFSTraverse(ALGraph G);//深度优先搜索Status BFSTraverse(ALGraph G);//广度优先搜索Status DFS(ALGraph G,int v);//深度优先搜索中的数据读取函数,用于递归bool visited[MAX_SIZE]; // 访问标志数组//初始化队列Status init_q(PreBit&P_B){P_B.front=P_B.rear=(Node*)malloc(sizeof(Node));if(!P_B.front){exit(OVERFLOW);}P_B.front->next=NULL;}//将数据入队Status en_q(PreBit & P_B,int num){Node *p=(Node*)malloc(sizeof(Node));if(!p){exit(OVERFLOW);}p->num=num;p->next=NULL;P_B.rear->next=p;P_B.rear=p;return OK;}//出队Status de_q(PreBit & P_B){if(P_B.front==P_B.rear){return ERROR;}Node* p=P_B.front->next;P_B.front->next=p->next;if(P_B.rear==p){P_B.rear=P_B.front;}free(p);return OK;}Status CreatGraph(ALGraph&G){cout<<"请输入顶点数目和弧数目"<<endl;cin>>G.vexnum>>G.arcnum;//依次输入顶点信息for(int i=0;i<G.vexnum;i++){cout<<"请输入顶点名称"<<endl;cin>>G.vertices[i].info;G.vertices[i].fistarc=NULL;}//依次输入弧信息for(int k=1;k<=G.arcnum;k++){char v1[10],v2[10]; //用于表示顶点名称的字符数组int i,j; //表示两个顶点的位置BACK: //返回点cout<<"请输入第"<<k<<"条弧的两个顶点"<<endl;cin>>v1>>v2;i=LocateV ex(G,v1); //得到顶点v1的位置j=LocateV ex(G,v2); //得到顶点v2的位置if(i==-1||j==-1){ //头信息不存在则返回重输cout<<"不存在该节点!"<<endl;goto BACK; //跳到BACK 返回点}addArcNode(G,i); //将弧的顶点信息插入表中addArcNode(G,j);}return OK;}//倒序插入弧的顶点信息Status addArcNode(ALGraph &G,int adjvex){ArcNode *p; //弧节点指针p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=adjvex;p->nextarc=G.vertices[adjvex].fistarc;//指向头结点的第一条弧G.vertices[adjvex].fistarc=p; //头结点的第一条弧指向p,即将p作为头结点的第一条弧return OK;}//定位顶点的位置int LocateV ex(ALGraph G,char info[]){for(int i=0;i<G.vexnum;i++){if(strcmp(G.vertices[i].info,info)==0){ //头结点名称与传入的信息相等,证明该头节点存在return i; //此时返回位置}}return -1;}//深度优先搜索Status DFSTraverse(ALGraph G){for(int v=0;v<G.vexnum;v++){visited[v]=false;}char v1[10];int i;BACK:cout<<"请输入首先访问的顶点"<<endl;cin>>v1;i=LocateV ex(G,v1);if(i==-1){cout<<"不存在该节点!"<<endl;goto BACK;}DFS(G,i);return OK;}//深度优先搜索递归访问图Status DFS(ALGraph G,int v){visited[v]=true;cout<<G.vertices[v].info<<" ";//输出信息ArcNode *p;p=G.vertices[v].fistarc; //向头节点第一条while(p) //当弧存在{if(!visited[p->adjvex]){DFS(G,p->adjvex); //递归读取}p=p->nextarc;}return OK;}//广度优先搜索Status BFSTraverse(ALGraph G){for(int v=0;v<G.vexnum;v++){visited[v]=false;}char v1[10];int v;BACK:cout<<"请输入首先访问的顶点"<<endl;cin>>v1;v=LocateV ex(G,v1);if(v==-1){cout<<"不存在该节点!"<<endl;goto BACK;}PreBit P_B;init_q(P_B);ArcNode *p;visited[v]=true;cout<<G.vertices[v].info<<" ";//输出信息en_q(P_B,v); //将头位置v入队while(P_B.front!=P_B.rear){//当队列不为空时,对其进行访问int w=P_B.front->next->num;//读出顶点位置de_q(P_B);//顶点已经访问过,将其出队列p=G.vertices[w].fistarc;//得到与顶点相关的第一条弧while(p){if(!visited[p->adjvex]){en_q(P_B,p->adjvex);//将弧入队,但不读取,只是将其放在队尾}p=p->nextarc;}}return OK;}int _tmain(int argc, _TCHAR* argv[]){ALGraph G;CreatGraph(G);cout<<"深度优先搜索图:"<<endl;DFSTraverse(G);cout<<endl;cout<<"广度优先搜索图:"<<endl;BFSTraverse(G);cout<<endl;system("pause");return 0;}。
数据结构课程实验(图的存储与遍历)

实验五图的存储与遍历1、实验目的掌握图这种复杂的非线性结构的邻接矩阵和邻接表的存储表示,以及在此两种常用存储方式下深度优先遍历(dfs)和广度优先遍历(BFS)操作的实现。
2、实验预备知识(1)图的存储结构:邻接矩阵表示法和邻接表表示法。
邻接矩阵表示法除了要用一个二维数组存储用于表示顶点间相邻关系的邻接矩阵外,还需用一个一维数组来存储顶点信息,另外还有图的顶点数和边数。
邻接表表示法类似于树的孩子链表表示法。
(2)图的遍历方法有深度优先遍历(Depth-First Traersal)和广度优先遍历(Breadth-First Traversal),简称 DFS和BFS。
DFS对图遍历时尽可能先对纵深方向进行搜索;BFS是类似于树的按层次遍历。
3、实验内容题目1对以邻接矩阵为存储结构的图进行 DFS和 BFS遍历(1) 问题描述:以邻接矩阵为图的存储结构,实现图的DFS和BFS遍历。
(2) 基本要求:建立一个图的邻接矩阵表示,输出顶点的一种DFS和BFS序列。
(3) 测试数据:如图4.18所示。
(4) 实现提示:图的DFS遍历可通过递归调用或用栈来实现。
其思想是:只要当前结点未访问过,就访问该结点,沿着其一条分支深入下去,每深入一个未访问过的结点,就访问这个结点,然后从这个结点继续进行DFS遍历。
在这一过程中,若深入时遇到一个已访问过的结点,则查找是否有与这个结点相邻的下一个未访问过的结点。
若有则继续深人,否则将退回到这个结点的前一个结点,再找下一个相邻的本访问过的结点,……如此进行下去,直到所有的结点都被访问过。
BFS遍历可利用队列来帮助实现,也可以用栈。
实现方法与二叉树的层次遍历类似。
题目2对以邻接表为存储结构的图进行DFS和BFS遍历(1) 问题描述:以邻接表为存储结构,实现图的DFS和BFS遍历。
(2) 基本要求:建立一个图的邻接表存储,输出顶点的一种DFS和BFS序列。
(3) 测试数据:如图4.19所示:(4) 实现提示:以邻接表为存储结构的图的DFS和BFS算法的实现思想与以邻接矩阵为存储结构的实现是一样的。
国家开放大学《数据结构》课程实验报告(实验5——图的存储方式和应用)参考答案

scanf("%d%d",&i,&j);
GA[i][j]=GA[j][i]=1;
}
}
else if(k1==0 && k2!=0) /*建立无向有权图*/
{
printf("输入%d条无向有权边的起点和终点序号及权值!\n",e);
for(k=1; k<=e; k++)
{
scanf("%d%d%d",&i,&j,&w);
printf("输入待处理图的顶点数和边数:");
scanf("%d%d",&n,&e);
/*输入有无向选择和有无权选择*/
printf("输入有无向选择和有无权选择(0为无,非0为有):");
scanf("%d%d",&k1,&k2);
CreateMatrix(gv,ga,n,e,k1,k2); /*建立图的邻接矩阵*/
printf("%6s","∞");
else
printf("%6d",GA[i][j]);
}
printf("\n");
}
}
实验结果:
测试用例1无向无权图如下图所示。
程序运行结果如下:
测试用例2有向有权图如下图所示。
程序运行结果如下:
实
验
小
结
(1)具有n个顶点的图,其邻接矩阵为n×n阶方阵,用二维数组存储,行列下标为0~n-1。
{
int i,j;
printf("顶点");
实验五图的操作及应用

实验五:图的操作及应用实验学时:4实验类型:综合型一、实验目的1.理解图的逻辑结构和物理结构;2.掌握图的邻接矩阵和邻接表存储表示的实现方法;3.掌握图的深度优先和广度优先遍历算法的实现;4.掌握拓扑排序算法的实现方法。
二、实验条件Visual C++ 6.0三、实验原理及相关知识1.图的邻接矩阵和邻接表存储结构的描述;2.图的邻接矩阵和邻接表存储表示的算法;3.图的深度优先和广度优先遍历算法;4.拓扑排序算法。
四、实验步骤1. 实现图的邻接矩阵的存储表示。
2. 实现图的邻接表存储表示。
3. 实现图的深度优先和广度优先遍历算法。
4. 实现拓扑排序算法。
5. 调用以上函数实现以下操作:(1) 建立图。
(2) 输出基于邻接表存储的深度优先和广度优先遍历序列。
(3) 输出有向图的拓扑排序序列。
参考代码:要求:补充完整以下代码使其能够运行通过。
#include "stdio.h"#include "malloc.h"#include "string.h"#define INFINITY 10000// 用整型最大值代替∞#define MAX_VERTEX_NUM 20 // 最大顶点个数#define OK 1#define ERROR 0#define FALSE 0#define TRUE 1#define MAXQSIZE100typedef int QElemType;typedef float VRType;typedef float InfoType;typedef char VertexType;typedef char VexType;//============邻接矩阵的定义============typedef struct {VRType adj;InfoType info; // 该弧相关信息的指针(可无)}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct {VertexType vexs[MAX_VERTEX_NUM][100]; // 顶点向量AdjMatrix arcs; // 邻接矩阵int vexnum,arcnum; // 图的当前顶点数和弧数} MGraph ;//=======================邻接矩阵的定义========//=================================邻接表的定义========= typedef struct ArcNode{ // 表结点int adjvex; // 该弧所指向的顶点的位置struct ArcNode *nextarc; // 指向下一条弧的指针float info; // 网的权值指针} ArcNode;typedef struct{ // 头结点VertexType data[100]; // 顶点信息ArcNode *firstarc; // 第一个表结点的地址} VNode, AdjList[MAX_VERTEX_NUM];typedef struct {AdjList vertices;int vexnum,arcnum; // 图的当前顶点数和弧数}ALGraph;int visited[MAX_VERTEX_NUM];//=================邻接表的定义=========================//=========队列定义和基本操作=============== typedef struct QNode1{QElemType data;struct QNode1 *next;}QNode, *QueuePtr;typedef struct { //链队列的定义QElemType *base;int front;int rear;} SqQueue;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;LinkQueue InitQueue(LinkQueue Q){Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(1);Q.front->next=NULL;return Q;}int EnQueue(LinkQueue* Q, QElemType e){QueuePtr p;if( !(p=(QueuePtr)malloc(sizeof(QNode))) )return ERROR;p->data = e;p->next = NULL;Q->rear->next = p;Q->rear = p;return OK;}int DeQueue(LinkQueue *Q, QElemType *e) {QueuePtr p;if( Q->front == Q->rear )return ERROR;p = Q->front->next;*e = p->data;Q->front->next = p->next;if(Q->rear == p) Q->rear = Q->front;free(p);return OK;}int QueueEmpty(LinkQueue *Q) {if(Q->front ==Q->rear) return 1;else return 0;}int DestroyQueue( LinkQueue *Q ){while(Q->front) {Q->rear=Q->front->next;free(Q->front);Q->front=Q->rear;}return OK;}//===================队列定义和基本操作===============int LocateVex(MGraph G,char *vert){ int i;for(i=0; i<G.vexnum; i++)if(strcmp(G.vexs[i],vert)==0)return i;return -1;}int LocateVex1(ALGraph G,char *vert){ int i;for(i=0; i<G.vexnum; i++)if(strcmp(G.vertices[i].data,vert)==0)return i;return -1;}MGraph CreateGraph_UDN( MGraph G ){//建立无向网G的邻接矩阵int i, j,k;float w;VexType v1[100], v2[100];printf("输入顶点数,数边数:");scanf("%d %d", &G.vexnum, &G.arcnum);for(i=0; i<G.vexnum; i++) // 读入所有的顶点{ printf("输入第%d个顶点的信息:",i+1);scanf("%s", &G.vexs[i]);}for(i=0; i <G.vexnum; i++) //初始化邻接矩阵for(j=0; j<G.vexnum; j++)G.arcs[i][j].adj=INFINITY;for(k=0; k<G.arcnum; k++) { // 输入所有的边printf("输入第%d条边依附的两个顶点和边上的权值:",k+1);scanf("%s %s %f", &v1, &v2, &w);// 查询两个顶点在图中存储的位置i = LocateVex(G, v1);j = LocateVex(G, v2);if (i==-1 || j==-1){printf("输入的边不正确\n"); return;}G.arcs[i][j].adj = w;G.arcs[j][i].adj = G.arcs[i][j].adj;}return G;}ALGraph CreateALGraph_UDN(ALGraph G )//建立无向网G的邻接表{int i,j,k;float w;ArcNode * p;VexType v1[100], v2[100];printf("输入顶点数,数边数:");scanf("%d %d",&(G.vexnum),&(G.arcnum)); /* 读入顶点数和边数*/for(i=0;i<G.vexnum;i++) /* 建立有n个顶点的顶点表*/{printf("输入第%d个顶点的信息:",i+1);scanf("%s",&(G.vertices[i].data)) ; /* 读入顶点信息*/G.vertices[i].firstarc=NULL; /* 顶点的边表头指针设为空*/}for(k=0;k<G.arcnum;k++ ) /* 建立边表*/{printf("输入一条边依附的两个顶点和边上的权值:");scanf("%s %s %f",&v1,&v2,&w) ; /* 读入边<Vi,Vj>的顶点对应序号*/i = LocateVex1(G, v1);j = LocateVex1(G, v2);if (i==-1 || j==-1){printf("输入的边不正确\n"); return;}p=(ArcNode*)malloc(sizeof(ArcNode) ); /* 生成新边表结点p */p->adjvex=j; /* 邻接点序号为j */p->info =w;p->nextarc=G.vertices[i].firstarc; /* 将新边表结点p插入到顶点Vi的链表头部*/G.vertices[i].firstarc=p;p=(ArcNode*)malloc(sizeof(ArcNode) ); /* 生成新边表结点p */p->adjvex=i; /* 邻接点序号为i */p->info =w;p->nextarc=G.vertices[j].firstarc; /* 将新边表结点p插入到顶点Vj的链表头部*/G.vertices[j].firstarc=p;}return G;} /*CreateALGraph*/VisitFunc(char *ch)//输出顶点的信息{printf("%s ",ch);}void DFS(ALGraph G, int v ) {int j;ArcNode *p;VisitFunc(G.vertices[v].data); // 访问第v个顶点visited[v]=TRUE; // 设置访问标志为TRUE(已访问)for(p=G.vertices[v].firstarc; p;p=p->nextarc){j=p->adjvex;if( !visited[j] ) DFS(G, j);}}void DFSTraverse( ALGraph G){//图的深度优先遍历算法int v;for(v=0; v<G.vexnum; v++)visited[v]=FALSE; // 访问标志数组初始化(未被访问) for(v=0;v<G.vexnum;v++)if(!visited[v])DFS(G,v); // 对尚未访问的顶点调用DFS }void BFSTraverse(ALGraph G) //图的广度优先遍历算法{int v,j,u ;ArcNode *p;LinkQueue Q;Q=InitQueue(Q); // 置空的辅助队列Qfor(v=0; v<G.vexnum; v++)visited[v]=FALSE; // 置初值for(v=0; v<G.vexnum; v++)if(!visited[v]){visited[v]=TRUE; // 设置访问标志为TRUE(已访问)VisitFunc(G.vertices[v].data);EnQueue( &Q, v ); // v入队列while(!QueueEmpty(&Q)){DeQueue(&Q,&u); // 队头元素出队并置为ufor(p=G.vertices[u].firstarc; p;p=p->nextarc){j=p->adjvex;if( !visited[j] ){visited[j]=TRUE;VisitFunc(G.vertices[j].data);EnQueue(&Q, j);}}}}DestroyQueue( &Q );}//实现建立有向网的邻接矩阵和邻接表的函数MGraph CreateGraph_DN( MGraph G ){//建立有向网G的邻接矩阵{}ALGraph CreateALGraph_DN(ALGraph G )//建立有向网G的邻接表{}Print_MGraph(MGraph G)//输出图的邻接矩阵表示{int i,j;for(i=0;i<G.vexnum;i++){ for(j=0;j<G.vexnum;j++)printf("%f ",G.arcs[i][j].adj ); /*邻接矩阵*/printf("\n");}}Print_ALGraph(ALGraph G) //输出图的邻接表表示{int i,j;ArcNode *p;for(i=0;i<G.vexnum;i++){printf("%s",G.vertices[i].data ); /* 顶点信息*/p=G.vertices[i].firstarc ;while(p!=NULL) /* 表节点信息*/{printf("->%s",G.vertices[p->adjvex ].data);p=p->nextarc ;} /* 顶点的边表头指针设为空*/printf("\n");}}void FindInDegree(ALGraph G, int *indegree){int i,k;ArcNode *p;for (i=0; i<G.vexnum; ++i){for (p=G.vertices[i].firstarc; p; p=p->nextarc) {{k = p->adjvex;indegree[k]++; }}}}//===================拓扑排序==============================int TopologicalSort(ALGraph G) {// 有向图G采用邻接表存储结构。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
___《数据结构》课程实验报告(实验5—
—图的存储方式和应用)参考答案
数据结构》课程实验报告(实验5——图的存储方式和应用)
学生姓名:
班级:
学号:
指导老师:
实验成绩:
实验概述:
本次实验旨在编写程序建立图的邻接矩阵,并具有一定的通用性。
通过输入图中每个结点与其他结点的关联情况,程序能自动形成邻接矩阵。
实验目的:
1.根据图中顶点和边的信息编制程序建立图的邻接矩阵。
2.程序要有一定的通用性。
实验基本原理:
为保证程序的通用性,适合各种图,在建立图的邻接矩阵算法中增加两个参数k1和k2.k1为表示无向图,否则为有向图;k2为表示边上无权,否则为边上有权。
初始化邻接矩阵时,对角线元素设置为0.若图的边上有权,则其他元素值设为∞;若边上无权,则设为0.
程序代码:
实验内容:
include
define MaxVertexNum 8.//定义图的最大顶点数
define MaxEdgeNum 20.//定义图的最大边数
define MaxValue 1000.//定义相当于∞的常量值
typedef int VertexType。
//定义顶点数据类型VertexType 为整型
typedef VertexType vexlist[MaxVertexNum]。
//定义vexlist 为存储顶点信息的数组类型
typedef int adjmatrix[MaxVertexNum][MaxVertexNum]。
//
定义adjmatrix为存储邻接矩阵的数组类型
void CreateMatrix(vexlist GV。
adjmatrix GA。
int n。
int e。
int k1.int k2)。
//建立图的邻接矩阵
void ShowMatrix(vexlist GV。
adjmatrix GA。
int n)。
//输出图的邻接矩阵
void main()
int n。
e。
k1.k2;
vexlist gv。
//定义保存顶点信息的数组
adjmatrix ga。
//定义保存邻接矩阵的数组
输入一个图的顶点数和边数
printf("输入待处理图的顶点数和边数:");
scanf("%d%d"。
&n。
&e);
输入有无向选择和有无权选择
printf("输入有无向选择和有无权选择(为无,非为有):");
CreateMatrix(gv。
ga。
n。
e。
k1.k2)。
//建立图的邻接矩阵ShowMatrix(gv。
ga。
n)。
//输出图的邻接矩阵
经过修改后,文章格式更加清晰,语言更加简洁明了。
scanf("%d%d%d",&i,&j,&w);
GA[i][j]=w;
首先,我们使用scanf函数输入k1和k2.然后,我们使用CreateMatrix函数建立图的邻接矩阵。
最后,我们使用ShowMatrix函数输出图的邻接矩阵。
CreateMatrix函数用于输入n个顶点和e条边,建立图的邻接矩阵。
其中,k1为0则为无向图,否则为有向图;k2为
0则为无权图,否则为有权图。
我们首先建立顶点数组,然后
初始化图的邻接矩阵。
如果是无向无权图,则输入e条无向无权边的起点和终点序号;如果是无向有权图,则输入e条无向有权边的起点和终点序号及权值;如果是有向无权图,则输入
e条有向无权边的起点和终点序号;如果是有向有权图,则输
入e条有向有权边的起点和终点序号及权值。
修正后的文章:
为了实现图的邻接矩阵存储,我们可以使用二维数组来表示。
具体来说,我们可以通过输入边的起点、终点和权值来构建邻接矩阵。
下面是相应的代码:
scanf("%d%d%d",&i,&j,&w);
GA[i][j]=w;
注意,对于具有n个顶点的图,其邻接矩阵为n×n阶方阵,行列下标为0~n-1.
为了输出邻接矩阵,我们可以编写如下的ShowMatrix函数:
void ShowMatrix(vexlist GV,adjmatrix GA,int n){
int i,j;
printf("顶点");
for(i=0.i<n。
i++)
printf("%6d",GV[i]);
printf("\n");
for(i=0.i<n。
i++)
printf("%6d",GV[i]);
for(j=0.j<n。
j++)
if(GA[i][j]==MaxValue)
printf("%6s","∞");
else
printf("%6d",GA[i][j]);
printf("\n");
该函数将邻接矩阵输出到控制台。
注意,我们需要将给定图的顶点从开始连续编号,以便与数组下标对应。
例如,顶点1和顶点2之间的边,边的起点和终点序号输入0 1即可。
实验结果:
测试用例1无向无权图如下图所示。
程序运行结果如下:
测试用例2有向有权图如下图所示。
程序运行结果如下:
实验小结:本次实验中,我们研究了如何使用邻接矩阵来存储图,并实现了相应的输入和输出函数。
在实现过程中,需要注意将顶点从开始连续编号,以便与数组下标对应。