实验六 图的邻接表存储及遍历
数据结构-实验6图的存储和遍历

实验6.1实现图的存储和遍历一,实验目的掌握图的邻接矩阵和邻接表存储以及图的邻接矩阵存储的递归遍历。
二,实验内容6.1实现图的邻接矩阵和邻接表存储编写一个程序,实现图的相关运算,并在此基础上设计一个主程序,完成如下功能:(1)建立如教材图7.9所示的有向图G的邻接矩阵,并输出。
(2)由有向图G的邻接矩阵产生邻接表,并输出。
(3)再由(2)的邻接表产生对应的邻接矩阵,并输出。
6.2 实现图的遍历算法(4)在图G的邻接矩阵存储表示基础上,输出从顶点V1开始的深度优先遍历序列(递归算法)。
(5)利用非递归算法重解任务(4)。
(6)在图G的邻接表存储表示基础上,输出从顶点V1开始的广度优先遍历序列。
三,源代码及结果截图#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream.h>#include<malloc.h>#define MAX_VERTEX_NUM 20typedef char VRType;typedef int InfoType; // 存放网的权值typedef char VertexType; // 字符串类型typedef enum{DG,DN,AG,AN}GraphKind; // {有向图,有向网,无向图,无向网}/*建立有向图的邻接矩阵*/typedef struct ArcCell{VRType adj;//VRType是顶点关系类型,对无权图用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;/* 顶点在顶点向量中的定位*/int LocateVex(MGraph &M,VRType v1){int i;for(i=0;i<M.vexnum;i++)if(v1==M.vexs[i])return i;return -1;}void CreateGraph(MGraph &M)//建立有向图的邻接矩阵{int i,j,k,w;VRType v1,v2;M.kind=DN;printf("构造有向网:\n");printf("\n输入图的顶点数和边数(以空格作为间隔):");scanf("%d%d",&M.vexnum,&M.arcnum);printf("输入%d个顶点的值(字符):",M.vexnum);getchar();for(i=0;i<M.vexnum;i++) //输入顶点向量{scanf("%c",&M.vexs[i]);}printf("建立邻接矩阵:\n");for(i=0;i<M.vexnum;i++)for(j=0;j<M.vexnum;j++){M.arcs[i][j].adj=0;M.arcs[i][j].info=NULL;}printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n");for(k=0;k<M.arcnum;++k)// 构造表结点链表{cin>>w>>v1>>v2;i=LocateVex(M,v1);j=LocateVex(M,v2);M.arcs[i][j].adj=w;}}//按邻接矩阵方式输出有向图void PrintGraph(MGraph M){int i,j;printf("\n输出邻接矩阵:\n");for(i=0; i<M.vexnum; i++){printf("%10c",M.vexs[i]);for(j=0; j<M.vexnum; j++)printf("%2d",M.arcs[i][j].adj);printf("\n");}}// 图的邻接表存储表示typedef struct ArcNode{int adjvex; // 该弧所指向的顶点的位置struct ArcNode *nextarc; // 指向下一条弧的指针InfoType *info; // 网的权值指针)}ArcNode; // 表结点typedef struct VNode{VertexType data; // 顶点信息ArcNode *firstarc; // 第一个表结点的地址,指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];// 头结点typedef struct{AdjList vertices;int vexnum,arcnum; // 图的当前顶点数和弧数int kind; // 图的种类标志}ALGraph;void CreateMGtoDN(ALGraph &G,MGraph &M){//由有向图M的邻接矩阵产生邻接表int i,j;ArcNode *p;G.kind=M.kind;G.vexnum=M.vexnum;G.arcnum=M.arcnum;for(i=0;i<G.vexnum;++i){//构造表头向量G.vertices[i].data=M.vexs[i];G.vertices[i].firstarc=NULL;//初始化指针}for(i=0;i<G.vexnum;++i)for(j=0;j<G.vexnum;++j)if(M.arcs[i][j].adj){p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;p->nextarc=G.vertices[i].firstarc;p->info=M.arcs[i][j].info;G.vertices[i].firstarc=p;}}void CreateDNtoMG(MGraph &M,ALGraph &G){ //由邻接表产生对应的邻接矩阵int i,j;ArcNode *p;M.kind=GraphKind(G.kind);M.vexnum=G.vexnum;M.arcnum=G.arcnum;for(i=0;i<M.vexnum;++i)M.vexs[i]=G.vertices[i].data;for(i=0;i<M.vexnum;++i){p=G.vertices[i].firstarc;while(p){M.arcs[i][p->adjvex].adj=1;p=p->nextarc;}//whilefor(j=0;j<M.vexnum;++j)if(M.arcs[i][j].adj!=1)M.arcs[i][j].adj=0;}//for}//输出邻接表void PrintDN(ALGraph G){int i;ArcNode *p;printf("\n输出邻接表:\n");printf("顶点:\n");for(i=0;i<G.vexnum;++i)printf("%2c",G.vertices[i].data);printf("\n弧:\n");for(i=0;i<G.vexnum;++i){p=G.vertices[i].firstarc;while(p){printf("%c→%c(%d)\t",G.vertices[i].data,G.vertices[p->adjvex].data,p->info);p=p->nextarc;}printf("\n");}//for}int visited[MAX_VERTEX_NUM]; // 访问标志数组(全局量)void(*VisitFunc)(char* v); // 函数变量(全局量)// 从第v个顶点出发递归地深度优先遍历图G。
图的邻接表存储结构实验报告

《图的邻接表存储结构实验报告》1.需解决的的问题利用邻接表存储结果,设计一种图。
2.数据结构的定义typedef struct node{//边表结点int adj;//边表结点数据域struct node *next;}node;typedef struct vnode{//顶点表结点char name[20];node *fnext;}vnode,AList[M];typedef struct{AList List;//邻接表int v,e;//顶点树和边数}*Graph;3.程序的结构图4.函数的功能1)建立无向邻接表Graph Create1( )//建立无向邻接表{Graph G;int i,j,k;node *s;G=malloc(M*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++)//建立边表--建立了2倍边的结点{ printf("请输入边的两顶点序号:(从0考试)");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;}2)建立有向邻接图Graph Create2() //有向邻接图{Graph G;int i,j,k;node *q;G=malloc(M*sizeof(vnode));printf("请输入顶点数和弧数:");scanf("%d%d",&G->v,&G->e);for (i=0;i<G->v;i++) //建立有n个顶点的顶点表{ printf("请输入图第%d个元素:",i+1);scanf("%s",&G->List[i].name); //读入顶点信息G->List[i].fnext=NULL;}for (k=0;k<G->e;k++) //建立边表{ printf("请输入两顶点的序号:(从0开始)");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;}3)输出无向图的邻接表void Print1(Graph G)//输出无向图的邻接表{int i;node *p;printf("\n\t\t\t邻接表\n");for(i=0;i<G->v;i++){ p=G->List[i].fnext;printf("\t\t\t%d | %3s",i,G->List[i].name);while(p){printf("->%d",p->adj);p=p->next;}printf("\n");}}4)输出个元素的度数void Du(Graph G)//输出各元素的度数{int i,j;node *p;printf("\n\t\t\t各点度数\n");for(i=0;i<G->v;i++){ p=G->List[i].fnext;printf("\t\t\t顶点%2s的度为:",G->List[i].name);j=0;while(p){ j++;p=p->next;}printf("%d\n",j);}}5)返回图结点在的序号int LocateVex(Graph G,char *u){//初始条件:图G存在,u和G中顶点有相同的特征//操作结果:若G中存在顶点u,则返回该顶点在图中的位置;否则返回-1 int i;for(i=0;i<G->v;++i)if(strcmp(u,G->List[i].name)==0)return -1;}6)返回序号为v的图结点的值char *VertexGet(Graph G,int v){if(v>=G->v||v<0)exit(0);return G->List[v].name;}7)返回图结点v的第一个邻接顶点的序号int FirstAdjVex(Graph G,char *v){//初始条件:图G存在,v是G中的某个顶点//操作结果:返回v中第一个邻接顶点的序号。
数据结构实验报告-图的遍历

数据结构实验报告实验:图的遍历一、实验目的: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、实验目的掌握图这种复杂的非线性结构的邻接矩阵和邻接表的存储表示,以及在此两种常用存储方式下深度优先遍历(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算法的实现思想与以邻接矩阵为存储结构的实现是一样的。
实验六 图及其应用

实验六图及其应用数据结构实验六图及其应用1、实验目的? 熟练掌握图的两种存储结构(邻接矩阵和邻接表)的表示方法 ? 掌握图的基本运算及应用? 加深对图的理解,逐步培养解决实际问题的编程能力2、实验内容:采用邻接表或邻接矩阵方式存储图,实现图的深度遍历和广度遍历;用广度优先搜索方法找出从一顶点到另一顶点边数最少的路径。
1.问题描述:利用邻接表存储结构,设计一种图(有向或无向),并能够对其进行如下操作:1) 创建一个可以随机确定结点数和弧(有向或无向)数的图; 2) 根据图结点的序号,得到该结点的值;3) 根据图结点的位置的第一个邻接顶点的序号,以及下一个邻接顶点的序号;4) 实现从第v 个顶点出发对图进行深度优先递归遍历; 5) 实现对图作深度优先遍历;6) 实现对图进行广度优先非递归遍历; 编写主程序,实现对各不同的算法调用。
2.实现要求:(以邻接表存储形式为例)编写图的基本操作函数::对图的各项操作一定要编写成为C(C++)语言函数,组合成模块化的形式,每个算法的实现要从时间复杂度和空间复杂度上进行评价。
1)“建立图的邻接表算法”:CreateGraph(ALGraph *G) 操作结果:采用邻接表存储结构,构造没有相关信息的图G2)“邻接表表示的图的递归深度优先遍历算法”:DFSTraverse(ALGraphG,void(*Visit)(char*)) 初始条件:图G 已经存在;操作结果:返回图的按深度遍历的结果。
3)“邻接表表示的图的广度优先遍历算法”: BFSTraverse(ALGraphG,void(*Visit)(char*)) 初始条件:图G 已经存在;操作结果:返回图的按广度遍历的结果。
4)“邻接表从某个结点开始的广度优先遍历算法”:BFS(ALGraph G, int v)初始条件:图G 已经存在;操作结果:返回图从某个结点开始的按广度遍历的结果。
分析: 修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。
实验报告:图的存储结构和遍历

武汉东湖学院
实验报告
学院:计算机科学学院专业计算机科学与技术2016年11月18日
姓名付磊学号42
班级计科一班指导老师吴佳芬
课程名称数据结构成
绩
实验名称图的存储结构和遍历
1.实验目的
(1)了解邻接矩阵存储法和邻接表存储法的实现过程。
(2)了解图的深度优先遍历和广度优先遍历的实现过程。
2.实验内容
1. 采用图的邻接矩阵存储方法,实现下图的邻接矩阵存储,并输出该矩阵.
2. 设计一个将第1小题中的邻接矩阵转换为邻接表的算法,并设计一个在屏幕上显示邻接表的算法
3. 实现基于第2小题中邻接表的深度优先遍历算法,并输出遍历序列
4. 实现基于第2小题中邻接表的广度优先遍历算法,并输出遍历序列
3.实验环境
Visual C++ 6.0
4.实验方法和步骤(含设计)
我们通过二维数组中的值来表示图中节点与节点的关系。
通过上图可知,其邻接矩阵示意图为如下:
V0 v1 v2 v3 v4 v5
V0 0 1 0 1 0 1
V1 1 0 1 1 1 0
V2 0 1 0 0 1 0
V3 1 1 0 0 1 1
V4 0 1 1 1 0 0
V5 1 0 0 1 0 0
此时的“1”表示这两个节点有关系,“0”表示这两个节点无关系。
我们通过邻接表来在计算机中存储图时,其邻接表存储图如下:
}。
图的dfs遍历模板(邻接表和邻接矩阵存储)

图的dfs遍历模板(邻接表和邻接矩阵存储)我们做算法题的⽬的是解决问题,完成任务,⽽不是创造算法,解题的过程是利⽤算法的过程⽽不是创造算法的过程,我们不能不能陷⼊这样的认识误区。
⽽想要快速⾼效的利⽤算法解决算法题,积累算法模板就很重要,利⽤模板可以使我们编码更⾼效,思路更清晰,不容易出bug.下⾯是利⽤DFS算法思想遍历图的模板。
邻接矩阵版://邻接矩阵版int n, G[MAXV][MAXV]; //n为顶点数bool vis[MAXV] = { false }; //⼊股顶点i已经被访问,则vis[i] = true,初值为falsevoid dfs(int u, int depth){ //u为当前访问的顶点标号,depth为深度vis[u] = true; //设置u已经被访问//如果需要对u进⾏⼀些操作,可以在这⾥进⾏//下⾯对所有从u出发能到达的分治顶点进⾏枚举for (int v = 0; v < n; v++){if (vis[v] == false && G[u][v] != INF){ //如果v未被访问,且u可到达vdfs(v, depth + 1); //访问v,深度加⼀}}}void dfsTrave(){for (int u = 0; u < n; u++){if (vis[u] == false){dfs(u, 1); //访问u和u所在的连通块,1表⽰初识为第⼀层}}}邻接表版(顶点类型为结构体):1struct Node{2int v;3int w;4 };56//邻接表版7 vector<Node> Adj[MAXV]; //图G的邻接表8int n; //n为顶点数,MAXV最⼤顶点数9bool vis[MAXV] = { false };1011void dfs(int u, int depth){12 vis[u] = true;1314/*如果需要对u进⾏⼀些操作可以在此处进⾏*/15for (int i = 0; i < Adj[u].size(); i++){16int v = Adj[u][i].v;17if (vis[v] == false){18 dfs(v, depth + 1);19 }20 }21 }2223void dfsTrave(){24for (int u = 0; u < n; u++){25if (vis[u] == false){26 dfs(u, 1);27 }28 }29 }图的遍历题型实战:One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A "Gang" is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threshold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.Input Specification:Each input file contains one test case. For each case, the first line contains two positive numbers N and K (both less than or equal to 1000),the number of phone calls and the weight threthold, respectively. Then N lines follow, each in the following format:Name1 Name2 Timewhere Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.Output Specification:For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.Sample Input 1:8 59AAA BBB 10BBB AAA 20AAA CCC 40DDD EEE 5EEE DDD 70FFF GGG 30GGG HHH 20HHH FFF 10Sample Output 1:2AAA 3GGG 3Sample Input 2:8 70AAA BBB 10BBB AAA 20AAA CCC 40DDD EEE 5EEE DDD 70FFF GGG 30GGG HHH 20HHH FFF 10Sample Output 2:题⽬要求⼤意:找出每个连通分量中总边权最⼤的点,并统计相应连通分量中点的数量代码:1 #include <stdio.h>2 #include <iostream>3 #include <string>4 #include <map>56using namespace std;78const int maxn = 2010;9const int INF = 1000000000;1011 map<string, int> stringToInt; // 将名字转换成数字12 map<int,string> intToString; // 将编号转换成名字13 map<string, int> gang; // 每个团伙的头⽬以及⼈数1415int G[maxn][maxn] = { 0 }, weight[maxn] = { 0 }; // 矩阵以及点权16int n, k, numPerson = 0; // 边数,下限数,总⼈数numperson17bool vis[maxn] = { false }; // 标记是否被访问1819// DFS函数访问单个连通块20// nowVisit为当前访问的编号21// head为头⽬的编号22void DFS(int visNow, int& head, int& numMember, int& totalValue){23 vis[visNow] = true;24 numMember++;25if (weight[head] < weight[visNow]){26 head = visNow;27 }2829// 访问当前顶点的所有邻接点30for (int i = 0; i < numPerson; i++){31if (G[visNow][i] > 0){32 totalValue += G[visNow][i];33 G[visNow][i] = G[i][visNow] = 0;34if (vis[i] == false){35 DFS(i, head, numMember, totalValue);36 }3738 }39 }4041 }4244void DFSTrave(){45for (int i = 0; i < numPerson; i++){46if (vis[i] == false){47int head = i, numMember = 0, totalValue = 0;48 DFS(i, head, numMember, totalValue);49if (numMember > 2 && totalValue > k){50 gang[intToString[head]] = numMember;51 }52 }53 }54 }5556// 根据名字获取名字的编号57int change(string str){58if (stringToInt.find(str) != stringToInt.end()){ // 如果str已经存在59return stringToInt[str];60 }61else{62 stringToInt[str] = numPerson; // 编号63 intToString[numPerson] = str;64return numPerson++;65 }66 }6768int main()69 {70// 读取输⼊71// freopen("in.txt", "r", stdin);72int w;73string str1, str2;74 cin >> n >> k;75for (int i = 0; i < n; i++){76 cin >> str1 >> str2 >> w;77// 读⼊每个名字都转化成编号78int id1 = change(str1);79int id2 = change(str2);80// 存⼊对称矩阵81 weight[id1] += w;82 weight[id2] += w;83 G[id1][id2] += w;84 G[id2][id1] += w;8586 }87// 遍历矩阵,统计数据88 DFSTrave();8990// 遍历map,输⼊结果91 cout << gang.size() << endl;92for (map<string, int>::iterator it = gang.begin(); it != gang.end(); it++){93 cout << it->first << "" << it->second << endl;94 }9596// fclose(stdin);97return0;98 }。
图的邻接表存储实现及深度优先遍历

第四次实验报告图的邻接表存储实现及深度优先遍历学号0708140119 电子072 姓名陆萍萍一、问题描述1、程序所能达到的基本功能构建以邻接表形式存储的表及实现深度优先遍历并输出结果。
2、输入的形式和输入值的范围:根据提示进行输入:先输入要构建的表的结点数和边数,要求是整型;输入各结点的代号,这里用char型,也可在源程序中改变其它形式;输入各边的头结点和尾结点的代号;3、输出的形式若正常输入,则输出深度优先遍历的最后结果。
用各结点的代码表示。
测试数据要求第一组数据:结点数和边数:4 4结点名称:a b c d边:a-b a-c b-c c-d 输出a-b-c-d-over!第二组数据:图如下:输出a-b-c-d-e-f-g-over! 4、概要设计1、抽象数据类型,它们的作用//图的结点类template<class T>class TVex{};//图类template<class T>class Graph{}//链表存储2主程序流程及模块调用关系(1)主程序模块:void main{构造一个图,对T实例化(char)。
调用Graph中的Create函数;调用Graph中的DFS函数;}(22、核心算法的粗线条伪码5、详细设计(要求主要变量和语句加注释)1、抽象数据类型的实现:包括类型定义和各个操作的实现。
1)TVex的详细设计(1)私有数据类型的定义private:T m_elem;TLinklist<int> m_arcs;2)Graph的详细设计(1)私有数据类型的定义private:TVex<T> Vextex[maxnum];int vexnum;int arcnum;int kind;int symbol[maxnum];(2)公有函数成员的定义Graph();void Create();int LocateVex(T v);void DFS();void DFS_IN(int i);(3)具体实现★template<class T>void Graph<T>::Create(){T v1,v2;int i,j;cout<<"*********************基本信息*****************************"<<endl;cout<<"请分别输入结点数和边数: ";cin>>vexnum>>arcnum;cout<<"***********************结点***************************"<<endl;for(int l=0;l<vexnum;l++){cout<<"请输入第"<<l+1<<"个结点的代号 ";cin>>Vextex[l].m_elem;}cout<<"***********************边数***************************"<<endl;for(int k=0;k<arcnum;k++){cout<<"请输入第"<<k+1<<"边的头结点和尾结点 ";cin>>v1>>v2;i=LocateVex(v1);j=LocateVex(v2);Vextex[i].m_arcs.InsertLate(j);Vextex[j].m_arcs.InsertLate(i);}cout<<"************************结果**************************"<<endl; }★template<class T>int Graph<T>::LocateVex(T v){for(int i=0;i<vexnum&&Vextex[i].m_elem!=v;i++); if(i==vexnum)return -1;elsereturn i;}★template<class T>void Graph<T>::DFS(){DFS_IN(0);cout<<"over!"<<endl;}★template<class T>void Graph<T>::DFS_IN(int i){int index;symbol[i]=1;cout<<Vextex[i].m_elem<<"-->";for(int j=0;;j++){index=Vextex[i].m_arcs.GetElem(j+1);if(index!=-1){if(symbol[index]!=1)DFS_IN(index);}elsebreak;}}2、其他主要算法的实现将次要算法均设为Graph的公有函数成员3、主程序的实现Void main(){huffmanTree<char> h;int *ww,n;char *cc;cout<<"请输入叶子节点的个数:";cin>>n;ww=new int[n];cc=new char[n];cout<<"请依次输入节点名称和权重:"<<endl;for(int i=1;i<=n;i++){cout<<"第"<<i<<"个"<<endl;cout<<" 名称:";cin>>cc[i-1];cout<<" 权重: ";cin>>ww[i-1];}h.CreatehuffmanTree(cc,ww,n);h.huffmanTreecoding();}四 .调试分析1、设计与调试过程中遇到的问题及分析、体会(1)这个实验较简单,经过对书本上已经给出的c版程序的分析,很容易就写出了对整个实验的大体思路。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
printf("\n"); /* 换行 */
}
}
{
printf("顶点%d =>",head[i].vertex);/* 顶点值 */
ptr = head[i].nextnode; /* 顶点位置 */
while ( ptr != NULL ) /* 遍历至链表尾 */
{
printf(" %d ",ptr->vertex); /* 输出顶点内容 */
2)当队列非空时重复做:
(1)取பைடு நூலகம்首顶点;
(2)对与队首顶点邻接的所有未被访问的顶点依次做:
打印该顶点;
置顶点为“已访问”标志;
该顶点入队;
否则,当前队首顶点出队。
3) 结束。
三、目的要求
1.掌握图的基本存储方法;
2.掌握有关图的操作算法并用高级语言实现;
3.熟练掌握图的两种搜索路径的遍历方法。
四、实验内容
1.编写程序实现下图的邻接表表示及其基础上的深度和广度优先遍历。
五、程序实例
图的邻接表表示法的C语言描述:
#include <stdlib.h>
#include <stdio.h>
struct node /* 图形顶点结构定义 */
{
int vertex; /* 顶点 */
struct node *nextnode; /* 指下一顶点的指针 */
};
typedef struct node *graph;
struct node head[vertexnum];
2.图的遍历
深度优先遍历(DFS)法:
算法步骤:
1)初始化:
(1)置所有顶点“未访问”标志;
(2)打印起始顶点;
(3)置起始顶点“已访问”标志;
(4)起始顶点进栈。
2)当栈非空时重复做:
/* 申请存储新顶点的内存空间 */
newnode = ( graph ) malloc(sizeof(struct node));
newnode->vertex = to; /* 建立顶点内容 */
newnode->nextnode = NULL; /* 设定指针初值 */
ptr = &(head[from]); /* 顶点位置 */
{
graph ptr;
int node[12][2] = { {1, 2}, {2, 1}, /* 边线数组 */
{1, 3}, {3, 1},
{2, 3}, {3, 2},
{2, 4}, {4, 2},
{3, 5}, {5, 3},
{4, 5}, {5, 4} };
int i;
for ( i = 1; i <= 5; i++ )
实验六 图的邻接表存储及遍历
一、实验学时2学时
二、背景知识
1.图的邻接表存储结构
在图的邻接表中,图中每个顶点都建立一个单链表,第i个单链表中的结点数为顶点i的出度。(逆邻接表中,第i个单链表中的结点数为顶点i的入度)
邻接表的数据结构描述为:
struct node
{ int vertex;
struct node *nextnode;
graph ptr;
int from; /* 边线的起点 */
int to; /* 边线的终点 */
int i;
for ( i = 0; i < num; i++ ) /* 读取边线的回路 */
{
from = node[i*2]; /* 边线的起点 */
to = node[i*2+1]; /* 边线的终点 */
while ( ptr->nextnode != NULL ) /* 遍历至链表尾 */
ptr = ptr->nextnode; /* 下一个顶点 */
ptr->nextnode = newnode; /* 插入结尾 */
}
}
/*------主程序: 建立图形后,将邻接链表输出------*/
void main()
{
head[i].vertex = i; /* 设定顶点值 */
head[i].nextnode = NULL; /* 清除图形指针 */
}
creategraph(*node,12); /* 建立图形 */
printf("图形的邻接链表内容:\n");
for ( i = 1; i <= 5; i++ )
};
typedef struct node *graph; /* 图形的结构重定义 */
struct node head[6]; /* 图形顶点结构数组 */
/*----------建立图形--------*/
void creategraph(int *node,int num)
{
graph newnode; /* 新顶点指针 */
(1)取栈顶点;
(2)如栈顶顶点存在未被访问过的邻接顶点,则选择第一个顶点做:
打印该顶点;
置顶点为“已访问”标志;
该顶点进栈;
否则,当前栈顶顶点退栈。
3)结束。
广度优先遍历(BFS)法:
算法步骤:
1) 初始化:
(1)置所有顶点“未访问”标志;
(2)打印起始顶点;
(3)置起始顶点“已访问”标志;
(4)起始顶点入队。