数据结构--图的实验报告
数据结构实验———图实验报告
数据结构实验报告目的要求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 -2typedef 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->nextarcprintf"%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->nextarcif --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; //若已是最后一个顶点;返回0else returnp->nextarc->adjvex; //返回下一个邻接顶点的序号}//采用邻接表存储实现无向图的深度优先递归遍历void DFSALGraph G;int i{ int w;visitedi=True; //访问第i个顶点printf"%d->";i;forw=FirstAdjVexG;i;w;w=NextAdjVexG;i;wifvisitedw 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; //访问顶点iprintf"%d->";i;EnQueueQ;i; //将序号i入队列whileQ.front ==Q.rear //若队列不空;继续{DeQueueQ;u; //将队头元素出队列并置为uforw=FirstAdjVexG;u;w;w=NextAdjV exG;u;wifvisitedw //对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实验总结这次的图的操作实验;与树的操作类似;但又比树复杂;包含更多的存储结构和遍历方法的操作;而且图的遍历需要沿着弧进行;以便输出弧上的信息..本实验中图的遍历采用邻接表的存储结构;在输入图的信息时;首先要画出图的邻接表信息..图有两种遍历的形式;一种为深度优先搜索;另一种为广度优先搜索..由于能力有限;没能实现图的深度非递归优先搜索;而是实现了图的深度递归优先搜索..本实验基本完成了图的操作;也学到了很多关于图的知识和算法..。
数据结构实验报告--图
数据结构实验报告--图【数据结构实验报告--图】【一、实验目的】本实验旨在掌握图的基本概念、存储结构以及相关操作,并通过实验加深对图的理解。
【二、实验环境】操作系统:Windows 10编程语言:C++开发工具:Dev-C++ 5.11【三、实验内容】1.图的定义与基本概念1.1 图的定义:有向图、无向图1.2 图的基本概念:顶点、边、路径、路径长度2.图的存储结构2.1 邻接矩阵表示法2.2 邻接表表示法3.图的操作3.1 图的创建①手动输入图的顶点和边②从文件中读取图的顶点和边3.2 图的遍历①深度优先遍历(DFS)②广度优先遍历(BFS)3.3 图的最小树① Prim算法② Kruskal算法3.4 图的最短路径① Dijkstra算法② Floyd算法4.实验结果分析4.1 图的创建结果4.2 图的遍历结果4.3 图的最小树结果4.4 图的最短路径结果【四、实验步骤】1.定义图的数据结构和相关操作的函数原型。
2.实现图的存储结构和相关操作的函数实现。
3.开发主程序,包括菜单、用户输入、调用图操作函数等。
4.运行程序,测试各个功能是否正常进行。
5.根据运行结果分析,进行必要的调试和优化。
【五、实验结果】1.图的创建结果:●手动输入图的顶点和边:●顶点数.10●边数.15●从文件中读取图的顶点和边:●顶点数.8●边数.122.图的遍历结果:●深度优先遍历:●遍历路径.1 -> 2 -> 4 -> 5 -> 3●广度优先遍历:●遍历路径.1 -> 2 -> 3 -> 4 -> 53.图的最小树结果:●Prim算法:●最小树顶点集合:{1, 2, 4, 5}●最小树边集合:{(1, 2), (2, 4), (2, 5)}●Kruskal算法:●最小树边集合:{(1, 2), (2, 4), (2, 5)}4.图的最短路径结果:●Dijkstra算法:●从顶点1到其他顶点的最短路径长度:●1 -> 2、2●1 -> 3、5●1 -> 4、4●1 -> 5、6●Floyd算法:●图的最短路径邻接矩阵:●0 2 5 4 6●2 0 3 1 3●5 3 0 5 4●4 1 5 0 2●6 3 4 2 0【附件】无【法律名词及注释】1.顶点:图中的一个节点,可以表示实体或事件。
数据结构图的实验报告
数据结构图的实验报告数据结构图的实验报告引言:数据结构图是计算机科学中重要的概念之一。
它是一种用图形表示数据元素之间关系的数据结构,广泛应用于算法设计、程序开发和系统优化等领域。
本实验报告旨在介绍数据结构图的基本原理、实验过程和结果分析。
一、实验目的本次实验的主要目的是掌握数据结构图的基本概念和操作方法,以及通过实验验证其在解决实际问题中的有效性。
具体而言,我们将通过构建一个社交网络关系图,实现对用户关系的管理和分析。
二、实验方法1. 确定数据结构在本次实验中,我们选择了无向图作为数据结构图的基础。
无向图由顶点集和边集组成,每条边连接两个顶点,且没有方向性。
2. 数据输入为了模拟真实的社交网络,我们首先需要输入一组用户的基本信息,如姓名、年龄、性别等。
然后,根据用户之间的关系建立边,表示用户之间的交流和联系。
3. 数据操作基于构建好的数据结构图,我们可以进行多种操作,如添加用户、删除用户、查询用户关系等。
这些操作将通过图的遍历、搜索和排序等算法实现。
三、实验过程1. 数据输入我们首先创建一个空的无向图,并通过用户输入的方式逐步添加用户和用户关系。
例如,我们可以输入用户A和用户B的姓名、年龄和性别,并建立一条边连接这两个用户。
2. 数据操作在构建好数据结构图后,我们可以进行多种操作。
例如,我们可以通过深度优先搜索算法遍历整个图,查找与某个用户具有特定关系的用户。
我们也可以通过广度优先搜索算法计算某个用户的社交网络影响力,即与该用户直接或间接相连的其他用户数量。
3. 结果分析通过实验,我们可以观察到数据结构图在管理和分析用户关系方面的优势。
它能够快速地找到用户之间的关系,帮助我们了解用户的社交网络结构和影响力。
同时,数据结构图也为我们提供了一种可视化的方式来展示用户之间的关系,使得分析更加直观和易于理解。
四、实验结果通过实验,我们成功构建了一个社交网络关系图,并实现了多种数据操作。
我们可以根据用户的姓名、年龄和性别等信息进行查询,也可以根据用户之间的关系进行遍历和排序。
数据结构试验报告-图的基本操作
中原工学院《数据结构》实验报告学院:计算机学院专业:计算机科学与技术班级:计科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、理解并掌握图的逻辑结构和物理结构——邻接矩阵、邻接表2、掌握图的构造方法3、掌握图的邻接矩阵、邻接表存储方式下基本操作的实现算法4、掌握图的深度优先遍历和广度优先原理二、实验内容:1、输入顶点数、边数、每个顶点的值以及每一条边的信息,构造一个无向图G,并用邻接矩阵存储改图。
2、输入顶点数、边数、每个顶点的值以及每一条边的信息,构造一个无向图G,并用邻接表存储该图3、深度优先遍历第一步中构造的图G,输出得到的节点序列4、广度优先遍历第一部中构造的图G,输出得到的节点序列三、实验要求:1、无向图中的相关信息要从终端以正确的方式输入;2、具体的输入和输出格式不限;3、算法要具有较好的健壮性,对错误操作要做适当处理;4、程序算法作简短的文字注释。
四、程序实现及结果:1、邻接矩阵:#include <stdio.h>#include <malloc.h>#define VERTEX_MAX 30#define MAXSIZE 20typedef struct{intarcs[VERTEX_MAX][VERTEX_MAX] ;int vexnum,arcnum;} MGraph; void creat_MGraph1(MGraph *g) { int i,j,k;int n,m;printf("请输入顶点数和边数:");scanf("%d%d",&n,&m);g->vexnum=n;g->arcnum=m;for (i=0;i<n;i++)for (j=0;j<n;j++)g->arcs[i][j]=0;while(1){printf("请输入一条边的两个顶点:\n");scanf("%d%d",&i,&j);if(i==-1 || j==-1)break;else if(i==j || i>=n || j>=n){printf("输入错误,请重新输入!\n");}else{g->arcs[i][j]=1;g->arcs[j][i]=1;}}}void printMG(MGraph *g) {int i,j;for (i=0;i<g->vexnum;i++){for (j=0;j<g->vexnum;j++)printf(" %d",g->arcs[i][j]);printf("\n");}printf("\n");}main(){int i,j;int fg;MGraph *g1;g1=(MGraph*)malloc(sizeof(MGraph));printf("1:创建无向图的邻接矩阵\n\n");creat_MGraph1(g1);printf("\n此图的邻接矩阵为:\n"); printMG(g1);}2、邻接链表:#include<stdio.h>#include<malloc.h>#define MAX_SIZE 10typedef struct node{int vertex;struct node *next;}node,adjlist[MAX_SIZE];adjlist g;int visited[MAX_SIZE+1];int que[MAX_SIZE+1];void creat(){int n,e;int i;int start,end;node *p,*q,*pp,*qq;printf("输入无向图的顶点数和边数:");scanf("%d%d",&n,&e);for(i = 1; i <= n ; i++){visited[i] = 0;g[i].vertex = i;g[i].next = NULL;}printf("依次输入边:\n");for(i = 1; i <= e ; i++){scanf("%d%d",&start,&end);p=(node *)malloc(sizeof(node));p->vertex = end;p->next = NULL;q = &g[start];while(q->next)q = q->next;q->next = p;p1=(node*)malloc(sizeof(node));p1->vertex = start;p1->next = NULL;q1 = &g[end];while(qq->next)q1 = q1->next;q1->next = p1;}}void bfs(int vi){int front,rear,v;node *p;front =0;rear = 1;visited[vi] = 1;que[0] = vi;printf("%d ",vi);while(front != rear){v = que[front];p = g[v].next;while(p){if(!visited[p->vertex]){visited[p->vertex]= 1;printf("%d",p->vertex);que[rear++] = p->vertex;}p = p->next;}front++;}}int main(){creat();bfs(1);printf("\n");return 0;}五.实验心得与体会:(1)通过这次实验,使我基本上掌握了图的存储和遍历,让我弄清楚了如何用邻接矩阵和邻接链表对图进行存储(2)深度优先遍历和广度优先遍历都有着各自的优点,通过程序逐步调试,可以慢慢的理解这两种遍历方法的内涵和巧妙之处。
数据结构实验报告--图
数据结构实验报告--图
数据结构实验报告--图
1、实验目的
本实验主要旨在通过实践操作,深入理解图这种数据结构的基本概念、性质和基本操作,掌握图的存储结构与常见算法。
2、实验环境
本次实验使用编程语言C++,在Windows平台下进行开发和运行。
3、实验内容
3.1 图的定义与基本概念
在本章中,我们将介绍图的基本概念,包括有向图与无向图、顶点与边、度与入度出度、连通性等。
3.2 图的存储结构
在本章中,我们将介绍图的几种存储结构,包括邻接矩阵、邻接表和十字链表,以及它们的优缺点和适用场景。
3.3 图的遍历
在本章中,我们将介绍图的两种常用的遍历算法,即深度优先搜索(DFS)和广度优先搜索(BFS),并分别给出它们的实现代码和应用场景。
3.4 最短路径
在本章中,我们将介绍图的最短路径问题,包括单源最短路径和全源最短路径。
我们将使用Dijkstra算法和Floyd-Warshall算法来解决这些问题,并给出它们的实现代码和应用场景。
3.5 最小树
在本章中,我们将介绍图的最小树问题,即找到一棵树使得树上的边的权值之和最小。
我们将使用Prim算法和Kruskal算法来解决这个问题,并给出它们的实现代码和应用场景。
4、实验步骤和结果
在本章中,我们将详细介绍实验的具体步骤,并给出实验结果的详细分析和说明。
5、实验总结
在本章中,我们将对整个实验进行总结,总结实验中遇到的问题、解决方案和经验教训。
6、附件
本实验报告所涉及的附件包括实验代码和运行结果的截图。
7、法律名词及注释
本文所涉及的法律名词和注释详见附件中的相关文件。
数据结构图实验报告
数据结构图实验报告数据结构图实验报告1. 引言数据结构是计算机科学中的重要概念之一,它研究数据的组织、存储和管理方式。
图作为一种重要的数据结构,广泛应用于各个领域,如网络拓扑、社交网络分析等。
本实验旨在通过实际操作,深入理解数据结构图的基本概念和操作。
2. 实验目的本实验的主要目的是掌握图的基本概念和相关操作,包括图的创建、遍历、搜索和最短路径算法等。
3. 实验环境本实验使用C++语言进行编程,采用图的邻接矩阵表示法进行实现。
4. 实验内容4.1 图的创建在实验中,我们首先需要创建一个图。
通过读取输入文件中的数据,我们可以获得图的顶点数和边数,并根据这些信息创建一个空的图。
4.2 图的遍历图的遍历是指从图的某个顶点出发,按照一定的规则依次访问图中的其他顶点。
常用的图的遍历算法有深度优先搜索(DFS)和广度优先搜索(BFS)。
我们可以通过实验来比较这两种遍历算法的效率和应用场景。
4.3 图的搜索图的搜索是指从图的某个顶点出发,找到与之相关的特定顶点或边。
常用的图的搜索算法有深度优先搜索和广度优先搜索。
在实验中,我们可以通过输入特定的顶点或边,来观察图的搜索算法的执行过程和结果。
4.4 图的最短路径算法图的最短路径算法是指在图中找到两个顶点之间的最短路径。
常用的最短路径算法有迪杰斯特拉算法和弗洛伊德算法。
通过实验,我们可以比较这两种算法的执行效率和应用场景。
5. 实验结果与分析通过实验,我们可以得到以下结论:- 图的邻接矩阵表示法在创建和操作图的过程中具有较高的效率。
- 深度优先搜索算法适用于查找图中的连通分量和回路等问题。
- 广度优先搜索算法适用于查找图中的最短路径和最小生成树等问题。
- 迪杰斯特拉算法适用于求解单源最短路径问题,而弗洛伊德算法适用于求解多源最短路径问题。
6. 实验总结通过本次实验,我们深入学习了数据结构图的基本概念和相关操作。
图作为一种重要的数据结构,具有广泛的应用价值。
在今后的学习和工作中,我们可以运用所学的知识,解决实际问题,提高工作效率。
数据结构实验报告—图
《算法与数据结构》课程实验报告一、实验目的1.实现图的存储结构;2.通过图的相关算法实现,掌握其算法思想。
二、实验内容及要求1.无向带权图的存储结构(邻接矩阵、邻接表等自选)2.实现图的相关算法(1)计算指定顶点的度(2)图的深度优先遍历和广度优先遍历算法(3)分别使用Kruskal和Prim算法求解该图的最小生成树三、系统分析(1)数据方面:定义图的模板基类,在模板类定义中的数据类型参数表<class T,class E>中,T是定点数据的类型,E是边上所附数据的类型。
这个模板基类是按照带权无向图来定义的。
在该实验中定点的数据的类型为char型,边上所附数据的类型为int型。
且图的创建为无向图。
(2)功能方面:1.能够实现图的创建以及图的输出。
2.能够返回顶点在图中位置以及图中位置对应顶点的值。
3.返回当前图中的边数与顶点数。
4.返回输入边的权值。
5.能够插入一个顶点或插入顶点与之相关联的边。
6.删除边或删除顶点与之相关联的边。
7.计算顶点的度。
8.实现深度优先搜索、广度优先搜索遍历。
9.Kruskal算法、Prim算法生成最小生成树。
四、系统设计(1)设计的主要思路根据实验要求,首先确定图的存储结构,在根据存储结构编写模板类,并将需要实现的功能代码完善,再写出实现各个功能的菜单并进行调试。
由于在编写由图生成最小生成树中采用了最小堆以及并查集的算法,故需要将这两个个类的代码完成并进行调试。
最后将此次实验所涉及的类全部整理完全后,通过之前编写的菜单对功能进行依次调试,完成此次实验。
(2)数据结构的设计图是非线性结构,它的每一个顶点可以与多个其他顶点相关联,各顶点之间的关系是任意的。
可以用很多方法来存储图结构。
在此采用邻接矩阵来存储图结构。
首先将所有顶点的信息组织成一个顶点表,然后利用一个矩阵来表示各顶点之间的邻接关系,称为邻接矩阵。
下面针对带权无向图的邻接矩阵作出说明。
其中有一个类型为顺序表的顶点表向量VerticesList,用以存储顶点的信息,还有一个作为邻接矩阵使用的二维数组Edge,用以存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关。
数据结构图综合实验实验报告宁波工程学院
数据结构图综合实验实验报告宁波工程学院图综合实验实验报告一、实验目的1)熟悉图的基本操作。
2)掌握求图的最短路径算法。
3)加深对图的理解,逐步培养解决实际问题的编程能力。
班级:计科12-1 学号:124010101姓名:实验日期:二、实验环境装有Visual C++的计算机。
本次实验共计4学时。
三、实验内容【基本要求】给定n个村庄之间的交通图。
若村庄i和j之间有路可通,则i和j用边连接,边上的权值Wij表示这条道路的长度。
现打算在这n个村庄中选定一个村庄建一所医院。
编写如下算法:求出该医院应建在哪个村庄,才能使距离医院最远的村庄到医院的路程最短。
求出该医院应建在哪个村庄,能使其它所有村庄到医院的路径总和最短。
【提示】? 对于问题,可以先求出每个村庄到其它所有村庄的最短路径,保存其最大值;然后在这些最大值中找出一个最小值。
? 对于问题,可以先求出每个村庄到其它所有村庄的最短路径,保存其累加和;然后在这些和中找出一个最小值。
? 自己设定n个村庄的交通图。
例如下图所示:四、重要数据结构typedef struct/*图的定义*/ { int edges[MAXV][MAXV]; /*邻接矩阵*/ int n,e;/*顶点数,弧数*/ } MGraph;/*图的邻接矩阵类型*/ 五、实现思路分析void Dijkstra(MGraph g,int v); //狄克斯特拉算法void Dispath(int dist,int path,int s,int n,int v); void Ppath(int path,int i,int v); void He(MGraph g,int v);//情况一void Slove(MGraph g,int v);//情况二六、程序调试问题分析狄克斯特拉算法输出的dist【i】总为0,在主函数对[i][j]先赋值即可。
七、实验总结通过这次实验,我对最小生成树有了更好的认识。
数据结构实验报告图的存储
数据结构实验报告图的存储数据结构图实验报告一、实验目的和要求(1)掌握图的相关概念,包括图,有向图,无向图,完全图,子图,连通图,度,入度,出度,简单回路和环等定义。
(2)重点掌握图的各种存储结构,包括邻接矩阵和邻接表等。
(3)重点掌握图的基本运算,包括创建图,输出图,深度优先遍历,广度优先遍历等。
(4)掌握图的其他运算,包括最小生成树,最短路径,拓扑排序和关键路径等算法。
(5)灵活运用图这种数据结构解决一些综合应用问题。
二、实验内容和方法(1)实验内容:1、编写一个程序algo8-1.cpp,实现不带权图和带权图的邻接矩阵与邻接表的相互转换算法、输出邻接矩阵与邻接表的算法,并在此基础上设计一个程序exp8-1.cpp实现如下功能:①建立如图1所示的有向图G的邻接矩阵,并输出;②由有向图G的邻接矩阵产生邻接表,并输出;③再由②的邻接表产生对应的邻接矩阵,并输出。
图12、编写一个程序algo8-2.cpp,实现图的遍历运算,并在此基础上设计一个程序exp8-2.cpp完成如下功能:①输出图1所示的有向图G从顶点0开始的深度优先遍历序列(递归算法);②输出图1所示的有向图G从顶点0开始的深度优先遍历序列(非递归算法);③输出图1所示的有向图G从顶点0开始的广度优先遍历序列。
3、设计一个程序exp8-3.cpp,采用邻接表存储图,并输出图8.1(a)中从指定顶点1出发的所有深度优先遍历序列。
(2)实验方法:1、综合运用课本所学的知识,用不同的算法实现在不同的程序功能。
2、结合指导老师的指导,解决程序中的问题,正确解决实际中存在的异常情况,逐步改善功能。
3、根据实验内容,编译程序。
三、实验环境:Windows 7,Visual C++6.0三、实验过程描述文件graph.h中定义了图的邻接矩阵表示类型和邻接表表示类型,该头文件在以下三个实验中都会使用到。
其代码如下:#ifndef GRAPH_H_INCLUDED#define GRAPH_H_INCLUDEDtypedef int InfoType;#define MAXV 100 //最大顶点个数#define INF 32767 //INF表示无限大//以下定义邻接矩阵类型typedef struct{int no;InfoType info;}VertexType;typedef struct{int edges[MAXV][MAXV];int n,e;VertexType vexs[MAXV];}MGraph;//以下定义邻接表类型typedef struct ANode{int adjvex;struct ANode* nextarc;InfoType info;}ArcNode;typedef int Vertex;typedef struct VNode{Vertex data;实验①源程序。
数据结构 图实验报告
数据结构图实验报告数据结构图实验报告引言:数据结构是计算机科学中非常重要的一个概念,它用于存储和组织数据,使得数据的操作更加高效和方便。
图是一种常见的数据结构,它由节点和边组成,用于表示各种实际问题中的关系和连接。
本实验旨在通过实际操作,深入理解图的基本概念和常见操作。
实验目的:1. 理解图的基本概念和特性;2. 掌握图的存储结构和基本操作;3. 实现图的遍历算法;4. 分析图的应用场景。
实验过程:1. 图的存储结构:在本次实验中,我们选择邻接矩阵来存储图。
邻接矩阵是一个二维数组,其中行和列分别表示图中的节点,数组元素表示节点之间的边的关系。
具体而言,如果节点i和节点j之间存在边,则邻接矩阵中的第i行第j列元素为1;否则为0。
2. 图的基本操作:在实验中,我们实现了以下几个图的基本操作:- 添加节点:通过向邻接矩阵中添加一行一列,并设置对应的边的关系,来添加一个节点;- 添加边:通过修改邻接矩阵中对应元素的值,来添加一条边;- 删除节点:通过删除邻接矩阵中对应行和列,并更新其他节点的索引,来删除一个节点;- 删除边:通过修改邻接矩阵中对应元素的值,来删除一条边;- 查找节点:通过遍历邻接矩阵,找到对应节点的索引;- 查找边:通过遍历邻接矩阵,找到对应边的关系。
3. 图的遍历算法:在实验中,我们实现了深度优先搜索(DFS)和广度优先搜索(BFS)两种图的遍历算法。
DFS通过递归的方式,先访问当前节点,再依次访问相邻节点,直到所有节点都被访问。
BFS则通过队列的方式,先访问当前节点,再依次访问当前节点的相邻节点,直到所有节点都被访问。
实验结果:通过实验,我们成功实现了图的存储结构和基本操作,并且正确实现了DFS和BFS两种遍历算法。
我们对不同规模的图进行了测试,并分析了算法的时间复杂度。
实验结果表明,邻接矩阵的存储结构在添加和删除节点时的时间复杂度较高,而在查找节点和边时的时间复杂度较低。
DFS和BFS的时间复杂度都为O(V+E),其中V表示节点数,E表示边数。
数据结构实验报告(图)
实验报告课程:数据结构(c语言)实验名称:图的建立、基本操作以及遍历系别:数字媒体技术实验日期: 12月13号 12月20号专业班级:媒体161 组别:无姓名:学号:实验报告内容验证性实验一、预习准备:实验目的:1、熟练掌握图的结构特性,熟悉图的各种存储结构的特点及适用范围;2、熟练掌握几种常见图的遍历方法及遍历算法;实验环境:Widows操作系统、VC6.0实验原理:1.定义:基本定义和术语图(Graph)——图G是由两个集合V(G)和E(G)组成的,记为G=(V,E),其中:V(G)是顶点(V ertex)的非空有限集E(G)是边(Edge)的有限集合,边是顶点的无序对(即:无方向的,(v0,v2))或有序对(即:有方向的,<v0,v2>)。
邻接矩阵——表示顶点间相联关系的矩阵设G=(V,E) 是有n 1 个顶点的图,G 的邻接矩阵A 是具有以下性质的n 阶方阵特点:无向图的邻接矩阵对称,可压缩存储;有n个顶点的无向图需存储空间为n(n+1)/2有向图邻接矩阵不一定对称;有n个顶点的有向图需存储空间为n²无向图中顶点V i的度TD(V i)是邻接矩阵A中第i行元素之和有向图中,顶点V i的出度是A中第i行元素之和顶点V i的入度是A中第i列元素之和邻接表实现:为图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(有向图中指以Vi为尾的弧)特点:无向图中顶点Vi的度为第i个单链表中的结点数有向图中顶点Vi的出度为第i个单链表中的结点个数顶点Vi的入度为整个单链表中邻接点域值是i的结点个数逆邻接表:有向图中对每个结点建立以Vi为头的弧的单链表。
图的遍历从图中某个顶点出发访遍图中其余顶点,并且使图中的每个顶点仅被访问一次过程.。
遍历图的过程实质上是通过边或弧对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用的存储结构。
图的遍历有两条路径:深度优先搜索和广度优先搜索。
数据结构与算法课程实验报告-图的应用
(前面可加目录页)一. 实验目的1.理解图的概念并熟悉有关术语。
2.熟练掌握邻接矩阵表示法和邻接表表示法。
3.掌握连通图遍历的基本思想和算法。
4.掌握最小生成树的有关概念和算法实现。
5.掌握最短路径有关概念和算法。
6.掌握拓扑排序的概念及实现。
二. 实验内容1.对给定的图,用邻接矩阵实现该图的深度优先搜索遍历。
2.对给定的图,用邻接矩阵实现该图的广度优先搜索遍历。
3.对给定的图,用邻接表实现该图的深度优先搜索遍历。
4.对给定的图,用邻接表实现该图的广度优先搜索遍历。
三. 文献综述数据结构(C语言版)习题解答及实训指导------------李根强、谢月娥四. 实验思路和技术路线(数据结构及算法)(1,2)算法设计:首先定义图的类型为结构型,包含图中的顶点信息和邻接矩阵两项信息,然后将输入边的信息建立邻接矩阵,再将深度搜索优先遍历和广度优先搜索遍历写成子函数的形式,在主函数中调用他们;(3,4)算法设计:首先定义图的邻接表数据类型,建立该图的邻接表,然后再用子函数写出深度优先搜索遍历和广度优先搜索遍历的算法,在主函数中调用它;五. 实验结果分析及心得(1)对给定的图,用邻接矩阵实现该图的深度优先和广度优先搜索遍历:<1 给定的图如下:< 2 广度优先和深度优先遍历程序如下:#include<stdio.h>#define n 8 //图中顶点数#define e 15 //图中边数#define elemtype intint visited[n+1]; //访问标志数组,为false表示未访问,为true表示已访问struct graph //定义图的数据类型{elemtype v[n+1]; //存放顶点信息 v1,v2,...,vn,不使用v[0]存储空间int arcs[n+1][n+1]; //邻接矩阵}g;void creatadj() //建立邻接矩阵{int i,j,k;printf("请输入%d个顶点信息\n",n);for(k=1;k<=n;k++)scanf("%d",&g.v[k]); //输入顶点信息for(i=1;i<=n;i++)for(j=1;j<=n;j++)g.arcs[i][j]=0;for(k=1;k<=e;k++){printf("请输入第%d条边,共%d条边",k,e);scanf("%d%d",&i,&j); //输入一条边(i,j)g.arcs[i][j]=1;g.arcs[j][i]=1;}}void dfs(int i) //从顶点i出发进行深度优先搜索遍历 {int j;printf("%d",g.v[i]); //输出访问顶点visited[i]=1; //全局数组访问标记置1表示已访问for(j=1;j<=n;j++)if((g.arcs[i][j]==1)&&(!visited[j]))dfs(j);}void bfs(int i) //从顶点i出发进行广度优先搜索遍历{int q[n+1]; //q为队列int f,r,j; //f,r分别为队列头指针、尾指针f=r=0; //设置空队列printf("%d",g.v[i]); //输出访问顶点visited[i]=1; //全局数组标记置1表示已访问r++;q[r]=i; //入队列while(f<r){f++;i=q[f]; //出队列for(j=1;j<=n;j++)if((g.arcs[i][j]==1)&&(!visited[j])){printf("%d",g.v[j]);visited[j]=1;r++;q[r]=j; //入队列}}}main(){int i,j;int yn=1;creatadj(); //建立邻接矩阵for(i=1;i<=n;i++) //输出邻接矩阵{for(j=1;j<=n;j++)printf("%d",g.arcs[i][j]);printf("\n");}while(yn==1){for(i=1;i<=n;i++)visited[i]=0;printf("请输入深度优先搜索开始访问的顶点");scanf("%d",&i);printf("\n");printf("从%d出发的深度优先搜素遍历序列为\n",i);dfs(i);printf("\n继续进行深度优先搜索吗(1/2)?");scanf("%d",&yn);}yn=1;while(yn==1){for(i=1;i<=n;i++)visited[i]=0;printf("请输入广度优先搜索开始访问的顶点");scanf("%d",&i);printf("\n");printf("从%d出发的广度优先搜索遍历序列为\n",i);bfs(i);printf("\n继续进行广度优先搜索吗 (1/2) ?");scanf("%d",&yn);}}运行结果:#define e 15 //图中边数#define elemtype intint visited[n+1];istruct link{elemtype data;struct link *next;};struct graph{struct link a[n+1];}g;void creatlink(){int i,j,k;struct link *s;for(i=1;i<=n;i++){g.a[i].data=i;g.a[i].next=NULL;}for(k=1;k<=e;k++){printf("请输入一条边");scanf("%d%d",&i,&j);s=(struct link *)malloc(sizeof(struct link));s->data=j;s->next=g.a[i].next;g.a[i].next=s;s=(struct link *)malloc(sizeof(struct link));s->data=i;s->next=g.a[j].next;g.a[j].next=s;}}void dfs1(int i){struct link *p;printf("%d",g.a[i].data);visited[i]=1;p=g.a[i].next;while(p!=NULL){if(!visited[p->data])dfs1(p->data);p=p->next;}}void bfs1(int i){int q[n+1];int f,r;struct link *p;f=r=0;printf("%d",g.a[i].data);visited[i]=1;r++;q[r]=i;while(f<r){f++;i=q[f];p=g.a[i].next;while(p!=NULL){if(!visited[p->data]){printf("%d",g.a[p->data].data);visited[p->data]=1;r++;q[r]=p->data;}p=p->next;}}}main(){struct link *p;int yn=1,i;creatlink();while(yn==1){for(i=1;i<=n;i++){p=g.a[i].next;printf("%d->",g.a[i].data);while(p->next!=NULL){printf("%d->",p->data);p=p->next;}printf("%d\n",p->data);}while(yn==1){for(i=1;i<=n;i++)visited[i]=0;printf("请输入深度优先搜索开始访问的顶点");scanf("%d",&i);printf("\n");printf("从%d出发的深度优先搜索遍历序列为\n",i);dfs1(i);printf("\n继续进行深度优先搜索吗(1/2)?");scanf("%d",&yn);}yn=1;while(yn==1){for(i=1;i<=n;i++)。
数据结构实验报告--图
.数据结构实验报告图一、实验目的1、熟悉图的结构和相关算法。
二、实验内容及要求1、编写创建图的算法。
2、编写图的广度优先遍历、深度优先遍历、及求两点的简单路径和最短路径的算法。
三、算法描述1、图的邻接表存储表示:对图的每个顶点建立一个单链表,第i个单链表表示所有依附于第i个点的边(对于有向图表示以该顶点为尾的弧);链表的每个节点存储两个信息,该弧指向的顶点在图中的位置(adjvex)和指向下一条弧的指针(nextarc)。
每个连表的头结点存储顶点的数据:顶点信息(data)和指向依附于它的弧的链表域。
存储表示如下:typedef struct ArcNode {int adjvex; // 该弧所指向的顶点的位置struct ArcNode *nextarc;// 指向下一条弧的指针// InfoType *info; // 该弧相关信息的指针} ArcNode;typedef struct VNode {char data; // 顶点信息int data2;int sngle;ArcNode *firstarc;// 指向第一条依附该顶点的弧} VNode, AdjList[MAX_NUM];typedef struct {AdjList vertices;int vexnum, arcnum;int kind; // 图的种类标志} ALGraph;2、深度优先搜索:假设初始态是图中所有定点未被访问,从图中的某个顶点v开始,访问此顶点,然后依次从v的未访问的邻接点出发深度优先遍历,直至途中所有和v有相同路径的点都被访问到;若图中仍有点未被访问,则从图中另选一个未被访问的点作为起点重复上述过程,直到图中所有点都被访问到。
为了便于区分途中定点是否被访问过,需要附设一个访问标致数组visited [0..n-1],将其初值均设为false,一旦某个顶点被访问,将对应的访问标志赋值为true。
2、广度优先搜索:假设初始态是图中所有顶点未被访问,从图中的某个顶点v开始依次访问v的各个未被访问的邻接点,然后分别从这些邻接点出发以此访问他们的邻接点,并使“先被访问的邻接顶点”先于“后被访问的邻接顶点”被访问,直至图中所有已被访问过的顶点的邻接顶点都被访问。
数据结构图的实验报告
数据结构图的实验报告
实验目的:学习并掌握数据结构图的基本知识和应用,了解其在程序设计中的重要性和作用。
实验环境:Windows10操作系统,CodeBlocks编译器
实验步骤:
1. 学习数据结构图的基本知识,包括用图形表示数据结构和数据结构之间的关系,以及不同类型的数据结构图的用途和特点。
2. 在CodeBlocks编译器中新建工程,建立一个以图形方式显
示树形结构的简单程序。
3. 建立一个树形结构示例程序,包括输入树中节点的数据和节点之间的关系,并在程序中显示树形结构图。
4. 对程序进行调试和测试,检查程序的正确性和稳定性。
5. 对程序进行优化,尽可能提高程序的运行效率和性能。
实验结果:
经过以上步骤的操作和测试,程序能够正确地显示树形结构,并在输入节点数据时自动建立节点间的关系,从而实现了树形结构图的基本功能。
此外,程序还具有调试和优化的能力,可以进一步提高其稳定性和性能。
实验结论:
学习并掌握数据结构图的基本知识和应用,不仅可以提高程序设计的效率和质量,还可以更好地理解程序运行的机理和原理,从而更好地应用和开发各种应用程序和系统。
因此,数据结构图在计算机科学和工程中具有重要的作用和价值。
数据结构实验报告 图
数据结构实验报告图一、实验目的本次实验的主要目的是深入理解和掌握图这种数据结构的基本概念、存储结构和相关算法,并通过实际编程实现来提高对图的操作和应用能力。
二、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。
三、实验内容(一)图的存储结构1、邻接矩阵邻接矩阵是用一个二维数组来表示图中顶点之间的关系。
如果顶点i 和顶点 j 之间有边相连,则数组中对应的元素值为 1;否则为 0。
这种存储结构简单直观,适用于顶点数较少且边数较多的稠密图。
2、邻接表邻接表是为图的每个顶点建立一个单链表,链表中存储的是与该顶点相邻的顶点信息。
这种存储结构在存储空间上比较节省,适用于顶点数较多且边数较少的稀疏图。
(二)图的遍历算法1、深度优先遍历(DepthFirst Search,简称 DFS)从图中的某个顶点出发,沿着一条路径尽可能深地访问顶点,直到无法继续前进,然后回溯到上一个未完全访问的顶点,继续进行深度优先搜索。
2、广度优先遍历(BreadthFirst Search,简称 BFS)从图中的某个顶点出发,先访问其所有相邻的顶点,然后再依次访问这些相邻顶点的相邻顶点,以此类推,逐层向外扩展。
(三)图的最短路径算法1、迪杰斯特拉(Dijkstra)算法用于求解单源最短路径问题,即从一个给定的源顶点到图中其他所有顶点的最短路径。
2、弗洛伊德(Floyd)算法用于求解任意两个顶点之间的最短路径。
四、实验步骤(一)邻接矩阵的实现```cppinclude <iostream>using namespace std;const int MAX_VERTEX_NUM = 100;class Graph {private:int vertexNum;int edgeNum;int adjMatrixMAX_VERTEX_NUMMAX_VERTEX_NUM;public:Graph(int vNum) {vertexNum = vNum;edgeNum = 0;for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){adjMatrixij = 0;}}}void addEdge(int i, int j) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjMatrixij = 1;adjMatrixji = 1;edgeNum++;}}void printGraph(){for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){cout << adjMatrixij <<"";}cout << endl;}}};int main(){Graph g(5);gaddEdge(0, 1);gaddEdge(0, 2);gaddEdge(1, 2);gaddEdge(2, 3);gaddEdge(3, 4);gprintGraph();return 0;}```(二)邻接表的实现```cppinclude <iostream>include <vector>using namespace std;const int MAX_VERTEX_NUM = 100; class Graph {private:int vertexNum;vector<int> adjListMAX_VERTEX_NUM;public:Graph(int vNum) {vertexNum = vNum;}void addEdge(int i, int j) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjListipush_back(j);adjListjpush_back(i);}}void printGraph(){for (int i = 0; i < vertexNum; i++){cout << i <<":";for (int j = 0; j < adjListisize(); j++){cout << adjListij <<"";}cout << endl;}}};int main(){Graph g(5);gaddEdge(0, 1);gaddEdge(0, 2);gaddEdge(1, 2);gaddEdge(2, 3);gaddEdge(3, 4);gprintGraph();return 0;}```(三)深度优先遍历的实现```cppinclude <iostream>include <vector>using namespace std;const int MAX_VERTEX_NUM = 100;class Graph {private:int vertexNum;vector<int> adjListMAX_VERTEX_NUM;bool visitedMAX_VERTEX_NUM;public:Graph(int vNum) {vertexNum = vNum;for (int i = 0; i < vertexNum; i++){visitedi = false;}}void addEdge(int i, int j) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjListipush_back(j);adjListjpush_back(i);}}void DFS(int v) {visitedv = true;cout << v <<"";for (int i = 0; i < adjListvsize(); i++){int u = adjListvi;if (!visitedu) {DFS(u);}}}void DFSTraversal(){for (int v = 0; v < vertexNum; v++){if (!visitedv) {DFS(v);}}}};int main(){Graph g(5);gaddEdge(0, 1);gaddEdge(0, 2);gaddEdge(1, 2);gaddEdge(2, 3);gaddEdge(3, 4);gDFSTraversal();return 0;}```(四)广度优先遍历的实现```cppinclude <iostream>include <queue>include <vector>using namespace std;const int MAX_VERTEX_NUM = 100; class Graph {private:int vertexNum;vector<int> adjListMAX_VERTEX_NUM; bool visitedMAX_VERTEX_NUM; public:Graph(int vNum) {vertexNum = vNum;for (int i = 0; i < vertexNum; i++){visitedi = false;}}void addEdge(int i, int j) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjListipush_back(j);adjListjpush_back(i);}}void BFS(int v) {queue<int> q;visitedv = true;qpush(v);while (!qempty()){int u = qfront();qpop();cout << u <<"";for (int i = 0; i < adjListusize(); i++){int w = adjListui;if (!visitedw) {visitedw = true;qpush(w);}}}}void BFSTraversal(){for (int v = 0; v < vertexNum; v++){if (!visitedv) {BFS(v);}}}};int main(){Graph g(5);gaddEdge(0, 1);gaddEdge(0, 2);gaddEdge(1, 2);gaddEdge(2, 3);gaddEdge(3, 4);gBFSTraversal();return 0;}```(五)迪杰斯特拉算法的实现```cppinclude <iostream>include <climits>include <vector>using namespace std;const int MAX_VERTEX_NUM = 100; const int INFINITY = INT_MAX; class Graph {private:int vertexNum;int adjMatrixMAX_VERTEX_NUMMAX_VERTEX_NUM;int distanceMAX_VERTEX_NUM;bool visitedMAX_VERTEX_NUM;public:Graph(int vNum) {vertexNum = vNum;for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){adjMatrixij = INFINITY;}distancei = INFINITY;visitedi = false;}}void addEdge(int i, int j, int weight) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjMatrixij = weight;adjMatrixji = weight;}}int minDistance(){int min = INFINITY;int minIndex =-1;for (int v = 0; v < vertexNum; v++){if (!visitedv && distancev <= min) {min = distancev;minIndex = v;}}return minIndex;}void dijkstra(int src) {distancesrc = 0;for (int count = 0; count < vertexNum 1; count++){int u = minDistance();visitedu = true;for (int v = 0; v < vertexNum; v++){if (!visitedv && adjMatrixuv!= INFINITY && distanceu!=INFINITY && distanceu + adjMatrixuv < distancev) {distancev = distanceu + adjMatrixuv;}}}for (int i = 0; i < vertexNum; i++){cout <<"源点"<< src <<"到顶点"<< i <<"的最短距离为: "<< distancei << endl;}}};int main(){Graph g(5);gaddEdge(0, 1, 2);gaddEdge(0, 2, 4);gaddEdge(1, 2, 1);gaddEdge(1, 3, 7);gaddEdge(2, 3, 3);gaddEdge(3, 4, 5);gdijkstra(0);return 0;}```(六)弗洛伊德算法的实现```cppinclude <iostream>include <climits>using namespace std;const int MAX_VERTEX_NUM = 100; const int INFINITY = INT_MAX; class Graph {private:int vertexNum;int adjMatrixMAX_VERTEX_NUMMAX_VERTEX_NUM;int distanceMAX_VERTEX_NUMMAX_VERTEX_NUM;public:Graph(int vNum) {vertexNum = vNum;for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){adjMatrixij = INFINITY;}}}void addEdge(int i, int j, int weight) {if (i >= 0 && i < vertexNum && j >= 0 && j < vertexNum) {adjMatrixij = weight;}}void floyd(){for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){distanceij = adjMatrixij;}}for (int k = 0; k < vertexNum; k++){for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){if (distanceik!= INFINITY && distancekj!= INFINITY &&distanceik + distancekj < distanceij) {distanceij = distanceik + distancekj;}}}}for (int i = 0; i < vertexNum; i++){for (int j = 0; j < vertexNum; j++){if (distanceij == INFINITY) {cout <<"顶点"<< i <<"到顶点"<< j <<"的距离为: 无穷大" << endl;} else {cout <<"顶点"<< i <<"到顶点"<< j <<"的距离为: "<< distanceij << endl;}}}}};int main(){Graph g(4);gaddEdge(0, 1, 5);gaddEdge(0, 3, 10);gaddEdge(1, 2, 3);gaddEdge(2, 3, 1);gfloyd();return 0;}```五、实验结果分析(一)邻接矩阵和邻接表的比较邻接矩阵的优点是可以快速判断两个顶点之间是否有边相连,时间复杂度为O(1)。
数据结构图实验报告
数据结构图实验报告一、实验目的本次实验的主要目的是深入理解和掌握数据结构图的基本概念、原理和操作方法,通过实际编程和操作,提高对数据结构的应用能力和解决问题的能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
三、实验内容(一)线性表1、顺序表实现顺序表的创建、插入、删除、查找等基本操作。
分析顺序表在不同操作下的时间复杂度。
2、链表实现单链表、双向链表的创建、插入、删除、查找等基本操作。
比较单链表和双向链表在操作上的优缺点。
(二)栈和队列1、栈实现顺序栈和链式栈。
用栈解决表达式求值问题。
2、队列实现顺序队列和链式队列。
用队列模拟银行排队问题。
(三)树1、二叉树实现二叉树的创建、遍历(前序、中序、后序)。
计算二叉树的深度和节点数。
2、二叉搜索树实现二叉搜索树的插入、删除、查找操作。
分析二叉搜索树的性能。
(四)图1、图的存储实现邻接矩阵和邻接表两种图的存储方式。
比较两种存储方式的优缺点。
2、图的遍历实现深度优先遍历和广度优先遍历算法。
用图的遍历解决最短路径问题。
四、实验步骤(一)线性表1、顺序表定义一个数组来存储顺序表的元素,并使用一个变量记录当前表的长度。
插入操作时,需要判断插入位置是否合法,如果合法则将插入位置后的元素依次向后移动一位,然后将新元素插入指定位置。
删除操作时,先判断删除位置是否合法,合法则将删除位置后的元素依次向前移动一位,并更新表的长度。
查找操作通过遍历数组来实现。
分析不同操作的时间复杂度,插入和删除操作在最坏情况下为O(n),查找操作在平均情况下为 O(n/2)。
2、链表对于单链表,定义一个节点结构体,包含数据域和指向下一个节点的指针域。
通过操作指针来实现插入、删除和查找操作。
双向链表则在节点结构体中增加指向前一个节点的指针,使得操作更加灵活,但也增加了空间复杂度。
比较单链表和双向链表在插入、删除操作中指针的调整过程,得出双向链表在某些情况下更方便,但空间开销较大的结论。
数据结构实验报告(图)
1.实验题目编制一个程序,用来演示图的建立、存储与遍历。
2.需求分析本演示程序在C-free5环境下编写调试,完成图的邻接表建立、存储和实现图的深度优先遍历。
(1)输入的形式和输入值的范围:建立邻接表时需要输入图的顶点数和边数并且输入每条边的关联顶点编号;执行深度优先遍历时需要输入出发点v1。
(2)输出的形式:邻接表建立后要输出邻接表;深度优先遍历结束后输出深度优先遍历结果。
(3)程序所达到的功能:完成邻接表的建立、输出、深度优先遍历。
(4)测试数据①建立邻接表时依次输入图的顶点数和边数4,4。
②输入每条边的关联顶点编号时输入1,3 1,2 1,4 2,4。
③执行深度优先遍历时输入3。
3.概要设计(1).为了实现上述功能,需要定义链表的数据结构。
头结点和表结点的组成形式如下所示。
表头结点表结点(2).本程序包含8个函数①主函数main( )。
②创建图的邻接表的函数creat L( )。
③邻接表的输出函数output_L()。
④图的深度优先遍历函数dfsL( )。
⑤队列初始化函数initqueue( )。
⑥判断队列是否为空的函数quempty( )。
⑦入队操作函数enqueue( )。
⑧出队操作函数dequeue( )。
各函数间的关系如下图所示。
maincreat L( ) output_LdfsL( ) initqueue( ) quempty( ) enqueue( )dequeue( )4.详细设计重要代码段建立无向图的邻接表void creat_L(Lgraph G){Vnode *p,*q;int i,j,k;printf("\n请输入图的顶点数和边数:");scanf("%d,%d",&n,&e);for(i=1;i<=n;i++){G[i].data=i;G[i].next=NULL;}for(k=1;k<=e;k++){printf("请输入每条边的关联顶点编号:");scanf("%d,%d",&i,&j);p=(Vnode *)malloc(sizeof(Vnode));p->data=i;p->next=G[j].next;G[j].next=p;q=(Vnode *)malloc(sizeof(Vnode));q->data=j;q->next=G[i].next;G[i].next=q;}}深度优先遍历void dfsL(Lgraph G,int v){Vnode *p;printf("%d->",G[v].data);visited[v]=1;p=G[v].next;while(p){v=p->data;if(visited[v]==0)dfsL(G,v);p=p->next;}}5.调试分析①写程序时代码会有输入错误。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图的实验报告班级:电子091 学号:0908140620 姓名:何洁编号:19(一)实验要求创建一个图。
能够实现图的输入,插入顶点和边,利用队列进行深度和广度遍历。
(二)需求分析功能:1,输入图的信息;2,插入一个顶点;3插入一个边;4,删除一个顶点;5,删除一个边;6,深度优先遍历;7,广度优先遍历;8退出。
(三)概要设计本程序采用的是模板类,抽象数据类型有:T,E。
类:template <class T,class E>class Graphmtx {friend istream & operator>>(istream& in,Graphmtx<T, E>& G);friend ostream & operator<<(ostream& out, Graphmtx<T, E>& G);//输出public:Graphmtx(int sz=30, E max=0); //构造函数~Graphmtx () //析构函数{ delete []VerticesList; delete []Edge; }T getValue (int i) {//取顶点i 的值, i 不合理返回0return i >= 0 && i <= numVertices ?V erticesList[i] : NULL;}E getWeight (int v1, int v2) { //取边(v1,v2)上权值return v1 != -1 && v2 != -1 ? Edge[v1][v2] : 0;}int NumberOfEdges(){return numEdges;} //返回当前边数int NumberOfVertices(){return numVertices;} //返回当前顶点int getFirstNeighbor (int v);//取顶点v 的第一个邻接顶点int getNextNeighbor (int v, int w);//取v 的邻接顶点w 的下一邻接顶点bool insertVertex (const T& vertex);//插入顶点vertexbool insertEdge (int v1, int v2, E cost);//插入边(v1, v2),权值为costbool removeVertex (int v);//删去顶点v 和所有与它相关联的边bool removeEdge (int v1, int v2);//在图中删去边(v1,v2)int getVertexPos (T vertex) {//给出顶点vertex在图中的位置for (int i = 0; i < numVertices; i++)if (VerticesList[i] == vertex) return i;return -1;}//int numVertexPos(T vertex);private:int maxVertices;int numEdges;int numVertices;T *VerticesList; //顶点表E **Edge; //邻接矩阵const E maxWeight;};(四)详细设计函数通过调用图类中的函数实现一些功能。
头文件:#include<iostream.h>#include<assert.h>const int maxSize=50;const int DefaultVertices=30; //最大顶点数(=n) const int maxWeight=50;其中顺序队列的实现:template<class T>class SeqQueue{//循环队列的类的定义public:SeqQueue(int sz=10); //构造函数~SeqQueue(){delete[] elements;} //析构函数bool EnQueue(const T& x);//若队列不满,则将X进队,否则队溢出处理bool DeQueue(T& x);//若队列不为空,则函数返回TRUE及对头元素的值,否则返回FALSEvoid makeEmpty(){front=rear=0;}//置空操作:对头指针和队尾指针置0bool IsEmpty()const{return(front==rear)?true:false;}//判队列空否,若队列空,则函数返回TRUE,否则返回FALSEbool IsFull()const{return((rear+1)%maxSize==front)?true:false;}//判队列满否,若队列满,则函数返回TRUE,否则返回FALSE protected:int rear,front; //对头和队尾指针T *elements; //存放队列元素的数组int maxSize; //队列最大可容纳元素个数};template<class T>SeqQueue<T>::SeqQueue(int sz):front(0),rear(0),maxSize(sz){//建立最大具有Maxsize个元素的空队列elements=new T[maxSize]; //创建队列空间assert(elements!=NULL); //断言:动态存储分配成功与否}template<class T>bool SeqQueue<T>::EnQueue(const T& x){//若队列不满,则将元素X插入到该队列的队尾,否则出错处理if(IsFull()==true)return false; //队列满则插入失败,返回elements[rear]=x; //按照队尾指针指示位置插入rear=(rear+1)%maxSize; //队尾指针加1return true; //插入成功}template<class T>bool SeqQueue<T>::DeQueue(T& x){//若队列不空则函数推掉一个对头元素并返回TRUE,否则函数返回FALSE if(IsEmpty()==true)return false; //若队列空则删除失败,返回x=elements[front];front=(front+1)%maxSize; //对头指针加1return true; //删除成功}类的实现:template <class T, class E>Graphmtx<T, E>::Graphmtx(int sz, E max):maxWeight(max){ //构造函数maxVertices=sz;numVertices=0;numEdges=0;int i, j;VerticesList = new T[maxVertices]; //创建顶点表Edge = (int **) new int *[maxVertices];for (i = 0; i < maxVertices; i++)Edge[i] = new int[maxVertices]; //邻接矩阵for (i = 0; i < maxVertices; i++) //矩阵初始化for (j = 0; j < maxVertices; j++)Edge[i][j]=(i==j)?0:maxWeight;}template <class T, class E>int Graphmtx<T, E>::getFirstNeighbor (int v) {//给出顶点位置为v的第一个邻接顶点的位置,//如果找不到, 则函数返回-1if (v != -1) {for (int col = 0; col < numVertices; col++)if (Edge[v][col] && Edge[v][col] < maxWeight)return col;}return -1;}template <class T, class E>int Graphmtx<T, E>::getNextNeighbor (int v, int w) {//给出顶点v 的某邻接顶点w 的下一个邻接顶点if (v != -1 && w != -1) {for (int col = w+1; col < numVertices; col++)if (Edge[v][col] && Edge[v][col] < maxWeight)return col;}return -1;}界面:cout<<" =================================="<<endl;cout<<" |1、输入一个图2、插入一个顶点| "<<endl;cout<<" |3、插入一个边4、删除一个顶点|"<<endl;cout<<" |5、删除一个边6、深度优先遍历|"<<endl;cout<<" |7、广度优先遍历8、退出|"<<endl;cout<<" =================================="<<endl;然后进入循环进行功能操作Case1中,输入一个图:其中有操作符的重载,使图的信息直接输入:template<class T,class E>istream& operator >> (istream& in,Graphmtx<T,E>& G){//通过从输入流in输入n个顶点信息和e条无向边的信息建立用邻接矩阵的图G。
//邻接矩阵初始化的工作已经在构造函数中完成、int i,j,k,n,m;T e1,e2;E weight;in>>n>>m;for(i=0;i<n;i++){in>>e1;G.insertVertex(e1);}i=0;while(i<m){in>>e1>>e2>>weight;j=G.getVertexPos(e1);k=G.getVertexPos(e2);if(j==-1||k==-1)cout<<"边两端信息有误,重新输入!"<<endl;else{G.insertEdge(j,k,weight);i++;}}return in;}cout<<"请输入图的信息:"<<endl;cin>>g1;cout<<endl;break;Case2中,是插入顶点,需要调用的函数有:template<class T,class E>bool Graphmtx<T,E>::insertVertex(const T& vertex){ //插入顶点vertexif(numVertices==maxVertices)return false; //顶点表满,不插入VerticesList[numVertices++]=vertex;return true;}case 2:cout<<"请输入要插入的顶点:";cin>>v1;g1.insertV ertex (v1);cout<<g1;cout<<"插入成功"<<endl;break;出现界面:Case3中,是实现插入边的操作,需要调用的函数有:template<class T,class E>bool Graphmtx<T,E>::insertEdge (int v1,int v2,E cost){//插入边(v1,v2),权值为costif(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices && Edge[v1][v2]==maxWeight){ Edge[v1][v2]=Edge[v2][v1]=cost;numEdges++;return true;}else return false;}然后执行调用:case 3:cout<<"请输入插入边的两个顶点的序号:";cin>>e1>>e2;cout<<endl;cout<<"请输入权值:";cin>>cost;g1.insertEdge (e1,e2,cost);cout<<g1;break;出现界面:Case 6是进行深度优先遍历:利用了队列,调用的函数有:template<class T, class E>void DFS(Graphmtx<T, E>& G, const T& v) {//从顶点v出发对图G进行深度优先遍历的主过程int i, loc,n;n=G.NumberOfVertices(); //顶点个数bool *visited=new bool[n]; //创建辅助数组for (i = 0; i < n; i++) visited [i] = false;//辅助数组visited初始化loc = G.getVertexPos(v);DFS (G, loc, visited); //从顶点0开始深度优先搜索delete [] visited; //释放visited}template<class T, class E>void DFS(Graphmtx<T, E>& G, int v, bool visited[]) {cout << G.getValue(v) << ' '; //访问顶点vvisited[v] = true; //作访问标记int w = G.getFirstNeighbor (v); //第一个邻接顶点while (w != -1) { //若邻接顶点w存在if ( !visited[w] ) DFS(G, w, visited);//若w未访问过, 递归访问顶点w w = G.getNextNeighbor (v, w); //下一个邻接顶点}}主函数中:case 6:cout<<"请输入一个顶点:";cin>>v1;cout<<"图的深度优先搜索为:"<<endl;DFS(g1,v1);cout<<endl;break;界面出现:Case7是现实广度优先遍历的操作,也需要利用到队列,其函数体为:template <class T, class E>void BFS(Graphmtx<T, E>& G, const T& v) {int i,w;int n = G.NumberOfVertices();//图中顶点个数bool *visited = new bool[n];for (i = 0; i < n; i++) visited[i] = false;int loc = G.getVertexPos (v); //取顶点号cout << G.getValue (loc) << ' '; //访问顶点vvisited[loc] = true; //做已访问标记SeqQueue<int> Q; Q.EnQueue (loc); //顶点进队列, 实现分层访问while (!Q.IsEmpty() ) { //循环, 访问所有结点Q.DeQueue (loc);w = G.getFirstNeighbor (loc); //第一个邻接顶点while (w != -1) { //若邻接顶点w存在if (!visited[w]) { //若未访问过cout << G.getValue (w) << ' '; //访问visited[w] = true;Q.EnQueue (w); //顶点w进队列}w = G.getNextNeighbor (loc, w); //找顶点loc的下一个邻接顶点}} //外层循环,判队列空否delete [] visited;}主函数中的调用:case 7:cout<<"请输入一个顶点:";cin>>v1;cout<<"图的广度优先搜索为:"<<endl;BFS(g1,v1);cout<<endl;break;界面显示:Case4中式删除顶点的操作;函数的实现:template<class T,class E>bool Graphmtx<T,E>::removeVertex (int v){//删去顶点v和所有与它相关的边if(v<0||v>=numVertices)return false;if(numVertices==1)return false;int i,j;VerticesList[v]=VerticesList[numVertices-1];for(i=0;i<numVertices;i++)if(Edge[i][v]<0&&Edge[i][v]<maxWeight)numEdges--;for(i=0;i<numVertices;i++)Edge[i][v]=Edge[i][numVertices-1];numVertices--;for(j=0;j<numVertices;j++)Edge[v][j]=Edge[numVertices][j];return true;}主函数中:case 4:cout<<"请输入要删除的顶点序号:";cin>>e1;g1.removeVertex(e1);cout<<g1;break;界面显示:Case5的操作是删除一条边:要调用的函数:template<class T,class E>bool Graphmtx<T,E>::removeEdge (int v1,int v2){//在图中删除边(v1,v2)if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]>0&&Edge[v1][ v2]<maxWeight){Edge[v1][v2]=Edge[v2][v1]=maxWeight;numEdges--;return true;}else return false;}在主函数中:case 5:cout<<"请输入要删除边的两个顶点序号:";cin>>e1>>e2;g1.removeEdge(e1,e2);cout<<g1;break;界面显示:Case8 的操作是退出case 8:return 0;break;界面显示:(五)调试与测试在调试过程中遇到很多问题,在定义变量的时候遇到一些问题,对于全局变量还是局部变量要区分一下。