数据结构实验—图的建立与遍历

合集下载

数据结构实验五---图的遍历及其应用实现

数据结构实验五---图的遍历及其应用实现

数据结构实验五---图的遍历及其应用实现实验五图的遍历及其应用实现一、实验目的1.熟悉图常用的存储结构。

2.掌握在图的邻接矩阵和邻接表两种结构上实现图的两种遍历方法实现。

3.会用图的遍历解决简单的实际问题。

二、实验内容[题目] :从键盘上输入图的顶点和边的信息,建立图的邻接表存储结构,然后以深度优先搜索和广度优先搜索遍历该图,并输出起对应的遍历序列. 试设计程序实现上述图的类型定义和基本操作,完成上述功能。

该程序包括图类型以及每一种操作的具体的函数定义和主函数。

三、实验步骤(一)、数据结构与核心算法的设计描述:本实验主要在于图的基本操作,关键是图的两种遍历,仔细分析图的遍历的特点,不难发现,其符合递归的特点,因此可以采用递归的方法遍历。

本实验图的存储结构主要采用邻接表,总共分为四个模块:图的创建、位置的查找、深度优先遍历、广度优先遍历。

以下是头文件中数据结构的设计和相关函数的声明:#include#include#include#nclude#define OVERFLOW -2#define MAX_VERTEX_NUM 50 //最大顶点数#define MAXQSIZE 100# define OK 1typedef int VRType;typedef int InfoType;typedef int QElemType;typedef enum{DG,DN,UDG,UDN}GraphKind;typedef struct ArcNode // 弧结点{int adjvex; //邻接点域,存放与Vi邻接的点在表头数组中的位置struct ArcNode *nextarc; //链域指向vi的下一条边或弧的结点,InfoType *info; //定义与弧相关的权值,无权则为0 }ArcNode;typedef struct VNode //表头结点{char vexdata; //存放顶点信息struct ArcNode *firstarc; //指示第一个邻接点}VNode,AdjList[MAX_VERTEX_NUM];typedef struct{ //图的结构定义AdjList vertices; //顶点向量int vexnum, arcnum; //vexnum为顶点数arcnum为弧或边的个数GraphKind kind; // 图的种类标志}MGraph;typedef struct Queue //构建循环队列{QElemType *base;int front;int rear;}Queue;void CreateGraph(MGraph &G); //图的创建void DFSTraverse(MGraph &G) ; //深度优先遍历void BFSTraverse(MGraph &G); //广度优先遍历int LocateVex(MGraph &G, char &v);//查找顶点v的位置(二)、函数调用及主函数设计void main(){int x;MGraph G;CreateGraph(G);cout<<"创建图成功!"<<endl;< p="">cout<<"1 深度优先搜索"<<endl<<"2 p="" 广度优先搜索"<<endl;<="">cin>>x;if(x==1){DFSTraverse(G);cout<<"深度优先搜索结束!"<<endl;< p="">}else if(x==2){BFSTraverse(G);cout<<"广度优先搜索结束!"<<endl;< p="">}elsecout<<"输入有误!"<<endl<<"再见!"<<endl;< p="">}(三)、实验总结由于图的基本操作在图这一章节中起着很主要的作用,所以在实验前就对实验做了充分的准备,实验的成功核心在于两种遍历的实现,因此只有充分理解遍历算法的精髓,才能更好的做好实验。

数据结构中图的建立与深度优先、广度优先遍历

数据结构中图的建立与深度优先、广度优先遍历

数据结构中图的建立与深度优先、广度优先遍历《数据结构》实验报告实验内容:图的建立(邻接矩阵)及其深度优先、广度优先遍历学号:姓名:一、上机实验的问题和要求(需求分析):[ 题目]二、程序设计的基本思想,原理和算法描述:设计一个程序,建立图的邻接矩阵,并且进行图的广度优先遍历。

三、调试和运行程序过程中产生的问题及采取的措施:(略)四、源程序及注释[ 源程序] 程序名:9.cpp#include"stdio.h"#include"stdlib.h"#define INFINITY 100#define MAX_VERTEX_NUM 20#define MAX 100#define OK 1#define ERROR 0#define NULL 0typedef int VRType;typedef int VertextType;typedef int Status;typedef enum {DG,DN,UDG,UDN}GraphKind;typedef struct ArcCell{VRType adj;}ArcCell,AdjMatrix[MAX_VERTEX_NUM ][MAX_VERTEX_NUM ]; typedef struct{int vexs[MAX_VERTEX_NUM ];int arcs[4][4] ;int vexnum,arcnum;GraphKind Kind;}MGraph;int LocateVex(MGraph G,int v1){ int i;for(i=0;i<g.vexnum;i++)< p="">if(G.vexs[i]==v1)printf("%d\n",i);return i;}Status CreateUDN(MGraph &G){ int v1,v2;int i,j,k,w;printf("输入图的顶点数和弧数:");scanf("%d,%d",&G.vexnum,&G.arcnum); printf("输入顶点:");for(i=0;i<g.vexnum;i++)< p="">scanf("%d",&G.vexs[i]);for(i=0;i<g.vexnum;i++)< p="">for(j=0;j<g.vexnum;j++)< p="">G.arcs[i][j]=INFINITY ;printf("输入顶点关系:");for(k=0;k<g.arcnum;k++)< p="">{scanf("%d%d%d",&v1,&v2,&w);i=LocateVex(G,v1);j=LocateVex(G,v2);G.arcs[i][j]=w;G.arcs[j][i]=G.arcs[i][j];printf("%d\n%d\n",G.arcs[i][j],G.arcs[j][i]);}printf("图的邻接矩阵图是:\n");for(i=0;i<g.vexnum;i++)< p="">{for(j=0;j<g.vexnum;j++)< p="">printf("%d",G.arcs[i][j]);printf("\n");}return OK;}Status Visit(int e){//输出函数printf("%d\n",e);return OK;}//PrintElement//Status(*VisitFunc)(char v);int visited[MAX];void DFS(MGraph G,int v){ int j;Visit (v);visited[v]=1;for(j=1;j<g.vexnum;j++)< p="">if(!visited[j]&&G.arcs[v][j]!=INFINITY)DFS(G,j); } void DFSTraverse(MGraph G){ int v;for(v=0;v<g.vexnum;++v)< p="">visited[v]=0;for(v=0;v<g.vexnum;++v)< p="">if(!visited[v])DFS(G,v);/* 有关队列的操作*/#define MAX SIZE 100#define QElemType int#define OVERFLOW 0typedef struct{QElemType *base;int front;int rear;}SqQueue;Status InitQueue(SqQueue &Q){ Q.base=(QElemType*)malloc(MAXSIZE* sizeof(QElemType)); if(!Q.base)exit(OVERFLOW);Q.front=Q.rear=0;return 0;}Status EnQueue(SqQueue &Q,QElemType e){if(Q.rear+1==Q.front)return ERROR;Q.base[Q.rear]=e;Q.rear=Q.rear+1;return OK;}Status DeQueue(SqQueue &Q,QElemType &e){if(Q.front==Q.rear)return ERROR;e=Q.base[Q.front];Q.front=Q.front+1;return OK;}Status QueueEmpty(SqQueue Q){if(Q.front==Q.rear)return OK;else return ERROR;void BFSTraverse(MGraph &G){ int v,u,j;SqQueue Q;for(v=0;v<g.vexnum;v++)< p=""> visited[v]=0;InitQueue(Q);for(v=0;v<g.vexnum;++v)< p="">if(!visited[v]){visited[v]=1;Visit(v);EnQueue(Q,v);while(!QueueEmpty(Q)){ DeQueue(Q,u);for(j=1;j<g.vexnum;j++)< p="">if(!visited[j]&&G.arcs[v][j]!=INFINITY) { visited[j]=1;Visit(j);EnQueue(Q,j);}} }}void main(){ MGraph G;CreateUDN(G);printf("建图成功!");printf("深度优先遍历的结果:\n"); DFSTraverse(G);printf("广度优先遍历的结果:\n"); BFSTraverse(G);}五、运行结果运行结果:上一页下一页</g.vexnum;j++)<></g.vexnum;++v)<></g.vexnum;v++)<></g.vexnum;++v)<> </g.vexnum;++v)<> </g.vexnum;j++)<> </g.vexnum;j++)<> </g.vexnum;i++)<> </g.arcnum;k++)<> </g.vexnum;j++)<> </g.vexnum;i++)<> </g.vexnum;i++)<> </g.vexnum;i++)<>。

数据结构C语言版——图的建立与遍历

数据结构C语言版——图的建立与遍历
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertices;
int vexnum,arcnum;
int kind;
typedef int Status;
//图的邻接矩阵——数组存储表示-------------------------
#define INF0
typedef int VRType;
typedef char VertexType[20];
{
scanf("%s%s",v1,v2);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G->arcs[i][j].adj=1;
G->arcs[j][i]=G->arcs[i][j];
}
return(1);
}
int LocateVex(MGraph *G,VertexType v){
Boolean visited[MAX_VERTEX_NUM];
void Dfs(MGraph *G,int v)
{
int w;
visited[v]=TRUE;
printf("%s",G->vexs[v]);
for(w=FirstAdjVex(G,v); w>=0;w=NextAdjVex(G,v,w))
AdjMatrix arcs;
int vexnum,arcnum;
}MGraph;

数据结构实验报告-图的遍历

数据结构实验报告-图的遍历

数据结构实验报告实验:图的遍历一、实验目的: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.首先输入顶点的数量,然后是各顶点对应的字母,再输入各条弧(权值都置为1)。

3.在Dos界面输出从首个顶点开始的广度优先遍历序列。

4.测试数据输入输入顶点数和弧数:8 9输入8个顶点.输入顶点0:a输入顶点1:b输入顶点2:c输入顶点3:d输入顶点4:e输入顶点5:f输入顶点6:g输入顶点7:h输入9条弧.输入弧0:a b 1输入弧1:b d 1输入弧2:b e 1输入弧3:d h 1输入弧4:e h 1输入弧5:a c 1输入弧6:c f 1输入弧7:c g 1输入弧8:f g 1输出广度优先遍历: a b d h e c f g深度优先遍历: a b c d e f g h二、概要设计:抽象数据类型:图的定义:ADT Graph {数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。

数据关系R:R={VR}VR={<v,w>|v,w∈v且P(v,w),<v,w>表示从v到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}基本操作P:CreateGraph(&G,V,VR)初始条件:V是图的顶点集,VR是图中弧的集合操作结果:按V和VR的定义构造图GFirstAdjV ex(G,v)初始条件:图G存在,v是G中某个顶点操作结果:返回v的第一个邻接顶点,若顶点在G中没有邻接顶点,则返回“空”Next AdjV ex(G,v,w)初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点操作结果:返回v的(相对于w的)下一个邻接顶点,若w是v的最后一个邻接点,则返回“空”visit(G, k)初始条件:图G存在操作结果:访问图G中的第K个节点Locate(G, c)初始条件:图G存在操作结果:访问图G中的c顶点DFS(G, v)初始条件:图G存在操作结果:以图G中的第v个节点为起点深度优先访问图GBFS(G)初始条件:图G存在操作结果:广度优先访问图G} ADT Graph算法的基本思想:(1)图的特点是没有首尾之分,所以算法的参数要指定访问的第一个顶点。

数据结构图的遍历实验报告

数据结构图的遍历实验报告

实验项目名称:图的遍历一、实验目的应用所学的知识分析问题、解决问题,学会用建立图并对其进行遍历,提高实际编程能力及程序调试能力。

二、实验内容问题描述:建立有向图,并用深度优先搜索和广度优先搜素。

输入图中节点的个数和边的个数,能够打印出用邻接表或邻接矩阵表示的图的储存结构。

三、实验仪器与设备计算机,Code::Blocks。

四、实验原理用邻接表存储一个图,递归方法深度搜索和用队列进行广度搜索,并输出遍历的结果。

五、实验程序及结果#define INFINITY 10000 /*无穷大*/#define MAX_VERTEX_NUM 40#define MAX 40#include<>#include<>#include<>#include<>typedef struct ArCell{int adj;}ArCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{ char name[20];}infotype;{ infotype vexs[MAX_VERTEX_NUM];AdjMatrix arcs;int vexnum,arcnum;}MGraph;int LocateVex(MGraph *G,char* v){ int c = -1,i;for(i=0;i<G->vexnum;i++)if(strcmp(v,G->vexs[i].name)==0){ c=i; break;}return c;}MGraph * CreatUDN(MGraph *G)d:",i+1);scanf("%s",G->vexs[i].name);}for(i=0;i<G->vexnum;i++)for(j=0;j<G->vexnum;j++)G->arcs[i][j].adj=INFINITY;printf("请输入一条边依附的两个顶点和权值:\n");for(k=0;k<G->arcnum;k++){printf("第%d条边:\n",k+1);printf("起始结点:");scanf("%s",v1);printf("结束结点:");scanf("%s",v2);dj=w;G->arcs[j][i]=G->arcs[i][j];}}return G;}int FirstAdjVex(MGraph *G,int v){int i;if(v<=0 && v<G->vexnum){ dj!=INFINITY)return i;}return -1;}void VisitFunc(MGraph *G,int v){printf("%s ",G->vexs[v].name);}int NextAdjVex(MGraph *G,int v,int w){int k;if(v>=0 && v<G->vexnum && w>=0 && w<G->vexnum)dj!=INFINITY) return k;return -1;}int visited[MAX];void DFS(MGraph *G,int v)//从第v个顶点出发递归地深度优先遍历图G {int w;visited[v]=1;VisitFunc(G,v);//访问第v个结点for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))if(!visited[w]){DFS(G,w);printf("%d ",G->arcs[v][w]);}}void DFSTraverse(MGraph *G,char *s)//深度优先遍历{int v,k;for(v=0;v<G->vexnum;v++)visited[v]=0;k=LocateVex(G,s);if(k>=0&&k<G->vexnum){for(v=k;v>=0;v--){if(!visited[v])DFS(G,v);}for(v=k+1;v<G->vexnum;v++)if(!visited[v])DFS(G,v);}}typedef struct Qnode{int vexnum;struct Qnode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;int InitQueue(LinkQueue *Q){Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));if(!Q->front)exit(0);Q->front->next=NULL;return 1;}void EnQueue(LinkQueue *Q,int a )QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(0);p->vexnum=a;p->next=NULL;Q->rear->next=p;Q->rear=p;}int DeQueue(LinkQueue *Q,int *v){ QueuePtr p;if(Q->front==Q->rear){printf("结点不存在!\n");exit(0);}p=Q->front->next;*v=p->vexnum;Q->front->next=p->next;if(Q->rear==p)Q->front=Q->rear;return *v;}int QueueEmpty(LinkQueue *Q){if(Q->rear==Q->front)return 0;return 1;}int Visited[MAX];void BFSTraverse(MGraph *G,char *str)//广度优先遍历{int w,u,v,k;LinkQueue Q,q;for(v=0;v<G->vexnum;v++) Visited[v]=0;InitQueue(&Q);InitQueue(&q);k=LocateVex(G,str);for(v=k;v>=0;v--)if(!Visited[v]){Visited[v]=1;VisitFunc(G,v);EnQueue(&Q,v);//v入队while(!QueueEmpty(&Q)){DeQueue(&Q,&u);//出队for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))if(!Visited[w]){VisitFunc(G,v);EnQueue(&Q,w);}}}for(v=k+1;v<G->vexnum;v++)if(!Visited[v]){Visited[v]=1;VisitFunc(G,v);EnQueue(&Q,v);//v入队while(!QueueEmpty(&Q)){DeQueue(&Q,&u);//出队for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(!Visited[w]){Visited[w]=1;VisitFunc(G,v);EnQueue(&Q,w);}}}}void main(){MGraph *G,b;char v[10];G=CreatUDN(&b);printf("请输入起始结点名称:");scanf("%s",v);printf("\n深度优先遍历:\n");DFSTraverse(G,v);printf("\n广度优先遍历:\n");BFSTraverse(G,v);getch();}六、实验总结实验要求输入图中节点的个数和边的个数,能够打印出用邻接表或邻接矩阵表示的图的储存结构。

数据结构课程实验(图的存储与遍历)

数据结构课程实验(图的存储与遍历)

实验五图的存储与遍历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算法的实现思想与以邻接矩阵为存储结构的实现是一样的。

C语言_数据结构_实验7_图的创建与遍历 2

C语言_数据结构_实验7_图的创建与遍历 2

实验五(1):图的创建与遍历
1.实验目的:
1.掌握图的含义;
2.掌握用邻接矩阵和邻接表的方法描述图的存储结构;
3.理解并掌握深度优先遍历和广度优先遍历的存储结构。

2.实验内容:
(1)以邻接矩阵为存储结构,实现连通有向图(下图)的所有顶点出度与入度的计算。

(2)设计两个算法分别实现深度优先遍历和广度优先遍历。

1 调试程序。

设计一个有向图和一个无向图,任选一种存储结构,完成有向
图和无向图的DFS(深度优先遍历)和BFS(广度优先遍历)的操作。

邻接矩阵作为存储结构的运行结果:
邻接链表作为存储结构的运行结果:
实验报告要求
画出你所设计的图,写出两种方法的遍历序列。

邻接矩阵:
V0 V1 V2 V3 V4 V5 V6 V7
V0 0 1 1 0 0 0 0 0 V1 1 0 0 1 1 0 0 0 V2 1 0 0 0 0 1 1 0 V3 0 1 0 0 0 0 0 1 V4 1 0 0 0 0 0 0 1 V5 0 1 0 0 0 0 1 0 V6 0 1 0 0 0 1 0 0 V7 0
1
1
V6 V4 V5 V7 V2 V3 V1 V0 图G 的示例
V0 0 2 1 ^
V1 1 4 3 ^ 0 ^ V2 2 6 5 0 ^ V3 3 4 1 ^
V4 4 7 1 ^
V5 5 6 2 ^
V6 6 5 2 ^
V7 7 4 3 ^
深度遍历为:0→2→6→5→1→4→7→3
广度遍历为:3→7→1→4→0→2→6→5。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验十图的建立与遍历1.实验目的(1)掌握图的含义。

(2)掌握用邻接矩阵和邻接链表的方法描述图的存储结构。

(3)理解并掌握深度优先遍历方法和广度优先遍历方法的存储结构。

2.实验内容(1)建立无向图的邻接矩阵,并实现插入、删除边的功能。

(2)建立有向图的邻接表,并实现插入、删除边的功能。

(3)实现该图的深度优先遍历与广度优先遍历。

3.实验要求(1)根据实验内容编写程序,上机调试并获得运行结果(2)撰写实验报告4.准备工作本次实验将建立如图所示有向图和无向图,并会根据此进行插入,删除,遍历操作5.关键操作与算法(1)建立邻接矩阵算法思想;建立邻接矩阵即用一维数存储图中的顶点信息,用二维数组(矩阵)存储图中各顶点之间的邻接关系。

假设图G(V,E)有n个确定的顶点,即V={V,V,…,Vn-1},则表示G 中各顶点相邻关系的是一个n*n的矩阵,矩阵的元素值为若G是带权图(网),则邻接矩阵可定义为其中,w表示边(v,v)或<v,V>上的权值;∞表示一个计算机允许的、大于所有边上权值的数,代表此路不通;若v1=v1,则A[i][j]的值取0。

算法如下;1.void CreateMGragh(GraphMatrix *g)2.{3.int i, j, k, t;4.float w;//权值5. printf("请输入无向网的顶点个数(不超过%d个): ",MAXVEX);6. scanf("%d",&g->vexNum);7. printf("\n请输入各顶点信息: \n");8. getchar();//吞掉上一步的回车9.for(i = 0; i < g->vexNum; i++)10. gets(g->vexs[i]);//输入各个顶点信息11.for (i = 0; i < g->vexNum; i++)12.for (j = 0; j < g->vexNum; j++)13. {14. g->arcs[i][j] = 0;//初始化邻接矩阵15. }16. printf("\n");17. printf("请输入图的边数(不超过%d个): ",(g->vexNum * (g->vexNum - 1))/2);18. scanf("%d",&k); //边的数目,这里的后面不用加getchar(),因为后面的一个输入的是一个整型类型19.for(t = 0; t < k; t++)20. {21. printf("\n请输入第%d条边的相关信息(起始顶点(序号从0开始) 终止顶点权值,如0 3 10.3)\n",t + 1);22. scanf("%d%d%f",&i,&j,&w);23. g->arcs[i][j] = w; //无向网的权是对称的24. g->arcs[j][i] = w;25. }26.}(2)创建邻接表算法步骤;邻接表(Adjacency List)是图的另一种存储方式,它是一种将顺序存储与链式存储相合的存储方法。

该方法是为图中每个顶点都建立一个单链表,即对于图G中的每个顶点v,将v1的所有邻接点v都链在一个单链表里,该单链表称为顶点v1的邻接表(链式存储构),再将所有顶点的邻接表表头集中放到一个一维数组(顺序存储结构)中,两者一起就成了图的邻接表结构。

算法如下;1.void CreateALGragh(GraphList *g)2.{3.int i,j,k;4. EdgeNode *s;5.float w;6. printf("请输入有向网的顶点个数,(不超过%d个): ",MAXVEX);7. scanf("%d",&g->VexNum);8. printf("请输入各个顶点的信息:\n");9. getchar();10.for(i = 0; i <g->VexNum; i++)11. {12. gets(g->vexs[i].vertex);13. g->vexs[i].firstarc = NULL;//这里vex[i].firstarc的点是因为vex[i]为结构体,所以引用它其中的内容使需要用"."运算符14. }15. printf("\n");16. printf("请输入图的边数(不超过%d个): ",g->VexNum * (g->VexNum - 1));17. scanf("%d",&g->EdgeNum);18.for(k = 0;k < g->EdgeNum; k++)19. {20. printf("\n请输入第%d条边的相关信息(起始顶点(序号从0开始) 终止顶点权值,如0 3 10.3)\n",k + 1);21. scanf("%d%d%f",&i,&j,&w);22. s = (EdgeNode*)(malloc(sizeof(EdgeNode)));23. s->endvex = j;24. s->next = g->vexs[i].firstarc;25. s->weight = w;26. g->vexs[i].firstarc = s;27. }28.}(3)无向网深度优先遍历算法过程;假设初始状态是未被访问过的图中所有顶点,则深度优先搜索可从图中某个顶点v出发,首先访问该顶点,然后从v的所有未被访问的邻接点中选择某一个邻接点w访问,然后再从w的所有未被访问的邻接点中选择某一个邻接点x访问,依此类推,直至图中所有和有路径相通的顶点都被访问过为止;若此时图中仍有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问过为止。

算法如下;1.void MUDGDFS(GraphMatrix *g, int v,int visited[])//visited数组是用来判断某节点是否被访问过的判断基准2.{3. DataType w;4. visited[v] = TRUE;5. printf("%d\t", v);6.for(w = MUDGFirstAdjacent(g, v); w != ERROR; w = MUDGNextAdjacent(g, v,w))7. {8.if(visited[w] != TRUE) //该顶点没有被访问过9. MUDGDFS(g,w,visited);10. }11.}(4)有向网广度优先算法步骤;搜索过程为从图中某顶点v出发,访问了顶点v后,再依次访问v的所有未曾访问过的邻接点,然后再分别从这些邻接点出发依次访问它们的所有未曾访问过的邻接点,遵循“先被访问的顶点的邻接点先于后被访问的顶点的邻接点”的访问原则,直至图中所有已被访问的顶点的邻接点都被访问到。

此时图中若还有顶点未被访问,则另选图中一个未曾被访问的顶点作为新的出发点,重复上述过程,直至图中所有顶点都被访问到为止。

广度优先搜索遍历图的过程类似于树的按层次遍历的过程。

算法如下;1.void LUDGBFS(GraphList *g, int v, int visited[])2.{3. DataType v1, v2;4. SeqQueue *q = SetSeqQueue(); //队列元素的类型为DataType(int)类型5. SeqQueueINQueue(q, v); //初始顶点入队6. printf("%d\t", v);7. visited[v] = TRUE; //初始顶点被访问8.while(!SeqQueueISEmpty(q))9. {10. SeqQueueOUTQueue(q, &v1); //对头元素出队,并将对头元素保存到v1中11. v2 = LUDGFirstAdjacent(g, v1);12.while (v2 != ERROR) //邻接顶点存在时进行循环13. {14.if (visited[v2] != TRUE) //如果邻接顶点未被访问则入队,访问,再改变visited标志15. {16. SeqQueueINQueue(q, v2);17. printf("%d\t", v2);18. visited[v2] = TRUE;19. }20. v2 = LUDGNextAdjacent(g, v1, v2); //取v1的下一个顶点21. }22.23. }24.}6.源代码1.#include<string.h>2.#include<malloc.h>3.#include<limits.h>4.#include<stdio.h>5.#include<stdlib.h>6.#include<io.h>7.#include<math.h>8.#define TRUE 19.#define FALSE 010.#define OK 111.#define ERROR -112.#define INFEASIBLE -113.#define MAXNAME 2014.#define MAXVEX 3015.#define MAXNUM 3016.typedef int DataType;17.typedef char VexType[MAXNAME];//顶点信息最长为20个字符18.typedef float AdjType;19.20.//定义一个队列(方便后面使用广度优先遍历)21.typedef struct22.{23. DataType data[MAXNUM];24.int front,rear;25.}SeqQueue;26.//置空队27.SeqQueue* SetSeqQueue()28.{29. SeqQueue *q = (SeqQueue* )malloc(sizeof(SeqQueue));30.if(q == NULL)31. printf("溢出!!\n");32.else33. q->front = q->rear = 0;34.return q;35.}36.//判断队空函数37.int SeqQueueISEmpty(SeqQueue *q)38.{39.if(q->front == q->rear)40. {41.return TRUE;42. }43.else44. {45.return FALSE;46. }47.}48.//入队49.void SeqQueueINQueue(SeqQueue *q,DataType x)50.{51.if(q->front == (q->rear + 1) % MAXNUM) printf("队满溢出!\n");52.else53. {54. q->rear++;55. q->data[q->rear % MAXNUM] = x;56. }57.}58.//出队59.void SeqQueueOUTQueue(SeqQueue *q,DataType *x)60.{61.if(q->front == q->rear) printf("队空!\n");62.else63. {64. q->front++;65. *x = q->data[q->front % MAXNUM];66. }67.}68.//队列部分结束69.70./*71.一.建立无向网邻接矩阵72.1.建立无向网的邻接矩阵73.2.实现插入的功能74.3.实现删除边的功能75.*/76.77.//定义图的邻接矩阵的数据结构78.typedef struct79.{80.int vexNum;81. VexType vexs[MAXVEX];82. AdjType arcs[MAXVEX][MAXVEX];83.}GraphMatrix;84.//建立无向网的邻接矩阵85.void CreateMGragh(GraphMatrix *g)86.{87.int i, j, k, t;88.float w;//权值89. printf("请输入无向网的顶点个数(不超过%d个): ",MAXVEX);90. scanf("%d",&g->vexNum);91. printf("\n请输入各顶点信息: \n");92. getchar();//吞掉上一步的回车93.for(i = 0; i < g->vexNum; i++)94. gets(g->vexs[i]);//输入各个顶点信息95.for (i = 0; i < g->vexNum; i++)96.for (j = 0; j < g->vexNum; j++)97. {98. g->arcs[i][j] = 0;//初始化邻接矩阵99. }100. printf("\n");101. printf("请输入图的边数(不超过%d个): ",(g->vexNum * (g->vexNum - 1))/2);102. scanf("%d",&k); //边的数目,这里的后面不用加getchar(),因为后面的一个输入的是一个整型类型103.for(t = 0; t < k; t++)104. {105. printf("\n请输入第%d条边的相关信息(起始顶点(序号从0开始) 终止顶点权值,如0 3 10.3)\n",t + 1);106. scanf("%d%d%f",&i,&j,&w);107. g->arcs[i][j] = w; //无向网的权是对称的108. g->arcs[j][i] = w;109. }110.}111.112.113.//无向网实现插入边114.void InsertAMArc(GraphMatrix *g, int i, int j, float weight)115.{116. g->arcs[i][j] = weight;117. g->arcs[j][i] = weight;118. printf("\n插入成功!\n");119.}120.121.//无向网实现删除边122.void DeleteAMArc(GraphMatrix *g, int i, int j)123.{124. g->arcs[i][j] = 0;125. g->arcs[j][i] = 0;126. printf("\n删除成功!\n");127.}128.129.//求无向网中与顶点i邻接的第一个顶点(为之后的广度优先做准备)130.int MUDGFirstAdjacent(GraphMatrix *g, int i)131.{132.int t;133.for(t = 0; t < g->vexNum; t++)134. {135.if(g->arcs[i][t] != 0) return t;136. }137.return ERROR;138.}139.140.//求无向网中与顶点i相对于顶点j的下一个邻接顶点(为之后的广度优先遍历做准备)141.int MUDGNextAdjacent(GraphMatrix *g, int i, int j)142.{143.int t;144.for(t = j + 1; t < g->vexNum; t++)145. {146.if(g->arcs[i][t] != 0) return t;147. }148.return ERROR;149.}150.151./*152.二.建立有向网邻接表153.1.建立有向网的邻接表154.2.实现插入的功能155.3.实现删除边的功能156.*/157.//建立图的数据结构158.typedef struct EdgeNode /*1.图的边结构定义*/159.{160.int endvex; //边顶点的索引161. AdjType weight; //边的权,非带权图可以忽略162.struct EdgeNode *next; //形成链表163.}EdgeNode;164.typedef struct/*2.图的顶点结构定义*/165.{166. VexType vertex; //顶点信息167. EdgeNode *firstarc; //边表头指针168.}VexNode; //顶点169.typedef struct/*3.图的邻接表结构*/170.{171.int VexNum; //图顶点个数172.int EdgeNum; //图边的条数173. VexNode vexs[MAXVEX];174.}GraphList;175.176./*在建立邻接表时要切记注意邻接表的具体结构以便后面去进行遍历,177.它不同于邻接矩阵在遍历的时候是按照从0到n-1的顺序来的,它是根据具体的链式结构得来的178.所以在进行创建林杰表示一定要注意插入顶点的先后顺序179.注:最好是先把邻接表给画出来,然后再去进行输入,在顶点直接连着的后面那个边节点一定是对于这个顶点的边来说,最后插入*/180.void CreateALGragh(GraphList *g)181.{182.int i,j,k;183. EdgeNode *s;184.float w;185. printf("请输入有向网的顶点个数,(不超过%d个): ",MAXVEX);186. scanf("%d",&g->VexNum);187. printf("请输入各个顶点的信息:\n");188. getchar();189.for(i = 0; i <g->VexNum; i++)190. {191. gets(g->vexs[i].vertex);192. g->vexs[i].firstarc = NULL;//这里vex[i].firstarc的点是因为vex[i]为结构体,所以引用它其中的内容使需要用"."运算符193. }194. printf("\n");195. printf("请输入图的边数(不超过%d个): ",g->VexNum * (g->VexNum - 1)); 196. scanf("%d",&g->EdgeNum);197.for(k = 0;k < g->EdgeNum; k++)198. {199. printf("\n请输入第%d条边的相关信息(起始顶点(序号从0开始) 终止顶点权值,如0 3 10.3)\n",k + 1);200. scanf("%d%d%f",&i,&j,&w);201. s = (EdgeNode*)(malloc(sizeof(EdgeNode)));202. s->endvex = j;203. s->next = g->vexs[i].firstarc;204. s->weight = w;205. g->vexs[i].firstarc = s;206. }207.}208.209.//有向网实现插入边210.void InsertALArc(GraphList *g, int i, int j, float w)211.{212. EdgeNode *s;213. s = (EdgeNode*)(malloc(sizeof(EdgeNode)));214. s->endvex = j;215. s->next = g->vexs[i].firstarc;216. s->weight = w;217. g->vexs[i].firstarc = s;218. printf("\n插入成功!\n");219.}220.221.//有向网实现删除边222.void DeleteALArc(GraphList *g, int i, int j)223.{224. EdgeNode *s, *temp;225. s = (EdgeNode*)(malloc(sizeof(EdgeNode)));226. temp = (EdgeNode*)(malloc(sizeof(EdgeNode)));227.int k = 0;228. s = g->vexs[i].firstarc;229. k = s->endvex;230.while(k != j)231. {232. temp = s;233. s = s->next;234. k = s->endvex;235. }236.if(k == g->vexs[i].firstarc->endvex)237. g->vexs[i].firstarc = s->next;238.else239. temp->next = s->next;240. printf("\n删除成功!\n");241.}242.//求有向网中与顶点i邻接的第一个顶点(为之后的广度优先做准备)243.int LUDGFirstAdjacent(GraphList *g, int i)244.{245.if(g->vexs[i].firstarc != NULL) return g->vexs[i].firstarc->endvex; 246.else return ERROR;247.}248.249.//求有向网中与顶点i相对于顶点j的下一个邻接顶点(为之后的广度优先遍历做准备)250.int LUDGNextAdjacent(GraphList *g, int i, int j)251.{252. EdgeNode *p;253. p = g->vexs[i].firstarc;254.while(p != NULL)255. {256.if(p->endvex == j)257. {258.if(p->next != NULL) return p->next->endvex;259.else return ERROR;260. }261. p = p->next;262. }263.return ERROR;264.}265.266.267./*三.深度优先遍历与广度优先遍历(无向网,有向网)*/268.//无向网(邻接矩阵实现的无向网)实现深度优先遍历269.void MUDGDFS(GraphMatrix *g, int v,int visited[])//visited数组是用来判断某节点是否被访问过的判断基准270.{271. DataType w;272. visited[v] = TRUE;273. printf("%d\t", v);274.for(w = MUDGFirstAdjacent(g, v); w != ERROR; w = MUDGNextAdjacent(g, v, w))275. {276.if(visited[w] != TRUE) //该顶点没有被访问过277. MUDGDFS(g,w,visited);//递归访问,实际上也是回到上一步所执行的函数,这里的递归可以仔细思考278. }279.}280.281.//有向网(邻接表实现的有向网)实现深度优先遍历282.void LUDGDFS(GraphList *g, int v, int visited[])//visited数组是用来判断某节点是否被访问过的判断基准283.{284. printf("%d\t", v);285. EdgeNode *p;286. visited[v] = TRUE; //以上是输出顶点信息,并置访问标志287. p = g->vexs[v].firstarc; //取出邻接顶点的链表头288.while(p)289. {290.if(visited[p->endvex] != TRUE)291. LUDGDFS(g, p->endvex, visited); //未访问过,则递归访问292. p = p->next; //取下一邻接点,实际上也是回到上一步执行的函数,这里的递归可以仔细思考293. }294.}295.296.//无向网(邻接矩阵实现的无向网)实现广度优先遍历297.void MUDGBFS(GraphMatrix *g, int v, int visited[])298.{299. DataType v1, v2;300. SeqQueue *q = SetSeqQueue(); //队列元素的类型为DataType(int)类型301. SeqQueueINQueue(q, v); //初始顶点入队302. printf("%d\t", v);303. visited[v] = TRUE; //初始顶点被访问304.while(!SeqQueueISEmpty(q))305. {306. SeqQueueOUTQueue(q, &v1); //对头元素出队,并将对头元素保存到v1中307. v2 = MUDGFirstAdjacent(g, v1);308.while (v2 != ERROR) //邻接顶点存在时进行循环309. {310.if (visited[v2] != TRUE) //如果邻接顶点未被访问则入队,访问,再改变visited标志311. {312. SeqQueueINQueue(q, v2);313. printf("%d\t", v2);314. visited[v2] = TRUE;315. }316. v2 = MUDGNextAdjacent(g, v1, v2); //取v1的下一个顶点317. }318.319. }320.}321.322.//有向网(邻接表实现的有向网)实现广度优先遍历323.void LUDGBFS(GraphList *g, int v, int visited[])324.{325. DataType v1, v2;326. SeqQueue *q = SetSeqQueue(); //队列元素的类型为DataType(int)类型327. SeqQueueINQueue(q, v); //初始顶点入队328. printf("%d\t", v);329. visited[v] = TRUE; //初始顶点被访问330.while(!SeqQueueISEmpty(q))331. {332. SeqQueueOUTQueue(q, &v1); //对头元素出队,并将对头元素保存到v1中333. v2 = LUDGFirstAdjacent(g, v1);334.while (v2 != ERROR) //邻接顶点存在时进行循环335. {336.if (visited[v2] != TRUE) //如果邻接顶点未被访问则入队,访问,再改变visited标志337. {338. SeqQueueINQueue(q, v2);339. printf("%d\t", v2);340. visited[v2] = TRUE;341. }342. v2 = LUDGNextAdjacent(g, v1, v2); //取v1的下一个顶点343. }344.345. }346.}347.348./*349.总结(广度优先(DFS)与深度优先(BFS)算法效率比较):350.1.空间复杂度都相同,都是O(n)(DFS借用栈,BFS借用队列)351.2.时间复杂度只与存储结构(邻接矩阵或邻接表)有关,而与搜索路径(广度,深度)无关, 352.*/353.354.//主函数355.void main()356.{357.int i;358. GraphMatrix *M;359. GraphList *L;360. M = (GraphMatrix *)malloc(sizeof(GraphMatrix));361. L = (GraphList *)malloc(sizeof(GraphList));362.int visited[MAXVEX];363.for(i = 0; i < MAXVEX; i++)364. visited[i] = FALSE;365. printf("\n创建无向网的邻接矩阵,并对其进行遍历!\n");366. CreateMGragh(M);367. printf("插入(1,3)边"); //插入(1,3)边368. InsertAMArc(M, 1, 3, 1);369. printf("删除(2,3)边");370. DeleteAMArc(M, 2, 3); //删除(2,3)边371. printf("无向网深度遍历结果为:\n");372. MUDGDFS(M, 0, visited);373.for(i = 0; i < MAXVEX; i++)374. visited[i] = FALSE;375. printf("\n无向网广度遍历结果为:\n");376. MUDGBFS(M, 0, visited);377.378. printf("\n\n--------------------------------\n\n");379.380. printf("\n创建有向网的邻接表,并对其进行遍历!\n");381. CreateALGragh(L);382. printf("插入(4,2)边");383. InsertALArc(L, 4, 2, 1);384. printf("删除(0,3)边");385. DeleteALArc(L, 0, 3);386.for(i = 0; i < MAXVEX; i++)387. visited[i] = FALSE;388. printf("有向网深度遍历结果为:\n");389. LUDGDFS(L, 0, visited);390.for(i = 0; i < MAXVEX; i++)391. visited[i] = FALSE;392. printf("\n有向网深度遍历结果为:\n");393. LUDGBFS(L, 0, visited);394.}7.测试图8.实验总结本节实验主要学习了图的两种建立方式,一种是图的邻接矩阵另一种是图的邻接表,在无向有权图的邻接矩阵中,用0,权值分别代表无关系和有关系,而在邻接表的表示中,定义了三种结构体,一个是边节点,一个是顶点节点,一个是图结构,且采用的是顺序存储与链式存储相结合。

相关文档
最新文档