采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作

采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作
采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作

/* 采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作 */

#include "stdio.h"

#include "string.h"

#define TRUE 1

#define FALSE 0

#define OVERFLOW -2

#define OK 1

#define ERROR 0

typedef int Status;

#define INFINITY INT_MAX /*最大值“无穷”*/

#define MAX_VERTEX_NUM 20 /*最大顶点个数*/

typedef int Boolean;

typedef char VertexType[20];

typedef int VRType;

/**************以下为队列的操作************/

/****队列的类型定义****/

typedef int QElemType;

typedef struct QNode

{QElemType data;

struct QNode *next;

} QNode, *QueuePtr;

typedef struct

{

QueuePtr front;

QueuePtr rear;

} LinkQueue;

/****初始化队列****/

Status InitQueue(LinkQueue *Q)

{ (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));

if (!(*Q).front) exit(OVERFLOW);

(*Q).front->next=NULL;

return OK; }

/****判断队列是否为空****/

Status QueueEmpty (LinkQueue Q)

{ if (Q.front==Q.rear)

return TRUE;

else

return FALSE; }

/****入队列****/

Status EnQueue(LinkQueue *Q, QElemType e)

{ QueuePtr p;

p=(QueuePtr)malloc(sizeof(QNode));

if (!p) exit(OVERFLOW);

p->data=e; p->next=NULL;

(*Q).rear->next=p;

(*Q).rear=p;

return OK; }

/****出队列****/

Status 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; }

/**************以下为图的操作************/

/*图的类型定义*/

typedef struct ArcCell

{ VRType adj; /*图中有1/0表示是否有边,网中表示边上的权值*/ /* InfoType *info; 与边相关的信息*/

} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct

{ VertexType vexs[MAX_VERTEX_NUM]; /*顶点向量*/

AdjMatrix arcs; /*邻接矩阵*/

int vexnum,arcnum; /*图中当前顶点数和边数*/

} MGraph;

/*建立无向图的邻接矩阵*/

void CreateGraph(MGraph *G)

{ int i,j,k; VertexType v1,v2;

printf("\nInput MG vexnum,arcnum:");

scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);

printf("Input %d vexs:",(*G).vexnum);

for(i=0;i<(*G).vexnum;i++) /*输入顶点向量*/ { scanf("%s",(*G).vexs[i]); }

printf("vexs list\n");

for(i=0;ivexnum;i++) /*输出顶点向量*/

puts(G->vexs[i]);

for(i=0;i<(*G).vexnum;i++) /*邻接矩阵初始化*/ for(j=0;j<(*G).vexnum;j++)

(*G).arcs[i][j].adj=0;

printf("\nInput %d arcs(vi vj):\n",(*G).arcnum); for(k=0;k<(*G).arcnum;k++) /*输入无权图的边*/ { 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];

}

}

/* 顶点在顶点向量中的定位*/

int LocateVex(MGraph G,VertexType v)

{ int i;

for(i=0;i

if (strcmp(v,G.vexs[i])==0) break;

return i;

}

/* 查找第1个邻接点 */

int FirstAdjVex(MGraph G,int v)

{ int j,p=-1;

for(j=0;j

if (G.arcs[v][j].adj==1) {p=j; break;}

return p;

}

/* 查找下一个邻接点 */

int NextAdjVex(MGraph G,int v,int w)

{ int j,p=-1;

for(j=w+1;j

if (G.arcs[v][j].adj==1) {p=j; break;}

return p;

}

/*按邻接矩阵方式输出无向图*/

void PrintGraph(MGraph G)

{ int i,j;

printf("\nMGraph:\n");

for(i=0; i

{ printf("%10s",G.vexs[i]);

for(j=0; j

printf("%4d",G.arcs[i][j].adj);

printf("\n");

}

}

/*深度遍历*/

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))

if(!visited[w]) Dfs(G,w);

}

void DfsTraverse(MGraph G)

{ int v;

for (v=0; v

visited[v]=FALSE;

for(v=0; v

if (!visited[v]) Dfs(G,v);

}

/* 广度遍历 */

void BfsTraverse(MGraph G)

{ int v,u,w; LinkQueue Q;

for(v=0; v

InitQueue(&Q);

for(v=0; v

if (!visited[v])

{ visited[v]=TRUE;

printf("%s",G.vexs[v]);

EnQueue(&Q,v);

while(!QueueEmpty(Q))

{ DeQueue(&Q,&u);

for(w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w))

if (!visited[w])

{ visited[w]=TRUE;

printf("%s",G.vexs[w]);

EnQueue(&Q,w);

}

}

}

}

/*主函数*/

main()

{ int w;

MGraph G;

CreateGraph(&G);

PrintGraph(G);

printf("\nDfs:"); DfsTraverse(G); /* 深度遍历 */ printf("\nBfs:"); BfsTraverse(G); /* 广度遍历 */ }

图的深度广度优先遍历操作代码

一、实验目的 1.掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表存储结构; 2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和宽度优先遍历算法,复习栈和队列的应用; 3.掌握图的各种应用的算法:图的连通性、连通分量和最小生成树、拓扑排序、关键路径。 二、实验内容 实验内容1**图的遍历 [问题描述] 许多涉及图上操作的算法都是以图的遍历为基础的。写一个程序,演示在连通无向图上遍历全部顶点。 [基本要求] 建立图的邻接表的存储结构,实现无向图的深度优先遍历和广度优先遍历。以用户指定的顶点为起点,分别输出每种遍历下的顶点访问序列。 [实现提示] 设图的顶点不超过30个,每个顶点用一个编号表示(如果一个图有N个顶点,则它们的编号分别为1,2,…,N)。通过输入图的全部边输入一个图,每条边是两个顶点编号对,可以对边依附顶点编号的输入顺序作出限制(例如从小到大)。 [编程思路] 首先图的创建,采用邻接表建立,逆向插入到单链表中,特别注意无向是对称插入结点,且要把输入的字符在顶点数组中定位(LocateVex(Graph G,char *name),以便后来的遍历操作,深度遍历算法采用递归调用,其中最主要的是NextAdjVex(Graph G, int v, int w);FirstAdjVex ()函数的书写,依次递归下去,广度遍历用队列的辅助。 [程序代码] 头文件: #include #include #define MAX_VERTEX_NUM 30 #define MAX_QUEUE_NUMBER 30 #define OK 1 #define ERROR 0 #define INFEASIBLE -1

图的深度和广度优先遍历

数据结构课程实验报告 课程名称数据结构班级计算123 实验日期2014年6月1日--3日 姓名学号实验成绩实验名称实验四图的深度和广度优先遍历 实验目的及要求【实验目的】 熟练掌握图的邻接表存储结构及其图的建立方法和深度和广度优先遍历的方法。 【实验要求】 1.图的存储可采用邻接矩阵或邻接表 2.GraphCreate(): 按从键盘的数据建立图 3.GraphDFS():深度优先遍历图 4.GraphBFS():广度优先遍历图 5.编写完整程序完成下面的实验内容并上机运行 6.整理并上交实验报告 实验环境硬件平台:普通的PC机 软件平台:Windows 7 操作系统编程环境:VisualC++ 6.0 实验内容1.以邻接矩阵或邻接表为存储结构,以用户指定的顶点为起始点,实现图的深度优先及广度优先搜索遍历,并输出遍历的结点序列。

算法描述及实验步骤算法: 1)定义图的邻接表存储结构 2)实现图的邻接表存储,即建立图的存储结构 3)实现图的深度优先遍历 4)定义队列的顺序存储结构,并实现队列的基本操作如初始化队列、入队、出对、判断队列是否为空等。利用队列实现图的广度优先遍历。伪代码: 1)定义邻接矩阵和队列的存取结构; 2)创建图L: 1.置空图L->num=0; 2.输入顶点数目num; 3.i++,输入结点L->vexs[i]直到L->num; 3)输出图L的各顶点; 4)深度优先遍历图g中能访问的各个顶点 1.输入起点的下标qidian; 2.标志数组初始化mark[v]=0; 3.for(v=qidian;v

图的邻接矩阵存储及遍历

实验五 图的邻接矩阵存储及遍历 一、实验学时 2学时 二、背景知识 1.图的邻接矩阵存储结构 设图G =(V ,E )有 n>=1个顶点,其编号分别为1,2,…,n 。描述图G 的邻接矩阵 为二维数组A[1…n ,1…n],A 的元素定义为: A []j i ,=???,,01否则)属于)或(若(E ,,i j j i v v v v 显然无向图的邻接矩阵一定是对称的。 对于网,其邻接矩阵A 的元素定义为: A []j i ,=?? ???∞=无邻接边到顶点若顶点若为该边上的权有邻接边,到顶点若顶点j i j i w j i w j i j i 0,, 2.图的遍历 深度优先遍历(DFS )法: 算法步骤: 1)初始化: (1)置所有顶点“未访问”标志; (2)打印起始顶点; (3)置起始顶点“已访问”标志; (4)起始顶点进栈。 2)当栈非空时重复做: (1)取栈顶点; (2)如栈顶顶点存在被访问过的邻接顶点,则选择一个顶点做: ① 打印该顶点; ② 置顶点为“已访问”标志; ③ 该顶点进栈; 否则,当前栈顶顶点退栈。 3)结束。 广度优先遍历(BFS )法: 算法步骤: 1) 初始化: (1)置所有顶点“未访问”标志; (2)打印起始顶点; (3)置起始顶点“已访问”标志; (4)起始顶点入队。 2)当队列非空时重复做: (1)取队首顶点; (2)对与队首顶点邻接的所有未被访问的顶点依次做: ① 打印该顶点; ② 置顶点为“已访问”标志; ③ 该顶点入队;

否则,当前队首顶点出队。 3) 结束。 三、目的要求 1.掌握图的基本存储方法; 2.掌握有关图的操作算法并用高级语言实现; 3.熟练掌握图的两种搜索路径的遍历方法。 四、实验内容 编写程序实现下图的邻接矩阵表示及其基础上的深度和广度优先遍历。 五、程序实例 图的邻接矩阵表示法的C语言描述: #include #include #include #define INFINITY 32767 #define MAX_VERTEX_MUN 20 int visited[20]; typedef struct ArcCell { int adj; char *info; }ArcCell,AdjMatrix[20][20]; typedef struct { char vexs[20]; AdjMatrix arcs; int vexnum,arcnum; }MGragh; typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef struct{ QueuePtr front; QueuePtr rear; }LinkQueue;

图的邻接矩阵和邻接表相互转换

图的邻接矩阵和邻接表相互转换 图的邻接矩阵存储方法具有如下几个特征:1)无向图的邻接矩阵一定是一个对称矩阵。 2)对于无向图的邻接矩阵的第i 行非零元素的个数正好是第i 个顶点的度()i v TD 。3)对于有向图,邻接矩阵的第i 行非零元素的个数正好是第i 个顶点的出度()i v OD (或入度 ()i v ID ) 。4)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是否有边相连;但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所发费得时间代价大。 邻接表是图的一种顺序存储与链式存储相结合的存储方法。若无向图中有n 个顶点、e 条边,则它的邻接表需n 个头结点和2e 个表结点。显然,在边稀疏的情况下,用邻接表表示图比邻接矩阵存储空间。在无向图的邻接表中,顶点i v 的度恰好是第i 个链表中的结点数,而在有向图中,第i 个链表中结点个数是顶点i v 的出度。 在建立邻接表或邻逆接表时,若输入的顶点信息即为顶点的编号,则建立临接表的时间复杂度是)(e n O +;否则,需要通过查找才能得到顶点在图中位置,则时间复杂度为)*(e n O 。在邻接表上容易找到任意一顶点的第一个邻接点和下一个邻接点,但要判断任意两个顶点之间是否有边或弧,则需要搜索第i 个或第j 个链表,因此,不及邻接矩阵方便。 邻接矩阵和邻接表相互转换程序代码如下: #include #define MAX 20 //图的邻接表存储表示 typedef struct ArcNode{ int adjvex; //弧的邻接定点 char info; //邻接点值 struct ArcNode *nextarc; //指向下一条弧的指针 }ArcNode; typedef struct Vnode{ //节点信息 char data; ArcNode *link; }Vnode,AdjList[MAX]; typedef struct{ AdjList vertices; int vexnum; //节点数 int arcnum; //边数

实验四:图的深度优先与广度优先遍历

实验报告

再从这些顶点出发,访问它们还未访问过的邻接点,…,如此做下去,直到图中所有顶点都被访问过为止。 2、 (1)将没有前驱(入度为零)的顶点进栈。 (2)从栈中退出栈顶元素输出,并把该顶点引出的所有弧删去,即把它的各个邻接点的入度减1,同时将当前已输出的顶点个数加1. (3)将新的入度为零的顶点再进栈。 (4)重复(2)、(2)两步,直到栈为空为止。此时或者已经输出前部顶点,或者剩下的顶点中没有入度为零的顶点。 3、 设置一个n*n的矩阵A(k),其中除对角线元素为0外,其他元素A(k)[i][j]表示顶点i到顶点j的路径长度,k表示运算步骤。开始时k = -1,A(-1)[i][j] = arcs[i][j],即A为图的邻接矩阵。 以后逐步尝试在原路径中加入其他顶点作为中间点,如果增加中间点顶点后,得到的路径比原来的路径短,则以此新路径代替原来路径,修改矩阵元素。具体做法为:第0步让所有路径上加入中间点0,去A[i][j]与A[i][0] + A[o][j]中较小的值作A[i][j]的新值,完成后得到A(0)如此进行下去,当第n-1步完成后,得到A(n-1),A(n-1)即为所求的结果,A(n-1)[i][j]表示从i 到j路径上的中间顶点的序号小于或等于n-1的最短路径的长度,即A(n-1)[i][j]表示从i到j 的最短路径的长度。 算法的实现和测试结果:包括算法运行时的输入、输出,实验中出现的问题及解决办法等 1、

2、

3、

算法时间复杂度分析 1、 深度优先遍历:O(n*n). 广度优先遍历:O(n*n). 2、 O(n+e). 3、 O(n*n*n). 四、收获与体会 不想说什么,这章的程序太难了,每次一想起来数据结构还没做就烦,前两个题基本上一天能做一道题,第三题也就是骗骗OJ,实际上还有个小BUG,等有空再写个真正符合题意的程序吧。 五、源代码清单

深度优先遍历(邻接矩阵)

上机实验报告 学院:计算机与信息技术学院 专业:计算机科学与技术(师范)课程名称:数据结构 实验题目:深度优先遍历(邻接矩阵)班级序号:师范1班 学号:201421012731 学生姓名:邓雪 指导教师:杨红颖 完成时间:2015年12月25号

一、实验目的: 1﹒掌握图的基本概念和邻接矩阵存储结构。 2﹒掌握图的邻接矩阵存储结构的算法实现。 3﹒掌握图在邻接矩阵存储结构上遍历算法的实现。 二、实验环境: Windows 8.1 Microsoft Visual c++ 6.0 二、实验内容及要求: 编写图的深度优先遍历邻接矩阵算法。建立图的存储结构,能够输入图的顶点和边的信息,并存储到相应存储结构中,而后输出图的邻接矩阵。 四、概要设计: 深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广。假设初始状态是图中所有的顶点未曾被访问,则深度优先遍历可从图的某个顶点V出发,访问此顶点,然后依次从V的未被访问的邻接点出发深度优先遍历图,直至图中所有和V有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中的一个未被访问的顶点,重复上述过程,直至图中所有顶点都被访问到为止。 以图中无向图G4为例,深度优先遍历图的过程如图所示。假设从顶点V1出发进行搜索,在访问了顶点V1后,选择邻接点V2。因为V2未曾访问,则从V2出发进行搜索。依次类推,接着从V4,V8,V5出发进行搜索。在访问了V5之后,由于V5的邻接点已都被访问,则搜索回到V8。由于同样的理由,搜索继续回到V4,V2直至V1,此时由于V1的另一个邻接点为被访问,则搜索又从V1到V3,再继续进行下去。由此得到顶点的访问序列为: V1 V2 V4 V8 V5 V3 V6 V7 五、代码 #include #include #define n 8 #define e 9 typedef char vextype; typedef float adjtype; int visited[n]; //定义结构体

数据结构与算法-图的邻接矩阵

实验报告实验日期:数据结构与算法课程: 图的邻接矩阵实验名称: 一、实验目的掌握图的邻接矩阵 二、实验内容必做部分 、给出图的邻接矩阵存储结构的类型定义。1 -1。v,返回其在vexs数组中的下标,否则返回2、实现LocateVex(G,v)操作函数:若找到顶点。、实现算法7.2(构造无向网)3&G) Status CreateUDN(MGraph 设计并实现无向网的输出算法,要求能显示顶点以及顶点之间的邻接关系(方式自定)4、 并进行输出。要求给出至少两组测试数据。在主函数中调用CreateUDN创建一个无向网,5、 选做部分 类型)编写下述操作函数:基于图的邻接矩阵存储结构(即MGraph若找不到这样返回该邻接点在顶点数组中的下标;1个邻接点,1、求下标为v的顶点的第-1。的邻接点,返回int FirstAdjVex(MGraph G,int v) 的顶点的下一个邻接点,返回该邻接点的下标;若w求下标为v的顶点相对于下标为2、找不到这样的邻接点,返回-1。 int NextAdjVex(MGraph G,int v,int w) 在主函数调用上述函数,给出测试结果。 三、实验步骤 必做部分 给出图的邻接矩阵存储结构的类型定义。、 1.

2、实现LocateVex(G,v)操作函数:若找到顶点v,返回其在vexs数组中的下标,否则返回-1。 3、实现算法7.2(构造无向网)。 &G) CreateUDN(MGraph Status

设计并实现无向网的输出算法,要求能显示顶点以及顶点之间的邻接关系(方式自定)、

4. 要求给出至少两组测试数据。并进行输出。、在主函数中调用CreateUDN创建一个无向网,5

图地深度广度遍历(算法与大数据结构课程设计)

图的操作 一、问题描述 图是一种较线性表和树更为复杂的数据结构。在图形结构中,节点间的关系可以是任意的,图中任意两个数据元素之间都可以相关。由此,图的应用极为广泛。现在邻接矩阵和邻接表的存储结构下,完成图的深度、广度遍历。 二、基本要求 1、选择合适的存储结构完成图的建立; 2、建立图的邻接矩阵,能按矩阵方式输出图,并在此基础上,完成图的深度和广度遍历,输出遍历序列; 3、建立图的邻接表,并在此基础上,完成图的深度和广度遍历,输出遍历序列; 三、测试数据 四、算法思想 1、邻接矩阵 顶点向量的存储。用两个数组分别存储数据(定点)的信息和数据元素之间的关系(边或弧)的信息。 2、邻接表 邻接表是图的一种链式存储结构。在邻接表中,对图中每个定点建立一个单链表,第i 个单链表中的节点表示依附于定点vi的边。每个节点由3个域组成,其中邻接点域(adjvex)指示与定点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。每个链表上附设一个头节点。在表头节点中,

除了设有链域(firstarc)指向链表中第一个节点之外,还设有存储定点vi的名或其他有关信息的数据域(data)。 3、图的深度遍历 深度优先搜索遍历类似于树的先根遍历,是树的先跟遍历的推广。假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,甚至图中所有和v相通的顶点都被访问到;若此时图有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 4、图的广度遍历 广度优先遍历类似于树的按层次遍历过程。假设从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先与“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图有顶点未被访问,则另选图中一个曾被 访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 五、模块划分 一、基于邻接矩阵的深广度遍历 1.Status InitQueue(LinkQueue *Q) 根据已知Q初始化队列 2.Status QueueEmpty (LinkQueue Q) 判断队列是否为空 3.Status EnQueue(LinkQueue *Q, QElemType e) 将e压入队尾 4.Status DeQueue(LinkQueue *Q, QElemType *e) 取队头元素e 5.int LocateVex(MGraph G,VertexType v) 定位定点v 6.void CreateGraph(MGraph *G) 建立无向图的邻接矩阵 7.void PrintGraph(MGraph G) 输出邻接矩阵的无向图 8.int FirstAdjVex(MGraph G,int v) 第一个邻接点的定位 9.int NextAdjVex(MGraph G,int v,int w) 查找下一个邻接点

图的遍历实验报告

实验四:图的遍历 题目:图及其应用——图的遍历 班级:姓名:学号:完成日期: 一.需求分析 1.问题描述:很多涉及图上操作的算法都是以图的遍历操作为基础的。试写一个程序,演示在连通的无向图上访问全部结点的操作。 2.基本要求:以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列和相应生成树的边集。 3.测试数据:教科书图7.33。暂时忽略里程,起点为北京。 4.实现提示:设图的结点不超过30个,每个结点用一个编号表示(如果一个图有n个结点,则它们的编号分别为1,2,…,n)。通过输入图的全部边输入一个图,每个边为一个数对,可以对边的输入顺序作出某种限制,注意,生成树的边是有向边,端点顺序不能颠倒。 5.选作内容: (1).借助于栈类型(自己定义和实现),用非递归算法实现深度优先遍历。 (2).以邻接表为存储结构,建立深度优先生成树和广度优先生成树,再按凹入表或树形打印生成树。 二.概要设计 1.为实现上述功能,需要有一个图的抽象数据类型。该抽象数据类型的定义为: ADT Graph { 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。 数据关系R: R={VR} VR={ | v,w v且P(v,w),表示从v到w得弧,谓词P(v,w)定义了弧的意义或信息} } ADT Graph 2.此抽象数据类型中的一些常量如下: #define TRUE 1 #define FALSE 0 #define OK 1 #define max_n 20 //最大顶点数 typedef char VertexType[20]; typedef enum{DG, DN, AG, AN} GraphKind; enum BOOL{False,True}; 3.树的结构体类型如下所示:

用邻接矩阵表示法创建有向图(数据结构)

#include #include #include #define MAX_VERTEX_NUM 20 //定义最多顶点个数 #define INFINITY32768 //定义无穷大 //描述图的类型,用枚举型类型来说明 typedef enum{DG,DN,UDG,UDN}GraphKind; //定义顶点数据类型 typedef char V ertexData; //定义邻接矩阵中元素值(即边信息)的数据类型 typedef int ArcNode; //定义图的邻接矩阵类型:一个顶点信息的一维数组,一个邻接矩阵、当前图中包含的顶点数、边数以及图类型(有向图、有向网、无向图、无向网) typedef struct { V ertexData vertex[MAX_VERTEX_NUM]; ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; int vertexnum,arcnum; GraphKind kind; } AdjMatrix;//图的邻接矩阵表示类型 int LocateV ertex(AdjMatrix *G,V ertexData v) //求顶点位置函数 { int j=-1,k; for(k=0;kvertexnum;k++) { if(G->vertex[k]==v) { return k; } } return j; } int CreateDN(AdjMatrix *G) //创建一个又向网 { int i,j,k,weight; V ertexData v1,v2; printf("输入图的顶点数和弧数,以逗号分隔\n"); //输入图的顶点数和弧数 scanf("%d,%d",&G->vertexnum,&G->arcnum); for(i=0;ivertexnum;i++) //初始化邻接矩阵(主对角线元素全为零,其余元素为无穷大) {

邻接矩阵表示图深度广度优先遍历

*问题描述: 建立图的存储结构(图的类型可以是有向图、无向图、有向网、无向网,学生可以任选两种类型),能够输入图的顶点和边的信息,并存储到相应存储结构中,而后输出图的邻接矩阵。 1、邻接矩阵表示法: 设G=(V,E)是一个图,其中V={V1,V2,V3…,Vn}。G的邻接矩阵是一个他有下述性质的n阶方阵: 1,若(Vi,Vj)∈E 或∈E; A[i,j]={ 0,反之 图5-2中有向图G1和无向图G2的邻接矩阵分别为M1和M2: M1=┌0 1 0 1 ┐ │ 1 0 1 0 │ │ 1 0 0 1 │ └0 0 0 0 ┘ M2=┌0 1 1 1 ┐ │ 1 0 1 0 │ │ 1 1 0 1 │ └ 1 0 1 0 ┘ 注意无向图的邻接是一个对称矩阵,例如M2。 用邻接矩阵表示法来表示一个具有n个顶点的图时,除了用邻接矩阵中的n*n个元素存储顶点间相邻关系外,往往还需要另设一个向量存储n个顶点的信息。因此其类型定义如下: VertexType vertex[MAX_VERTEX_NUM]; // 顶点向量 AdjMatrix arcs; // 邻接矩阵 int vexnum, arcnum; // 图的当前顶点数和弧(边)数 GraphKind kind; // 图的种类标志

若图中每个顶点只含一个编号i(1≤i≤vnum),则只需一个二维数组表示图的邻接矩阵。此时存储结构可简单说明如下: type adjmatrix=array[1..vnum,1..vnum]of adj; 利用邻接矩阵很容易判定任意两个顶点之间是否有边(或弧)相联,并容易求得各个顶点的度。 对于无向图,顶点Vi的度是邻接矩阵中第i行元素之和,即 n n D(Vi)=∑A[i,j](或∑A[i,j]) j=1 i=1 对于有向图,顶点Vi的出度OD(Vi)为邻接矩阵第i行元素之和,顶点Vi 的入度ID(Vi)为第i列元素之和。即 n n OD(Vi)=∑A[i,j],OD(Vi)=∑A[j,i]) j=1j=1 用邻接矩阵也可以表示带权图,只要令 Wij, 若或(Vi,Vj) A[i,j]={ ∞, 否则。 其中Wij为或(Vi,Vj)上的权值。相应地,网的邻接矩阵表示的类型定义应作如下的修改:adj:weightype ; {weightype为权类型} 图5-6列出一个网和它的邻接矩阵。 ┌∞31∞∞┐ │∞∞51∞│ │∞∞∞∞∞│ │∞∞6∞∞│ └∞322∞┘ (a)网(b)邻接矩阵 图5-6 网及其邻接矩阵 对无向图或无向网络,由于其邻接矩阵是对称的,故可采用压缩存贮的方法,

实现图的邻接矩阵和邻接表存储

实现图的邻接矩阵和邻接表存储 1.需求分析 对于下图所示的有向图G,编写一个程序完成如下功能: 1.建立G的邻接矩阵并输出之 2.由G的邻接矩阵产生邻接表并输出之 3.再由2的邻接表产生对应的邻接矩阵并输出之 2.系统设计 1.图的抽象数据类型定义: ADT Graph{ 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集 数据关系R: R={VR} VR={|v,w∈V且P(v,w),表示从v到w的弧, 谓词P(v,w)定义了弧的意义或信息} 基本操作P: CreatGraph(&G,V,VR) 初始条件:V是图的顶点集,VR是图中弧的集合 操作结果:按V和VR的定义构造图G DestroyGraph(&G) 初始条件:图G存在 操作结果:销毁图G InsertVex(&G,v) 初始条件:图G存在,v和图中顶点有相同特征 操作结果:在图G中增添新顶点v …… InsertArc(&G,v,w) 初始条件:图G存在,v和w是G中两个顶点 操作结果:在G中增添弧,若G是无向的则还增添对称弧 …… DFSTraverse(G,Visit()) 初始条件:图G存在,Visit是顶点的应用函数 操作结果:对图进行深度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。

一旦Visit()失败,则操作失败 BFSTraverse(G,Visit()) 初始条件:图G存在,Visit是顶点的应用函数 操作结果:对图进行广度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 }ADT Graph 2.主程序的流程: 调用CreateMG函数创建邻接矩阵M; 调用PrintMatrix函数输出邻接矩阵M 调用CreateMGtoDN函数,由邻接矩阵M创建邻接表G 调用PrintDN函数输出邻接表G 调用CreateDNtoMG函数,由邻接表M创建邻接矩阵N 调用PrintMatrix函数输出邻接矩阵N 3.函数关系调用图: 3.调试分析 (1)在MGraph的定义中有枚举类型 typedef enum{DG,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网} 赋值语句G.kind(int)=M.kind(GraphKind);是正确的,而反过来M.kind=G.kind则是错误的,要加上那个强制转换M.kind=GraphKind(G.kind);枚举类型enum{DG,DN,UDG,UDN} 会自动赋值DG=0;DN=1,UDG=2,UDN=3;可以自动从GraphKind类型转换到int型,但不会自动从int型转换到GraphKind类型

C语言版图的深度和广度优先遍历源代码

邻接表表示的图: #include"" #include"" #define MaxVertexNum 50 ertex=a; irstedge=NULL; irstedge; G->adjlist[i].firstedge=s; irstedge; G->adjlist[j].firstedge=s; ertex); irstedge; ertex); irstedge; ertex); //访问Vj visited[p->adjvex]=TRUE; r=r+1; cq[r]=p->adjvex; //访问过的Vj入队 } p=p->next; //找Vi的下一个邻接点 } }//endwhile } //==========主函数=========== void main() { //int i; ALGraph *G; G=(ALGraph *)malloc(sizeof(ALGraph)); CreatALGraph(G); printf("Print Graph DFS: "); DFS(G); printf("\n");

printf("Print Graph BFS: "); BFS(G,3); printf("\n"); } 邻接矩阵表示的图: #include"" #include"" #define MaxVertexNum 100 //定义最大顶点数 typedef struct{ char vexs[MaxVertexNum]; //顶点表 int edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵,可看作边表int n,e; //图中的顶点数n和边数e }MGraph; //用邻接矩阵表示的图的类型 //=========建立邻接矩阵======= void CreatMGraph(MGraph *G)

图的实现及遍历

数据结构【第六次】实验报告学院: 班级: 学号: 姓名:

实验六 (一)实验名称:图的实现及遍历 (二)实验目的: 1) 掌握有向图和无向图的概念; 2) 掌握邻接矩阵和邻接链表建立图的存储结构; 3) 掌握DFS及BFS对图的遍历操作和过程; 4) 了解图结构在人工智能、工程等领域的广泛应用。(三)实验要求: 1) 采用邻接矩阵作为图的存储结构,完成有向图和无向图的DFS和BFS操作; 2) 采用邻接链表作为图的存储结构,完成有向图和无向图的DFS和BFS操作。 (四)源代码: 1)邻接矩阵作为存储结构的程序 #include"stdio.h" #include"stdlib.h" #define MaxVertexNum 100 typedef struct{ char vexs[MaxVertexNum]; int edges[MaxVertexNum][MaxVertexNum]; int n,e; }MGraph;

void CreatMGraph(MGraph *G) { int i,j,k; char a; printf("Input VertexNum(n) and EdgesNum(e): "); scanf("%d,%d",&G->n,&G->e); scanf("%c",&a); printf("Input Vertex string:"); for(i=0;in;i++) { scanf("%c",&a); G->vexs[i]=a; } for(i=0;in;i++) for(j=0;jn;j++) G->edges[i][j]=0; printf("Input edges,Creat Adjacency Matrix\n"); for(k=0;ke;k++) { scanf("%d%d",&i,&j); G->edges[i][j]=1; G->edges[j][i]=1; } } typedef enum{FALSE,TRUE} Boolean; Boolean visited[MaxVertexNum]; //========DFS: void DFSM(MGraph *G,int i) { int j; printf("%c",G->vexs[i]); visited[i]=TRUE; for(j=0;jn;j++) if(G->edges[i][j]==1 && ! visited[j]) DFSM(G,j); } void DFS(MGraph *G) { int i; for(i=0;in;i++) visited[i]=FALSE; for(i=0;in;i++) if(!visited[i]) DFSM(G,i); } void BFS(MGraph *G,int k)

图采用邻接矩阵存储结构

图采用邻接矩阵存储结构 #define TRUE 1 #define FALSE 0 #define MAXV 20 typedef int V ertexType; //用顶点编号表示顶点 typedef struct { // 图的定义 int edges[MAXV][MAXV] ; // 边数组 int n, e; //顶点数,弧数 V ertexType vexs[MAXV]; // 顶点信息 } MGraph; 1、创建具有n个顶点e条边的无向图 void CreateUDG(MGraph &G,int n,int e) { int i,j,u,v; G.n=n;G.e=e; /* printf("请输入%d个顶点的编号:\n",n); for(i=0;i

void CreateDG(MGraph &G,int n,int e) { int i,j,u,v; G.n=n;G.e=e; /* printf("请输入%d个顶点的编号:\n",n); for(i=0;i

图的深度优先遍历和广度优先遍历

华北水利水电学院数据结构实验报告 20 10 ~20 11 学年第一学期2008级计算机专业 班级:107学号:200810702姓名:王文波 实验四图的应用 一、实验目的: 1.掌握图的存储结构及其构造方法 2.掌握图的两种遍历算法及其执行过程 二、实验内容: 以邻接矩阵或邻接表为存储结构,以用户指定的顶点为起始点,实现无向连通图的深度优先及广度优先搜索遍历,并输出遍历的结点序列。 提示:首先,根据用户输入的顶点总数和边数,构造无向图,然后以用户输入的顶点为起始点,进行深度优先和广度优先遍历,并输出遍历的结果。 三、实验要求: 1.各班学号为单号的同学采用邻接矩阵实现,学号为双号的同学采用邻接表实现。 2.C/ C++完成算法设计和程序设计并上机调试通过。 3.撰写实验报告,提供实验结果和数据。 4.写出算法设计小结和心得。 四、程序源代码: #include #define MaxVerNum 50 struct edgenode { int endver; int inform; edgenode* edgenext; }; struct vexnode { char vertex; edgenode* edgelink; }; struct Graph { vexnode adjlists[MaxVerNum]; int vexnum; int arcnum; }; //队列的定义及相关函数的实现 struct QueueNode

{ int nData; QueueNode* next; }; struct QueueList { QueueNode* front; QueueNode* rear; }; void EnQueue(QueueList* Q,int e) { QueueNode *q=new QueueNode; q->nData=e; q->next=NULL; if(Q==NULL) return; if(Q->rear==NULL) Q->front=Q->rear=q; else { Q->rear->next=q; Q->rear=Q->rear->next; } } void DeQueue(QueueList* Q,int* e) { if (Q==NULL) return; if (Q->front==Q->rear) { *e=Q->front->nData; Q->front=Q->rear=NULL; } else { *e=Q->front->nData; Q->front=Q->front->next; } } //创建图 void CreatAdjList(Graph* G) { int i,j,k; edgenode* p1; edgenode* p2;

采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作

/* 采用邻接矩阵完成无向图的“建立、深度遍历、广度遍历”操作 */ #include "stdio.h" #include "string.h" #define TRUE 1 #define FALSE 0 #define OVERFLOW -2 #define OK 1 #define ERROR 0 typedef int Status; #define INFINITY INT_MAX /*最大值“无穷”*/ #define MAX_VERTEX_NUM 20 /*最大顶点个数*/ typedef int Boolean; typedef char VertexType[20]; typedef int VRType; /**************以下为队列的操作************/ /****队列的类型定义****/ typedef int QElemType; typedef struct QNode {QElemType data; struct QNode *next; } QNode, *QueuePtr; typedef struct { QueuePtr front; QueuePtr rear; } LinkQueue; /****初始化队列****/ Status InitQueue(LinkQueue *Q) { (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if (!(*Q).front) exit(OVERFLOW); (*Q).front->next=NULL; return OK; } /****判断队列是否为空****/ Status QueueEmpty (LinkQueue Q) { if (Q.front==Q.rear) return TRUE; else

图的邻接矩阵的建立与输出

#include #include #include #define MAX_VERTEX_NUM 20 typedef int Arc_Type; typedef char VerTex_Type[5]; typedef enum { DG, DN, UDG, UDN }Graph_Kind; typedef struct ArcCell { Arc_Type adj; //Info_Type *info; }AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { V erTex_Type vexs[MAX_VERTEX_NUM]; AdjMatrix arcs; int vertex_num; int arc_num; Graph_Kind kind; }MGraph; void Init_MGraph( MGraph &G ) { printf("输入图的定点数:"); scanf("%d", &G.vertex_num ); printf("输入图的边数:"); scanf("%d", &G.arc_num ); printf("输入图的类型(有向图:1 无向图:2 ):"); scanf("%d", &G.kind); int i, j; printf("输入节点向量(定点之间用空格隔开):"); for( i=0; i

图的邻接矩阵结构上实现图的广度优先遍历

图的邻接矩阵结构上实现图的广度优先遍历: 广搜的实现相对而言比较难,它需要用到数据结构中另一个抽象:队列 [c-sharp]view plaincopy 1.void bfs(graph *g,int i){ 2.int j,k; 3. printf("%d点被访问/n",i);//i已经被访问 4. visited[i] = 1;//标记i边已经被访问 5. cirqueue *p = (cirqueue*)malloc(sizeof(cirqueue));//申请一个对队列 6. p->front = p->rear = p->count = 0;//表示队列为空 7.//以下三行代码使得i进入队列 8. p->q[p->rear] = i; 9. p->rear = (p->rear++)/maxnum; 10. p->count++; 11. 12.while(p->count!=0){//假如队列不空 13.//以下三行代码是去队列元素 14. j = p->q[p->front]; 15. p->front = (p->rear++)/maxnum; 16. p->count--; 17.//寻找序号为i顶点的邻接点,并做如下处理 18.for(k=0;kvNum;k++){ 19.if(g->e[j][k]!=0&&visited[k]==0){//假如j点与i点相连,并且j点还没 有被访问过 20. printf("%d点被访问/n",k);//i已经被访问 21. visited[k] = 1;//标记i边已经被访问 22. 23.//以下三行代码使得k进入队列 24. p->q[p->rear] = k; 25. p->rear = (p->rear++)/maxnum; 26. p->count++; 27. } 28. } 29. } 30.} 31. 32. 33.void BFS(graph *g){ 34.int i; 35.//首先把所有点都设置成没有访问过 36.for(i=0;ivNum;i++){

相关文档
最新文档