1、实验五 图的存储与遍历1、实验目的掌握图这种复杂的非线性结构的邻接矩阵和邻接表的存储表示,以及在此两种常用存储方式下深度优先遍历(dfs)和广度优先遍历( BFS)操作的实现。2、实验预备知识(1)图的存储结构:邻接矩阵表示法和邻接表表示法。邻接矩阵表示法除了要用一个二维数组存储用于表示顶点间相邻关系的邻接矩阵外,还需用一个一维数组来存储顶点信息,另外还有图的顶点数和边数。邻接表表示法类似于树的孩子链表表示法。(2)图的遍历方法有深度优先遍历(DepthFirst Traersal)和广度优先遍历(BreadthFirst Traversal),简称 DFS 和 BFS。DFS 对图遍历时尽可
2、能先对纵深方向进行搜索;BFS 是类似于树的按层次遍历。3、实验内容题目 1 对以邻接矩阵为存储结构的图进行 DFS 和 BFS 遍历(1) 问题描述:以邻接矩阵为图的存储结构,实现图的 DFS 和 BFS 遍历。(2) 基本要求:建立一个图的邻接矩阵表示,输出顶点的一种 DFS 和 BFS序列。(3) 测试数据:如图 418 所示。(4) 实现提示:图的 DFS 遍历可通过递归调用或用栈来实现。其思想是:只要当前结点未访问过,就访问该结点,沿着其一条分支深入下去,每深入一个未访问过的结点,就访问这个结点,然后从这个结点继续进行 DFS 遍历。在这一过程中,若深入时遇到一个已访问过的结点,则查
3、找是否有与这个结点相邻的下一个未访问过的结点。若有则继续深人,否则将退回到这个结点的前一个结点,再找下一个相邻的本访问过的结点,如此进行下去,直到所有的结点都被访问过。BFS 遍历可利用队列来帮助实现,也可以用栈。实现方法与二叉树的层次遍历类似。题目 2 对以邻接表为存储结构的图进行 DFS 和 BFS 遍历(1) 问题描述:以邻接表为存储结构,实现图的 DFS 和 BFS 遍历。(2) 基本要求:建立一个图的邻接表存储,输出顶点的一种 DFS 和 BFS 序列。(3) 测试数据:如图 4.19 所示:(4) 实现提示:以邻接表为存储结构的图的 DFS 和 BFS 算法的实现思想与以邻接矩阵为
4、存储结构的实现是一样的。只是由于图的存储形式不同。而具体到取第一个邻接点和下一个邻接点的语句表示上有所差别而已。4、实验步骤(1)仔细分析实验内容,给出其算法和流程图;(2)用 C 语言实现该算法;(3)给出测试数据,并分析其结果;(4)在实验报告册上写出实验过程。5、实验报告要求实验报告要求书写整齐,步骤完整,实验报告格式如下:1、实验目的2、实验设备3、实验步骤4、实验内容5、实验结果(结论)程序如下:/*sy41.c*/#define MaxVertexNum 10 /设最大顶点数为 10#include #include typedef char VertexType;typedef
5、int EdgeType;typedef structchar vexs10;int edges1010;int n,e;MGraph;#define FALSE 0#define TRUE 1#define Error printfint visited10;void CreateMGraph(MGraph *G);void DFSTraverseM(MGraph *G);void BFSTraverseM(MGraph *G);void DFSM(MGraph *G,int i);void BFSM(MGraph *G,int i);#define QueueSize 30 /*假定预分配
6、的队列空间最多为 30*/typedef int DataType; /*队列中的元素类型为字符型 */typedef structint front; /*队头指针,队非空时指向队头元素*/int rear; /*队尾指针,队非空时指向队尾元素的下一位置*/int count; /*计数器,记录队中元素总数*/DataType dataQueueSize;CirQueue;void InitQueue(CirQueue *Q) /*初始队列*/Q-front=Q-rear=0;Q-count=0;int QueueEmpty(CirQueue *Q) /*判队空*/return Q-coun
7、t=0;int QueueFull(CirQueue *Q) /*判队满*/return Q-count=QueueSize;void EnQueue(CirQueue *Q,DataType x) /*入队*/if (QueueFull(Q)Error(“Queue overflow“); /*队满上溢*/else Q-count+; /*队列元素个数加 1*/Q-dataQ-rear=x; /*新元素插入队列*/Q-rear=(Q-rear+1)%QueueSize; /*循环队列的尾指针加 1*/DataType DeQueue(CirQueue *Q) /*出队*/DataType t
8、emp;if (QueueEmpty(Q)Error(“Queue underflow“); /*队空下溢*/else temp=Q-dataQ-front;Q-count-; /*队列元素个数减 1*/Q-front=(Q-front+1)%QueueSize; /*循环队列的头指针加 1*/return temp;main()MGraph *G; /*定义一个以邻接矩阵为存储类型的图 G*/char ch1,ch2;printf(“create graph(adjoining matrix ):n“); /*创建图 G 的存储*/CreateMGraph(G);ch1=y;while(ch
9、1=y | ch1=Y)printf(“select:n“);printf(“nA-update graph(adjoining matrix ) “);printf(“nB-Degree First search “);printf(“nC-breadth First search “);printf(“nD-exitn“);scanf(“n%c“,switch (ch2)case A:case a:CreateMGraph(G);printf(“create graph success 。n“);break;case B:case b:DFSTraverseM(G);break;case
10、C:case c:BFSTraverseM(G);break;case D:case d:ch1=n;break;default:ch1=n;void CreateMGraph(MGraph *G)/*建立有向图 G 的邻接矩阵存储*/int i,j,k,w;char ch;printf(“input vertex number and edge number(input format:vn,en):n“);/*输入顶点数和边数,输入格式:顶点数,边数*/scanf(“%d,%d“,printf(“input vertex(input format:serial number):n“);/*输
11、入顶点信息,建立顶点表,输入格式为:顶点号)/*/for (i=0;in;i+)scanf(“%c“,for (i=0;in;i+)for (j=0;jn;j+)G-edgesij=0; /*初始化邻接矩阵*/printf(“input edge(format:i,j):n“);/*输入 e 条边,输入格式为:i,j*/for (k=0;ke;k+)scanf(“%d,%d“, /*输入 e 条边,建立邻接矩阵*/G-edgesij=1;/*CreateMGraph*/void DFSTraverseM(MGraph *G)/*深度优先遍历以邻接矩阵存储的图 G*/int i;printf(“
12、Degree First searchn“);for (i=0;in;i+)visitedi=FALSE; /*标志向量初始化*/for (i=0;in;i+)if (!visitedi) DFSM(G,i);/*Vi 未访问过,以 Vi 为原点开始 DFS 搜索*/*DFSTraverse*/void DFSM(MGraph *G,int i)/*以 Vi 为出发点,对邻接矩阵存储的图 G 进行 DFS 搜索*/int j;printf(“vertex:V%cn“,G-vexsi); /*访问顶点 Vi*/visitedi=TRUE;for (j=0;jn;j+) /*依次搜索 Vi 的邻接
13、点*/if (G-edgesij=1 /*当E,且 Vj 未访问过时,以 Vj 为新的出发点继续按深度优先遍历*/*DFSM*/void BFSTraverseM(MGraph *G)/*广度优先遍历邻接矩阵存储的图 G*/int i;printf(“breadth First searchn“);for (i=0;in;i+)visitedi=FALSE; /*标志向量初始化*/for (i=0;in;i+)if (!visitedi) BFSM(G,i);/*Vi 未访问过,以 Vi 为原点开始 BFS 搜索*/*BFSTraverseM*/void BFSM(MGraph *G,int k)/*以 Vi 为出发点,对邻接矩阵存储的图 G 进行 BFS 搜索*/int i,j;CirQueue Q;InitQueue(printf(“vertex:v%cn“,G-vexsk);visitedk=TRUE;EnQueue( /*原点 Vk 入队列*/while (!QueueEmpty( /*Vi 出队列*/for (j=0;jn;j+) /*依次搜索 Vi 的邻接点 Vj*/if (G-edgesij=1 visitedj=TRUE;EnQueue( /*访问过的 Vj 入队列*/*BFSM*/