大数据结构与算法实验——图的基本操作
数据结构实验———图实验报告
数据结构实验报告目的要求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实验总结这次的图的操作实验;与树的操作类似;但又比树复杂;包含更多的存储结构和遍历方法的操作;而且图的遍历需要沿着弧进行;以便输出弧上的信息..本实验中图的遍历采用邻接表的存储结构;在输入图的信息时;首先要画出图的邻接表信息..图有两种遍历的形式;一种为深度优先搜索;另一种为广度优先搜索..由于能力有限;没能实现图的深度非递归优先搜索;而是实现了图的深度递归优先搜索..本实验基本完成了图的操作;也学到了很多关于图的知识和算法..。
实验六 图的基本操作
南京信息工程大学实验(实习)报告图的基本操作一、实验目的1、熟悉图的存储结构2、掌握图的基本操作二、实验准备1、奔腾2计算机或以上机型2、Microsoft Visual C++ 6.0三、实验内容1、建立一张图2、实现深度优先搜索、广度优先搜索遍历四、实验代码#include<stdio.h>#include<conio.h>#include<stdlib.h>typedef struct ArcNode{int adjVex;struct ArcNode *nextArc;}ArcNode;typedef struct VNode{int data;ArcNode *firstArc;}VNode;//创建一张图void CreatGraphic();//深度优先搜索遍历void DFSTraverse(int searchNode);//广度优先搜索遍历void BFSTraverse(int searchNode);//访问标志置零void ClearVisited();void Bound(char ch, int num);//邻接表VNode *adjList;//访问标记数组short *visited;//循环队列, 用于广度优先搜索遍历函数中int *queue;//图的结点数int graphicNode;//用于判断是否创建了图bool creatGraphic;int main(void){char choice;int searchNode;creatGraphic = false;while (true){if (!creatGraphic){system("CLS");printf(" 图的操作\n");Bound('-', 15);printf(" 1. 创建一张图\n");printf(" 0. 退出程序\n");Bound('-', 15);printf(" 请选择: ");fflush(stdin);choice = getchar();switch (choice){case '1':CreatGraphic();break;case '0':printf("\n");system("PAUSE");return 0;default:printf("\n 输入错误, 按任意键后重新输入!");getch();break;}}else{system("CLS");printf(" 图的操作\n");Bound('-', 20);printf(" 1. 深度优先搜索遍历\n");printf(" 2. 广度优先搜索遍历\n");printf(" 0. 退出程序\n");Bound('-', 20);printf(" 请选择: ");fflush(stdin);choice = getchar();switch (choice){case '1':ClearVisited();Lable1:printf("\n 请输入起始搜索的结点序号: ");fflush(stdin);scanf("%d", &searchNode);if (searchNode>=1 && searchNode <=graphicNode){printf(" 深度优先搜索遍历为: ");DFSTraverse(searchNode);}else{printf(" 序号输入错误, 按任意键后重新输入! \n");getch();goto Lable1;}printf("\n\n");system("PAUSE");break;case '2':ClearVisited();Lable2:printf("\n 请输入起始搜索的结点序号: ");scanf("%d", &searchNode);if (searchNode>=1 && searchNode <=graphicNode){printf(" 广度优先搜索遍历为: ");BFSTraverse(searchNode);}else{printf(" 序号输入错误, 按任意键后重新输入! \n");getch();goto Lable2;}printf("\n\n");system("PAUSE");break;case '0':printf("\n");system("PAUSE");return 0;default:printf("\n 输入错误, 按任意键后重新输入!");getch();break;}}}}void CreatGraphic(){int number;int localNode, linkNode;ArcNode *tempNode;Flag:printf("\n 请输入图的顶点数: ");fflush(stdin);scanf("%d", &graphicNode);if (graphicNode <= 0){printf(" 输入错误, 按任意键后重新输入!\n");getch();goto Flag;}if ((adjList=(VNode *)malloc(sizeof(VNode)*graphicNode)) == NULL){printf(" 内存空间不足, 无法创建图!\n");system("PAUSE");exit(0);}if ((visited=(short *)malloc(sizeof(short)*graphicNode)) == NULL){printf(" 内存空间不足, 无法创建访问记录表!\n");system("PAUSE");exit(0);}if ((queue=(int *)malloc(sizeof(int)*graphicNode)) == NULL){printf(" 内存空间不足, 无法创建队列!\n");system("PAUSE");exit(0);}for (number=0; number<graphicNode; ++number){adjList[number].data = number + 1;adjList[number].firstArc = NULL;}printf("\n 请输入所要创建的图中所有相关联的顶点, 格式( 图中一顶点与此顶点相关联的顶点)\n");do{printf(" 请输入( 注意: 输入0 0 结束输入): ");fflush(stdin);scanf("%d %d", &localNode, &linkNode);if (localNode>=1 && localNode<=graphicNode && linkNode>=1 && linkNode<=graphicNode){if ((tempNode = (ArcNode *)malloc(sizeof(ArcNode))) == NULL){printf(" 内存不足, 无法创建图!\n");exit(0);}tempNode->adjVex = linkNode;tempNode->nextArc = adjList[localNode - 1].firstArc;adjList[localNode - 1].firstArc = tempNode;}else{creatGraphic = true;return;}}while(true);}void DFSTraverse(int searchNode){ArcNode *tempNode;visited[searchNode - 1] = 1;printf("%d ", searchNode);tempNode = adjList[searchNode - 1].firstArc;while (tempNode != NULL){if (visited[tempNode->adjVex - 1] == 0){DFSTraverse(tempNode->adjVex);}tempNode = tempNode->nextArc;}}void BFSTraverse(int searchNode){ArcNode *tempNode;int nodeNum;int front = 0, rear = 0;printf("%d ", searchNode);visited[searchNode - 1] = 1;rear = (rear + 1) % graphicNode;queue[rear] = searchNode;while (front != rear){front = (front + 1) % graphicNode;nodeNum = queue[front];tempNode = adjList[nodeNum - 1].firstArc;while (tempNode != NULL){if (visited[tempNode->adjVex - 1] == 0){visited[tempNode->adjVex - 1] = 1;printf("%d ", tempNode->adjVex);rear = (rear + 1) % graphicNode;queue[rear] = tempNode->adjVex;}tempNode = tempNode->nextArc;}}}void ClearVisited(){int cnt;for (cnt=0; cnt<graphicNode; ++cnt){visited[cnt] = 0;}}void Bound(char ch, int num){while (num--){putchar(ch);}putchar('\n');}(本次实验中所用图示意图)(图1:按格式创建图)1876 5 4 3 2(图2:深度优先搜索遍历)(图3:广度优先搜索遍历)五、实验总结…。
图的基本操作 实验报告
图的基本操作实验报告图的基本操作实验报告引言:图是一种常见的数据结构,广泛应用于计算机科学和其他领域。
本实验报告旨在介绍图的基本操作,包括创建图、添加节点和边、遍历图等,并通过实验验证这些操作的正确性和效率。
实验目的:1. 了解图的基本概念和术语;2. 掌握图的创建和修改操作;3. 熟悉图的遍历算法;4. 分析图的操作的时间复杂度。
实验过程:1. 创建图首先,我们需要创建一个图对象。
图可以用邻接矩阵或邻接表来表示。
在本实验中,我们选择使用邻接表来表示图。
通过遍历输入的节点和边信息,我们可以创建一个包含所有节点和边的图。
2. 添加节点和边在创建图对象后,我们可以通过添加节点和边来构建图的结构。
通过输入节点的标识符和边的起始和结束节点,我们可以在图中添加新的节点和边。
添加节点和边的操作可以通过修改邻接表来实现,将节点和边的信息存储在对应的链表中。
3. 遍历图遍历图是图操作中常用的操作之一。
通过遍历图,我们可以访问图中的所有节点和边。
在本实验中,我们选择使用深度优先搜索(DFS)算法来遍历图。
DFS算法通过递归的方式遍历图中的节点,先访问当前节点,然后再递归地访问与当前节点相邻的节点。
4. 分析时间复杂度在实验过程中,我们记录了图的操作所花费的时间,并分析了它们的时间复杂度。
通过对比不同规模的图的操作时间,我们可以评估图操作的效率和可扩展性。
实验结果:通过实验,我们成功创建了一个图对象,并添加了多个节点和边。
我们还通过DFS算法遍历了图,并记录了遍历的顺序。
实验结果表明,我们的图操作实现正确,并且在不同规模的图上都能够高效地工作。
讨论与结论:本实验报告介绍了图的基本操作,并通过实验验证了这些操作的正确性和效率。
通过实验,我们了解到图是一种重要的数据结构,可以用于解决许多实际问题。
同时,我们还深入分析了图操作的时间复杂度,为后续的图算法设计和优化提供了参考。
总结:通过本次实验,我们对图的基本操作有了更深入的了解。
数据结构试验报告-图的基本操作
中原工学院《数据结构》实验报告学院:计算机学院专业:计算机科学与技术班级:计科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;}。
实验九:图的基本操作
cout<<q.table[i]<<" "; i=(i+1) % q.size; } cout<<endl; return out; } struct EdgeNode1 // 带权值的边 { int init; // 边的起点 int end; // 边的终点 int weight; // 边的权值 }; class Graph1 //邻接矩阵图类 { private: int visited[MaxSize]; // 访问标记数组 void unvisited(); // 设置未访问标记 void depthfs(int k); // 从结点 k 开始的深度优先遍历 void breadthfs(int k); // 从结点 k 开始的广度优先遍历 public: char vertex[MaxSize]; // 图的结点集,MaxSize 为最大结点数 int mat[MaxSize][MaxSize]; //图的邻接矩阵 int vertCount; // 图的结点数 int edgeCount; // 图的边数 Graph1(); //初始化图的结点集和邻接矩阵 ~Graph1(){} // 析构函数为空 void createGraph(int n,char vert[],int m,EdgeNode1 edge[]); friend ostream& operator<<(ostream& out,Graph1 &g1); void depthFirstSearch(); //图的深度优先遍历 void breadthFirstSearch(); //图的广度优先遍历 void insertVertex(char vert); // 插入结点 void insertEdge(EdgeNode1 e); // 插入边 void insertEdge(int init,int end,int w); void removeVertex(char vert); // 删除结点 void removeEdge(EdgeNode1 e); // 删除边 void removeEdge(int init,int end); //删除边 }; Graph1::Graph1() // 初始化图的结点集和邻接矩阵 { int i,j; for(i=0;i<MaxSize;i++) // 初始化图的结点集 vertex[i]=' '; for(i=0;i<MaxSize;i++) // 初始化图的邻接矩阵 for(j=0;j<MaxSize;j++) if(i==j) mat[i][j]=0; //数据元素权值为 0 else mat[i][j]=MaxWeight; //权值为无穷大 vertCount=0; // 当前结点数为 0 edgeCount=0; // 当前边数为 0 } void Graph1::createGraph(int n,char vert[],int m,EdgeNode1 edge[]) { // 以结点集和边集构造一个图 vertCount=n; // 图的结点个数 int i,j,k; for(i=0;i<n;i++) // 初始结点加入结点集 vertex[i]=vert[i]; edgeCount=m; // 图的边数
图的基本操作
实验七:图的基本操作(1)键盘输入数据,建立一个有向图的邻接表。
(2)输出该邻接表。
(3)在有向图的邻接表的基础上计算各顶点的度,并输出。
(4)以有向图的邻接表为基础实现输出它的拓扑排序序列。
(5)采用邻接表存储实现无向图的深度优先遍历。
(6)采用邻接表存储实现无向图的广度优先遍历。
(7)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
(8)采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
(9)在主函数中设计一个简单的菜单,分别调试上述算法。
综合训练:为计算机专业设计教学计划:4个学年,每学年2个学期,开设50门课程,每学期所开课程门数尽量均衡,课程的安排必须满足先修关系。
#include<stdio.h>#include<stdlib.h>#include<stack>#include<queue>using namespace std;#define max_vertex_num 20#define INFINITY 1000000000typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode;typedef char vertexType;typedef struct VNode{vertexType data;ArcNode *firstarc;int count;}VNode,AdjList[max_vertex_num];typedef struct{AdjList vertices;int vexnum,arcnum;int degree;}ALGraph;//邻接表typedef struct ArcCell{int adj;}ArcCell,AdjMatrix[max_vertex_num][max_vertex_num];typedef struct{char vex[max_vertex_num];AdjMatrix arc;int vexnum,arcnum;}MGraph;//邻接矩阵ALGraph ALG,InsertALG,UALG;MGraph G;int visit[max_vertex_num];struct edge{char adjvex;int lowcost;}closedge[max_vertex_num];int P[max_vertex_num];int D[max_vertex_num];int finial[max_vertex_num];void print(){printf("(1)键盘输入数据,建立一个有向图的邻接表\n");printf("(2)输出该邻接表\n");printf("(3)在有向图的邻接表的基础上计算各顶点的度,并输出\n");printf("(4)以有向图的邻接表为基础实现输出它的拓扑排序序列\n");printf("(5)采用邻接表存储实现无向图的深度优先遍历\n");printf("(6)采用邻接表存储实现无向图的广度优先遍历\n");printf("(7)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法\n");printf("(8)采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径\n");printf("(0)退出程序\n");}int locatevex(MGraph G,char v){//查找顶点在图中的位置int i=0;while(i<G.vexnum){if(v==G.vex[i])break;elsei++;}return i;}void CreateALGraph(ALGraph &ALG,ALGraph &InsertALG){//创建有向邻接表及其逆邻接表并且其顶点用大写字母表示int i,j,k;ArcNode *s,*r;printf("请输入有向邻接表的顶点数和边数:\n");scanf("%d%d",&ALG.vexnum,&ALG.arcnum);for(i=0;i<ALG.vexnum;i++){ALG.vertices[i].data='A'+i;ALG.vertices[i].firstarc=NULL;InsertALG.vertices[i].data='A'+i;InsertALG.vertices[i].firstarc=NULL;}for(k=0;k<ALG.arcnum;k++){scanf("%d%d",&i,&j);s=(ArcNode*)malloc(sizeof(ArcNode));r=(ArcNode*)malloc(sizeof(ArcNode));s->adjvex=j;s->nextarc=ALG.vertices[i].firstarc;ALG.vertices[i].firstarc=s;r->adjvex=i;r->nextarc=InsertALG.vertices[j].firstarc;InsertALG.vertices[j].firstarc=r;}}void CeratUALGraph(ALGraph &UALG){//用头插法建立无向邻接表int i,j,k;ArcNode *p;printf("请输入无向邻接表的的顶点数和边数:\n");scanf("%d%d",&UALG.vexnum,&UALG.arcnum);for(i=0;i<UALG.vexnum;i++){UALG.vertices[i].data='A'+i;UALG.vertices[i].firstarc=NULL;}for(k=0;k<UALG.arcnum;k++){scanf("%d%d",&i,&j);p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=j;p->nextarc=UALG.vertices[i].firstarc;UALG.vertices[i].firstarc=p;p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=i;p->nextarc=UALG.vertices[j].firstarc;UALG.vertices[j].firstarc=p;}}void CreateUDN(MGraph &G,int a){//若a==1的时候创建无向邻接矩阵,否则创建有向邻接矩阵int i,j,k,w;char v1,v2;printf("请输入邻接矩阵的顶点数和边数:\n");scanf("%d%d",&G.vexnum,&G.arcnum);getchar();for(i=0;i<G.vexnum;i++)scanf("%c",&G.vex[i]);for(i=0;i<G.vexnum;i++)for(j=0;j<G.vexnum;j++)G.arc[i][j].adj=INFINITY;for(k=0;k<G.arcnum;k++){getchar();scanf("%c %c %d",&v1,&v2,&w);i=locatevex(G,v1);j=locatevex(G,v2);G.arc[i][j].adj=w;if(a==1)G.arc[j][i].adj=G.arc[i][j].adj;}}void shuchu(ALGraph ALG){//遍历邻接表并输出int i;ArcNode *p;for(i=0;i<ALG.vexnum;i++){printf("%d %c ",i,ALG.vertices[i].data);for(p=ALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)printf("%d ",p->adjvex);printf("\n");}}void Degree(ALGraph ALG,ALGraph InsertALG){//计算邻接表的度=邻接表的出度+逆邻接表的的出度int i;ArcNode *p;for(i=0;i<ALG.vexnum;i++){ALG.vertices[i].count=0;for(p=ALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)ALG.vertices[i].count++;}for(i=0;i<ALG.vexnum;i++){InsertALG.vertices[i].count=0;for(p=InsertALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)InsertALG.vertices[i].count++;}for(i=0;i<ALG.vexnum;i++){printf("%c的度为:%d\n",'A'+i,ALG.vertices[i].count+InsertALG.vertices[i].count);}}void dfs(ALGraph UALG,int v){//深度优先遍历ArcNode *p;visit[v]=1;printf("%c\n",UALG.vertices[v].data);p=UALG.vertices[v].firstarc;while(p){if(!visit[p->adjvex])dfs(UALG,p->adjvex);p=p->nextarc;}}void DFSTraverse(ALGraph UALG){for(int i=0;i<UALG.vexnum;i++)visit[i]=0;for(i=0;i<UALG.vexnum;i++)if(!visit[i])dfs(UALG,i);printf("\n");}void BFSTraverse(ALGraph UALG){//广度优先遍历ArcNode *p;int v;queue<int>q;for(int i=0;i<UALG.vexnum;i++)visit[i]=0;for(i=0;i<UALG.vexnum;i++)if(!visit[i]){visit[i]=1;printf("%c\n",UALG.vertices[i].data);q.push(i);while(!q.empty()){v=q.front();q.pop();p=UALG.vertices[v].firstarc;while(p){if(!visit[p->adjvex]){visit[p->adjvex]=1;printf("%c\n",UALG.vertices[p->adjvex].data);q.push(p->adjvex);}p=p->nextarc;}}}}void prim(MGraph G,char v){//用prim算法求最小生成树int i,j,k,min,n;k=locatevex(G,v);for(i=0;i<G.vexnum;i++){if(i!=k){closedge[i].adjvex=v;closedge[i].lowcost=G.arc[k][i].adj;}}closedge[k].lowcost=0;for(i=1;i<G.vexnum;i++){min=INFINITY;for(j=0;j<G.vexnum;j++){if(closedge[j].lowcost!=0&&closedge[j].lowcost<min){n=j;min=closedge[j].lowcost;}}printf("%c %c\n",closedge[n].adjvex,G.vex[n]);closedge[n].lowcost=0;for(j=0;j<G.vexnum;j++)if(G.arc[n][j].adj<closedge[j].lowcost&&G.arc[n][j].adj!=INFINITY){closedge[j].adjvex=G.vex[n];closedge[j].lowcost=G.arc[n][j].adj;}}printf("\n");}int indegree[max_vertex_num];int topsort(ALGraph ALG,ALGraph InsertALG){//拓扑排序ArcNode *p;stack<int>s;int i,k,count;for(i=0;i<ALG.vexnum;i++){InsertALG.vertices[i].count=0;for(p=InsertALG.vertices[i].firstarc;p!=NULL;p=p->nextarc)InsertALG.vertices[i].count++;}for(i=0;i<ALG.vexnum;i++){indegree[i]=InsertALG.vertices[i].count;printf("%d\n",indegree[i]);}for(i=0;i<ALG.vexnum;i++)if(indegree[i]==0)s.push(i);count=0;while(!s.empty()){i=s.top();s.pop();printf("%c ",ALG.vertices[i].data);count++;for(p=ALG.vertices[i].firstarc;p;p=p->nextarc){k=p->adjvex;indegree[k]--;if(indegree[k]==0)s.push(k);}}if(count<ALG.vexnum)return -1;elsereturn 1;}void short_dij(MGraph G,int v0,int *P,int *D){//用dij球最短路径int i,v,w,min;for(i=0;i<G.vexnum;i++){finial[i]=0;D[i]=G.arc[v0][i].adj;if(D[i]<INFINITY)P[i]=v0;}D[v0]=0;finial[v0]=1;for(i=1;i<G.vexnum;i++){min=INFINITY;for(w=0;w<G.vexnum;w++){if(finial[w]==0)if(D[w]<min){v=w;min=D[w];}}if(min<INFINITY)finial[v]=1;elsebreak;for(w=0;w<G.vexnum;w++){if(finial[w]==0&&min+G.arc[v][w].adj<D[w]){D[w]=min+G.arc[v][w].adj;P[w]=v;printf("%d ",P[w]);}}printf("\n");}printf("路径长度为:\n");for(i=0;i<G.vexnum;i++){if(D[i]==INFINITY)printf("无法到达!!!\n");elseprintf("%d\n",D[i]);}}int main(){int menu;char V;do{void print();scanf("%d",&menu);switch(menu){case 1: CreateALGraph(ALG,InsertALG);break;case 2: shuchu(ALG); break;case 3: CreateALGraph(ALG,InsertALG);Degree( ALG, InsertALG);break;case 4: CreateALGraph(ALG,InsertALG);topsort( ALG,InsertALG);break;case 5: CeratUALGraph(UALG);DFSTraverse(UALG);break;case 6: CeratUALGraph(UALG);BFSTraverse(UALG);break;case 7: CreateUDN(G,1);printf("请输入出发顶点:\n");scanf("%c",&V);prim(G,V);break;case 8: CreateUDN(G,0);short_dij( G, 0,P,D);break;case 0: return 0;}}while(menu!=0);return 0;}。
数据结构与算法课程实验报告-图的应用
(前面可加目录页)一. 实验目的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. 理解图的基本概念和表示方法;2. 掌握图的基本操作,包括节点的插入、删除,边的添加、删除等;3. 运用图的基本操作解决实际问题。
三、实验方法本实验使用Python编程语言实现图的基本操作。
首先,定义图类,包括图的初始化、节点的插入、删除,边的添加、删除等方法。
然后,根据实际需求设计测试用例,验证图的基本操作的正确性。
四、实验过程1. 图的初始化在图类的初始化方法中,创建一个空的字典用于存储节点和边的信息。
节点用唯一的标识符表示,边用包含两个节点标识符的元组表示。
2. 节点的插入编写节点插入方法,接收节点标识符作为参数,将节点添加到图中。
在添加节点时,需要判断节点是否已存在于图中,如果存在则不进行插入操作。
3. 节点的删除编写节点删除方法,接收节点标识符作为参数,将节点从图中删除。
在删除节点时,需要同时删除与该节点相关的边。
4. 边的添加编写边添加方法,接收两个节点标识符作为参数,将边添加到图中。
在添加边时,需要判断节点是否存在于图中,如果不存在则先进行节点的插入操作。
5. 边的删除编写边删除方法,接收两个节点标识符作为参数,将边从图中删除。
在删除边时,需要判断边是否存在于图中。
6. 测试用例设计设计多个测试用例,包括插入节点、删除节点、添加边、删除边等操作,并验证操作的正确性。
七、实验结果经过多次测试,图的基本操作均能正常运行,符合预期结果。
通过图的基本操作,可以方便地对图进行增、删、改、查等操作,解决实际问题。
八、实验总结通过本次实验,我深入理解了图的基本概念和表示方法,并掌握了图的基本操作。
图作为一种重要的数据结构,在计算机科学中有着广泛的应用,例如社交网络分析、路线规划等领域。
数据结构实验报告--图
.数据结构实验报告图一、实验目的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的各个未被访问的邻接点,然后分别从这些邻接点出发以此访问他们的邻接点,并使“先被访问的邻接顶点”先于“后被访问的邻接顶点”被访问,直至图中所有已被访问过的顶点的邻接顶点都被访问。
数据结构实验-图的基本操作
#include<stdio.h>#include<malloc.h>#define MAXV 30typedef int InfoType;typedef struct{int no;InfoType info;}VertexType;typedef struct{VertexType vexs[MAXV];int arcs[MAXV][MAXV];int vexnum,arcnum;}MGraph;typedef struct ArcNode{int adjvex;int weight;struct ArcNode *nextarc;}ArcNode;typedef struct VNode{VertexType data;ArcNode *firstarc;}VNode;//typedef VNode AdjList[MAXV]; typedef struct{VNode vertices[MAXV];int vexnum,arcnum;}LGraph;int visited[MAXV];int queue[MAXV];void CreateMG(MGraph &mg){int i,j;int A[7][7];mg.vexnum=7;mg.arcnum=9;for(i=0;i<mg.vexnum;i++)for(j=0;j<mg.vexnum;j++)A[i][j]=0;A[0][1]=A[0][2]=A[0][6]=1;A[1][3]=1;A[2][3]=A[2][5]=A[2][6]=1;A[3][4]=1;A[5][6]=1;for(i=1;i<mg.vexnum;i++)for(j=0;j<i;j++)A[i][j]=A[j][i];for(i=0;i<mg.vexnum;i++)for(j=0;j<mg.vexnum;j++)mg.arcs[i][j]=A[i][j];}void CreatLG(LGraph *&lg,MGraph mg){int i,j;ArcNode *p;lg=(LGraph *)malloc(sizeof(LGraph));for(i=0;i<mg.vexnum;i++)lg->vertices[i].firstarc=NULL;for(i=0;i<mg.vexnum;i++)for(j=mg.vexnum-1;j>=0;j--)if(mg.arcs[i][j]!=0){p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=j;p->weight=mg.arcs[i][j];p->nextarc=lg->vertices[i].firstarc;lg->vertices[i].firstarc=p;}lg->vexnum=mg.vexnum;lg->arcnum=mg.arcnum;}void OutputMG(MGraph mg){int i,j;for(i=0;i<mg.vexnum;i++){for(j=0;j<mg.vexnum;j++)printf("%3d",mg.arcs[i][j]);printf("\n");}}void OutputLG(LGraph *lg){int i;ArcNode *p;for(i=0;i<lg->vexnum;i++){p=lg->vertices[i].firstarc;if(p) printf("%3d: ",i);while(p){printf("%3d",p->adjvex);p=p->nextarc;}printf("\n");}}void LDFS(LGraph *lg,int i){ArcNode *p;printf("%3d",i);visited[i]=1;p=lg->vertices[i].firstarc;while(p){if(!visited[p->adjvex])LDFS(lg,p->adjvex);p=p->nextarc;}}void MDFS(MGraph mg,int i){int j;printf("%3d",i);visited[i]=1;for(j=0;j<mg.vexnum;j++){if(mg.arcs[i][j]!=0&&visited[j]==0)MDFS(mg,j);}}void LBFS(LGraph *lg,int s){int i,v,w,front,rear;ArcNode *p;for(i=0;i<lg->vexnum;i++)visited[i]=0;front=rear=0;printf("%3d",s);visited[s]=1;queue[rear++]=s;while(front<rear){v=queue[front++];for(p=lg->vertices[v].firstarc;p!=NULL;p=p->nextarc){ w=p->adjvex;if(visited[w]==0){printf("%3d",w);visited[w]=1;queue[rear++]=w;}}}}void MBFS(MGraph mg,int s){int i,j,v,front,rear;for(i=0;i<mg.vexnum;i++)visited[i]=0;front=rear=0;printf("%3d",s);visited[s]=1;queue[rear++]=s;while(front<rear){v=queue[front++];for(i=0;i<mg.vexnum;i++)for(j=0;j<mg.vexnum;j++){if(mg.arcs[i][j]!=0&&visited[j]==0){printf("%3d",j);visited[j]=1;queue[rear++]=j;}}}}void main(){LGraph *lg;MGraph mg;int i;CreateMG(mg);CreatLG(lg,mg);printf("(1)当前图的邻接矩阵是:\n");OutputMG(mg);printf("(2)当前图的邻接表是:\n");OutputLG(lg);for(i=0;i<mg.vexnum;i++)visited[i]=0;getchar();printf("(3)邻接表表示的图的深度优先遍历序列是:");LDFS(lg,0);getchar();for(i=0;i<mg.vexnum;i++)visited[i]=0;printf("(4)邻接矩阵表示的图的深度优先遍历序列是:");MDFS(mg,0);getchar();printf("(5)邻接表表示的图的广度优先遍历序列是:");LBFS(lg,0);getchar();printf("(6)邻接矩阵表示的图的广度优先遍历序列是:");MBFS(mg,0);printf("\n");}。
大数据结构与算法实验——图的基本操作
图的基本操作实验报告图的基本操作实验报告实验名称图的基本操作实验目的1.掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表的存储结构;2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和广度优先遍历的算法,复习栈和队列的应用;3.掌握以邻接矩阵作为存储结构的生成图的最小生成树的普利姆算法;实验内容编制一个演示图的邻接表的创建、深度遍历、广度遍历操作的程序。
问题描述用数据结构相关知识,实现邻接表的定义和操作。
该程序包括图的邻接表的结点类型定义以及对图操作的具体的函数定义(包括:建立图的邻接表、深度优先遍历图、广度优先遍历图)。
问题分析该实验是基于C语言和数据结构知识基础的对图的基本操作的检验,无需设计复杂的算法,程序语句也相对简单。
因此,我直接按要求定义了对图操作的具体函数,并于主函数中实现对应的功能调用。
实验步骤1.需求分析本演示程序用VC++编写,完成图的邻接表的生成、遍历基本操作。
① 输入的形式和输入值的范围:在输入邻接表顶点信息前,必须先确定该信息能正确创建邻接表。
②输出的形式:在所有三种操作中都显示操作是否正确以及操作后图的内容。
③程序所能达到的功能:完成图的邻接表的生成、深度优先遍历、广度优先遍历基本操作。
④测试数据:创建操作中依次输入7,7作为顶点数和边数,以(0,1)(0,2)(1,3)(1,5)(3,4)(3,6)(4,5)作为各顶点信息生成一个邻接表。
2.概要设计1)为了实现上述程序功能,需要定义二叉树的抽象数据类型:ADT Graph {数据对象:顶点的有穷非空集合和边的集合数据关系:结点具有相同的数据类型及层次结构基本操作:Void InitGraph(ALGraph *G)初始条件:无操作结果:初始化图Void DFSTraverse(ALGraph *G)初始条件:图Graph已存在操作结果:按深度优先遍历图的邻接表Void BFSTraverse(ALGraph *G)初始条件:图Graph已存在操作结果:按广度优先遍历图的邻接表2)本程序包含7个函数:①主函数main() ②建立一个图的邻接表函数CreateGraphAL ()③深度优先遍历图DFS ()④广度优先遍历BFS()函数说明#include <stdio.h>#include <stdlib.h>#define MaxVertexNum 100#define QueueSize 30typedef enum{FALSE,TRUE}Boolean;Boolean visited[MaxVertexNum];typedef char VertexType;typedef int EdgeType;typedef struct node //边表结点{int adjvex; //邻接点域struct node *next; //域链//若是要表示边上的权,则应增加一个数据域}EdgeNode;typedef struct vnode //顶点边结点{VertexType vertex; //顶点域EdgeNode *firstedge;//边表头指针}VertexNode;typedef VertexNode AdjList[MaxVertexNum]; //AdjList是邻接表类型typedef struct{AdjList adjlist; //邻接表int n,e; //图中当前顶点数和边数}ALGraph;void CreateGraphAL (ALGraph *G){int i,j,k;EdgeNode * s;printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");scanf("%d,%d",&(G->n),&(G->e)); // 读入顶点数和边数printf("请输入顶点信息(输入格式为:顶点号<CR>)每个顶点以回车作为结束:\n");for (i=0;i<G->n;i++) // 立有n个顶点的顶点表{scanf("\n%c",&(G->adjlist[i].vertex)); // 读入顶点信息G->adjlist[i].firstedge=NULL; // 点的边表头指针设为空}printf("请输入边的信息(输入格式为:i,j):\n");for (k=0;k<G->e;k++) // 建立边表{scanf("\n%d,%d",&i,&j); // 读入边<Vi,Vj>的顶点对应序号s=new EdgeNode; // 生成新边表结点ss->adjvex=j; // 邻接点序号为js->next=G->adjlist[i].firstedge; // 将新边表结点s插入到顶点Vi的边表头部G->adjlist[i].firstedge=s;s=new EdgeNode;s->adjvex=i;s->next=G->adjlist[j].firstedge;G->adjlist[j].firstedge=s;}}/************************************************************************/ /* 深度优先遍历*/ /************************************************************************/ void DFS(ALGraph *G,int i){//以vi为出发点对邻接表表示的图G进行深度优先搜索EdgeNode *p;printf("visit vertex:%c\n",G->adjlist[i].vertex); // 访问顶点vivisited[i]=TRUE; //标记vi已访问p=G->adjlist[i].firstedge; //取vi边表的头指针while(p){ //依次搜索vi的邻接点vj,这里j=p->adjvex if (!visited[p->adjvex]) //若vi尚未被访问DFS(G,p->adjvex); //则以Vj为出发点向纵深搜索p=p->next; //找vi的下一邻接点}}void DFSTraverseM(ALGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE;for(i=0;i<G->n;i++)if(!visited[i])DFS(G,i);}/************************************************************************/ /* 广度优先遍历*/ /************************************************************************/ typedef struct{int front;int rear;int count;int data[QueueSize];}CirQueue;void InitQueue(CirQueue *Q){Q->front=Q->rear=0;Q->count=0;}int QueueEmpty(CirQueue *Q){return Q->front==Q->rear;}int QueueFull(CirQueue *Q){return (Q->rear+1)%QueueSize==Q->front;}void EnQueue(CirQueue *Q,int x){if (QueueFull(Q))printf("Queue overflow");else{Q->count++;Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;}}int DeQueue(CirQueue *Q){int temp;if(QueueEmpty(Q)){printf("Queue underflow");return false;}else{temp=Q->data[Q->front];Q->count--;Q->front=(Q->front+1)%QueueSize;return temp;}}void BFS(ALGraph*G,int k){ // 以vk为源点对用邻接表表示的图G进行广度优先搜索int i;CirQueue Q; //须将队列定义中DataType改为intEdgeNode *p;InitQueue(&Q); //队列初始化printf("visit vertex:%c\n",G->adjlist[k].vertex); //访问源点vkvisited[k]=TRUE;EnQueue(&Q,k); //vk已访问,将其人队。
数据结构之图(图的基本操作)
数据结构之图(图的基本操作)由于图的基本操作的代码较多,我放到这⼀章来写。
图可以⽤两种⽅法来存储,但是本⼈偏爱链表的表⽰⽅法,所以以下代码也都是是基于邻接链表的存储⽅式。
1/*2以下存储结构参考严蔚敏版数据结构,不懂的可以翻阅查看3*/4const int UNDIGRAPH = 0; //⽆向图5const int DIGRAPH = 1; //有向图6const int MAX_VERTEX_NUM = 20;78 typedef struct ArchNode9 {10int vertexIndex; //该弧指向顶点在图中顶点数组的索引,对应vertexs[20]的下标11 ArchNode *nextarc; //指向下⼀条弧的指针12 InfoTypde info; //⽐如弧的权重13 }ArchNode;1415 typedef struct Vertex16 {17 VertexType data; //顶点信息18 ArchNode *firstarc; //指向第⼀条弧的指针19 }Vertex;2021//这样定义图有个坏处,⼀旦定义好,图中结点的个数就固定了!22 typedef struct Graph23 {24 Vertex *vertexs[MAX_VERTEX_NUM]; //存储顶点的数组,存放的是指向顶点的指针25int vexNum; //当前图中的定点数26int arcNum; //当前图中的弧的个数27int kind; //图的种类,有向图还是⽆向图28 }Graph;//图的创建1/*2初始条件:kind是图的类型,⽬前有有向图和⽆向图两种.3返回值:⽆。
---⼤部分函数都⽆返回值,是对图的引⽤进⾏操作的4*/5void createGraph(Graph *&G,int kind)6 {7if(G) G = NULL;8 G = (Graph *)malloc(sizeof(struct Graph));9 assert(NULL != G);10for(int i = 0; i < MAX_VERTEX_NUM; ++i)11 {12 G->vertexs[i] = NULL; //初始化指向顶点的指针为NULL13 }14 G->kind = kind; //设置图的种类15 G->vexNum = 0; //初始化图中顶点的个数16 G->arcNum = 0; //初始化图中弧的个数17 }//图的销毁1/*2初始条件:G存在3返回值:⽆。
数据结构实验-图的基本操作
浙江大学城市学院实验报告课程名称数据结构实验项目名称实验十三/十四图的基本操作学生姓名专业班级学号实验成绩指导老师(签名)日期 2014/06/09一.实验目的和要求1、掌握图的主要存储结构。
2、学会对几种常见的图的存储结构进行基本操作。
二.实验内容1、图的邻接矩阵定义及实现:建立头文件test13_AdjM.h,在该文件中定义图的邻接矩阵存储结构,并编写图的初始化、建立图、输出图、输出图的每个顶点的度等基本操作实现函数。
同时建立一个验证操作实现的主函数文件test13.cpp(以下图为例),编译并调试程序,直到正确运行。
2、图的邻接表的定义及实现:建立头文件test13_AdjL.h,在该文件中定义图的邻接表存储结构,并编写图的初始化、建立图、输出图、输出图的每个顶点的度等基本操作实现函数。
同时在主函数文件test13.cpp中调用这些函数进行验证(以下图为例)。
3、填写实验报告,实验报告文件取名为report13.doc。
4、上传实验报告文件report13.doc到BB。
注: 下载p256_GraphMatrix.cpp(邻接矩阵)和p258_GraphAdjoin.cpp(邻接表)源程序,读懂程序完成空缺部分代码。
三. 函数的功能说明及算法思路(包括每个函数的功能说明,及一些重要函数的算法实现思路)四. 实验结果与分析(包括运行结果截图、结果分析等)五.心得体会程序比较难写,但是可以通过之前的一些程序来找到一些规律(记录实验感受、上机过程中遇到的困难及解决办法、遗留的问题、意见和建议等。
)【附录----源程序】256://p-255 图的存储结构以数组邻接矩阵表示, 构造图的算法。
#include <iostream.h>#include <stdio.h>#include <stdlib.h>#include <string.h>typedef char VertexType; //顶点的名称为字符const int MaxVertexNum=10; //图的最大顶点数const int MaxEdgeNum=100; //边数的最大值typedef int WeightType; //权值的类型const WeightType MaxValue=32767; //权值的无穷大表示typedef VertexType Vexlist[MaxVertexNum]; //顶点信息,定点名称typedef WeightType AdjMatrix[MaxVertexNum][MaxVertexNum]; //邻接矩阵typedef enum{DG,DN,AG,AN} GraphKind; //有向图,有向网,无向图,无向网typedef struct{Vexlist vexs; // 顶点数据元素AdjMatrix arcs; // 二维数组作邻接矩阵int vexnum, arcnum; // 图的当前顶点数和弧数GraphKind kind; // 图的种类标志} MGraph;void CreateGraph(MGraph &G, GraphKind kd)// 采用数组邻接矩阵表示法,构造图G{//构造有向网Gint i,j,k,q;char v, w;G.kind=kd; //图的种类printf("输入要构造的图的顶点数和弧数:\n");scanf("%d,%d",&G.vexnum,&G.arcnum);getchar();//过滤回车printf("依次输入图的顶点名称ABCD...等等:\n");for (i=0; i<G.vexnum; i++) scanf("%c",&G.vexs[i]);//构造顶点数据getchar();//过滤回车for (i=0; i<G.vexnum; i++) //邻接矩阵初始化for (j=0; j<G.vexnum; j++)if(kd==DN||kd==AN)G.arcs[i][j]=MaxValue; //网,初始值为无穷大elseG.arcs[i][j]=0; //图,初始为0if(kd==DN||kd==AN)printf("按照:尾顶点名->头顶点名,权值输入数据:如A->B,23 \n");elseprintf("按照:尾顶点名->头顶点名输入数据:A->B\n");for (k=0; k<G.arcnum; k++){ //构造邻接矩阵if(kd==DN||kd==AN)scanf("%c->%c,%d",&v,&w,&q); //输入弧的两个定点及该弧的权重elsescanf("%c->%c",&v,&w);getchar();for(i=0;i<G.vexnum; i++)if(G.vexs[i]==v) break;//查找出v在vexs[]中的位置iif(i==G.vexnum) {cerr<<"vertex ERROR!";exit(1);} for(j=0;j<G.vexnum; j++)if(G.vexs[j]==w) break;//查找出v在vexs[]中的位置jif(j==G.vexnum) {cerr<<"vertex ERROR!";exit(1);}if(kd==AN)//无向网{G.arcs[i][j]=q; //邻接矩阵对应位置置权值G.arcs[j][i]=q; //无向图为对称矩阵}else if(kd==DN)//有向网G.arcs[i][j]=q;else if(kd==AG)//无向图{G.arcs[i][j]=1; //对称矩阵G.arcs[j][i]=1;}else //有向图G.arcs[i][j]=1;// getchar();}}//CreateGraph/* 注意输入格式,按以下方式输入构造有向网输入要构造的网的顶点数和弧数:4,5依次输入网的顶点名称ABCD...等等:abcd按照:尾顶点名->头顶点名,权值输入数据:如A->B,23 a->b,5a->c,8c->b,7a->d,4d->c,3输出邻接矩阵∞ | 5 | 8 | 4 |∞ | ∞ | ∞ | ∞ |∞ | 7 | ∞ | ∞ |∞ | ∞ | 3 | ∞ |Press any key to continue*/void PrintMGraph(MGraph &G){int i,j;switch(G.kind){case DG:for (i=0; i<G.vexnum; i++){for (j=0; j<G.vexnum; j++)printf(" %2.d | ",G.arcs[i][j]);printf("\n");}break;case DN:for (i=0; i<G.vexnum; i++){for (j=0; j<G.vexnum; j++){if(G.arcs[i][j]!=MaxValue) printf(" %2.d | ",G.arcs[i][j]);else printf(" ∞ | ");}printf("\n");}break;case AG:for (i=0; i<G.vexnum; i++){for (j=0; j<G.vexnum; j++){printf(" %2.d | ",G.arcs[i][j]);}printf("\n");}break;case AN: //********完成构造无向网****************/* 请模仿编写无向网*/for (i=0; i<G.vexnum; i++){for (j=0; j<G.vexnum; j++){if(G.arcs[i][j]!=MaxValue) printf(" %2.d | ",G.arcs[i][j]);else printf(" ∞ | ");}printf("\n");}break;}}//*****************完成函数**********************************void countdig(MGraph G) //请完成计算图的入度或初度{if(G.kind==DG||G.kind==DN){//计算有向图或网的各个顶点的入度与出度int outD,inD;int i,j;for(i=0;i<G.vexnum;i++){outD=inD=0;for(j=0;j<G.vexnum;j++){if(G.arcs[i][j]!=0&&G.arcs[i][j]!=MaxValue)outD++;}for(j=0;j<G.vexnum;j++){if(G.arcs[j][i]!=0&&G.arcs[j][i]!=MaxValue)inD++;}printf("%c:出度是%d,入度是%d\n",G.vexs[i],outD,inD);}}else{// 计算无向图或网的度int i,j;int Du;for(i=0;i<G.vexnum;i++){Du=0;for(j=0;j<G.vexnum;j++){if(G.arcs[i][j]!=0&&G.arcs[i][j]!=MaxValue)Du++;}printf("%c的度是%d\n",G.vexs,Du);}}}//************参照p265设计深度有限搜索***********void DFSMatrix(MGraph G,int i,int n,bool*visited){cout<<G.vexs[i]<<' ';visited[i]=true;for(int j=0;j<n;j++)if(G.arcs[i][j]!=0&&G.arcs[i][j]!=MaxValue&& !visited[j])DFSMatrix(G,j,n,visited);}//************参照p268设计广度有限搜索***********void BFSMatrix(MGraph G,int i, int n , bool*visited){const int MaxSize=30;int q[MaxSize]={0};int front=0,rear=0;cout<<G.vexs[i]<<' ';visited[i]=true;q[++rear]=i;while(front!=rear){front=(front+1)%MaxSize;int k=q[front];for(int j=0;j<n;j++){if(G.arcs[i][j]!=0&&G.arcs[i][j]!=MaxValue&& !visited[j]){cout<<G.vexs[j]<<' ';visited[j]=true;rear=(rear+1)%MaxSize;q[rear=j];}}}}void main(){MGraph G;int k;printf("请选择图的种类:0:有向图,1:有向网,2:无向图,3:无向网. 请选择:");scanf("%d",&k);switch(k) { //DG,DN,AG,ANcase 0:printf("构造有向图\n");CreateGraph(G,DG); // 采用数组邻接矩阵表示法,构造有向图break;case 1:printf("构造有向网\n");CreateGraph(G,DN); // 采用数组邻接矩阵表示法,构造有向网AGGbreak;case 2:printf("构造无向图\n");CreateGraph(G,AG); // 采用数组邻接矩阵表示法,构造无向图AGGbreak;case 3:printf("构造无向网\n");CreateGraph(G,AN); // 采用数组邻接矩阵表示法,构造无向网AGGbreak;}PrintMGraph(G); //打印图的邻接矩阵bool*visited=new bool[G.vexnum];int i;cout<<"按图的邻接矩阵得到的深度优先遍历序列"<<endl;for(i=0;i<G.vexnum;i++) visited[i]=false;DFSMatrix(G,0,G.vexnum,visited);cout<<"按图的邻接矩阵得到的广度优先遍历序列"<<endl;for(i=0;i<G.vexnum;i++) visited[i]=false;BFSMatrix(G,0,G.vexnum,visited);cout<<"度:"<<endl;countdig(G);}258://p-258 图的存储结构以邻接表表示, 构造图的算法。
数据结构---图的基本操作
数据结构---图的基本操作#include "stdio.h"#include "malloc.h"#define MAX_VERTEX_NUM 20#define OK 1#define error -1#define ERROR 0#define ErrorInput -2typedef int VertexType;typedef int Status;int CHIOCE;//用来接收用户的选择int VEXNUM,ARCNUM ; //用来接收用户输入的顶点和弧数目int i;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;//vexcount; //图的当前顶点和弧数和顶点计数,count记录真实结点个数int kind; //图的种类}ALGraph;typedef int ElemType;#define NULL 0typedef int ElemType;typedef struct QNode{ElemType data;struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;bool InitQueue(LinkQueue &Q){Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front) return false;Q.front->next=NULL;return true;}bool DestroyQueue(LinkQueue &Q){while(Q.front){Q.rear=Q.front->next;free(Q.front);Q.front=Q.rear;}return true;}bool EnQueue(LinkQueue &Q,ElemType data) {QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p) return false;p->data=data;p->next=NULL;Q.rear->next=p;Q.rear=p;return true;}bool DeQueue(LinkQueue &Q,ElemType &data) {QueuePtr p;if(Q.front==Q.rear) return false;p=Q.front->next;data=p->data;Q.front->next=p->next;if(Q.rear==p) Q.rear=Q.front;free(p);return true;}bool GetQueueTop(LinkQueue Q,ElemType &data){if(Q.front==Q.rear) return false;data=(Q.front->next)->data;return true;}bool QueueEmpty(LinkQueue &Q){if(Q.front==Q.rear) return true;return false;}void InitiateGraph(ALGraph *G){int i;G->vexnum=0;G->arcnum=0;for(i=0;i<MAX_VERTEX_NUM;i++){G->vertices[i].firstarc=NULL;}}/**********************在图G中第i个位置增添新顶点v *****************/void InsertVex(ALGraph *G,int i,VertexType v){if(i>=0&&i<MAX_VERTEX_NUM){G->vertices[i].data=v;//存储顶点数据元素vextexG->vexnum++; //个数加1 }elseprintf("顶点越界\n");}/***************************在图G中删除v*************************/Status DeleteVex(ALGraph &G,int v){//(事实上只是释放V-1处的空间并对v-1.data=-2做标记)int i=0;ArcNode *p,*q;for(i=0;i<G.vexnum;i++)//********删除以v为弧头的边*******{if(i==v) continue;if(G.vertices[i].firstarc==NULL) continue;if(G.vertices[i].firstarc->adjvex==v)//如果v为该节点的第一个临界弧所指向的顶点位置{p=G.vertices[i].firstarc;G.vertices[i].firstarc=p->nextarc;free(p);G.arcnum--;}else{ //q用来记录前一个弧,p为当前弧for(p=G.vertices[i].firstarc;p!=NULL;q=p,p=p->nextarc) {if(p->adjvex==v){q->nextarc=p->nextarc;free(p);G.arcnum--;break;//弧只有一条所以用break跳出}}}}//*********************删除以v为弧尾的边*************** if(G.vertices[v].firstarc!=NULL){p=G.vertices[v].firstarc;//p记录前一个弧q=p->nextarc;//q为当前弧//G.vertices[v].firstarc=NULL;while(1){free(p);G.arcnum--;if(q==NULL){break;}else{p=q;q=q->nextarc;}}}/*********************从数组中删除v节点**************************/for(i=v;i<G.vexnum-1;i++)G.vertices[i]=G.vertices[i+1];G.vexnum--;return OK;}void Connect(ALGraph &G,int v,int w){ArcNode *p,*q;if(G.vertices[v].firstarc==NULL){//如果是第一个节点为NULL,则直接建立p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=w;p->nextarc=NULL;G.vertices[v].firstarc=p;}else{//如果不是NULL则进行遍历到最后一个弧for(p=G.vertices[v].firstarc;p!=NULL;q=p,p=p->nextarc);p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=w;p->nextarc=NULL;q->nextarc=p;}}/*****在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v>*******/int InsertArc(ALGraph &G,int v,int w){if(v<0||v>=G.vexnum||w<0||w>=G.vexnum){printf("参数错误\n");return 0;}else{Connect(G,v,w);G.arcnum++;if(G.kind==1){//如果是无向图则反向插入一个弧Connect(G,w,v);G.arcnum++;}printf("添加弧成功\n");return 1;}}/*******************删除节点v和w间的弧***********************************/Status Delete(ALGraph &G,int v,int w){ArcNode *p,*q;if(G.vertices[v].firstarc->adjvex==(w))//该弧是第一条依附顶点v的弧{p=G.vertices[v].firstarc;G.vertices[v].firstarc=p->nextarc;free(p);G.arcnum--;return OK;}else{//否则遍历找到这条弧for(p=G.vertices[v].firstarc;(p->adjvex!=w)&&(p->nextarc !=NULL);q=p,p=p->nextarc);if(p->adjvex==w){q->nextarc=p->nextarc;free(p);G.arcnum--;return ERROR;}elseprintf("该弧不存在");return OK;}}/*****在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v>*******/Status DeleteArc(ALGraph &G,int v,int w){if(v<0||v>G.arcnum||w<0||w>G.arcnum){printf("参数错误");return ERROR;}else{Delete(G,v,w);if(G.kind==1){Delete(G,w,v);}return OK;}}/***********若G中存在顶点u,则返回该顶点在图中位置;否//则返回其它信息*******/int LocateVex(ALGraph G,int u){int i=0;while((G.vertices[i].data!=u)&&(i<G.vexnum))//遍历数组G.vertices[]查找ui++;if(G.vertices[i].data==u)return i;elsereturn ERROR;}/***********返回v的值*******************************/int GetVex(ALGraph G,int v){if(v<0||v>G.arcnum){printf("参数错误");return ERROR;}elsereturn G.vertices[v].data;}//**********对v赋值value*******************************Status SetVex(ALGraph &G,int v,int val){if(v<0||v>G.arcnum){printf("参数错误");return ERROR;}else{G.vertices[v].data=val;return OK;}}//******返回v的第一个邻接点。
数据结构之--图的基本运算方法
数据结构A:实验--图的基本运算方法一、实验目的和要求1.掌握在图的邻接矩阵和邻接表存储结构实现图的基本运算的算法。
学习使用图算法解决应用问题的方法。
(1). 验证教材中关于在邻接矩阵和邻接表两种不同存储结构上实现图的基本运算的算法(2)在邻接矩阵和邻接表存储结构上实现图的深度和宽度优先遍历算法。
(3)在两种储存结构上面分别实现Dijkstra、prim、Floyd算法2. 飞机最少换乘次数问题。
二、实验环境(实验设备)PC计算机,Windows 7操作系统,IDE: Codeblocks 16.01编译器: GNU GCC Compiler、实验原理及内容程序一:邻接矩阵表示的图的运算本程序包含邻接矩阵表示的图的基本运算,包括插入边,移除边,判断边是否存在,深度优先遍历DFS,宽度优先遍历BFS,单源最短路Dijkstra算法,多源最短路Floyd算法,以及最小生成树prim算法。
程序定义了一个图类包含三个数据成员,分别是指向二维数据的指针T **a,记录顶点数的n和记录边数量的e。
构造函数负责申请二维数组动态空间,析构函数负责释放空间。
类的声明:template<class T>class MGraph{public:MGraph(int mSize);~MGraph();bool Insert(int u,int v,int w);bool Remove(int u,int v);bool Exist(int u,int v)const;void DFS();void BFS();void Dijkstra(int v,T *d,int *path);void Floyd(int d[][Size],int path[][Size]);void prim(int k,int *nearest,T* lowcost);protected:int Choose(int *d,bool *s);void DFS(int v,bool *visited);void BFS(int v,bool *visited);T **a;int n,e;};(1)深度优先遍历DFS算法图的深度优先遍历重载了两个DFS函数,分别是面向用户的DFS()和私有成员DFS(int v,bool *visited)。
数据结构-实验8-图的基本操作
1.实验题目图的基本操作2.实验目的1)掌握图的邻接矩阵、邻接表的表示方法。
2)掌握建立图的邻接矩阵的算法。
3)掌握建立图的邻接表的算法。
4)加深对图的理解,逐步培养解决实际问题的编程能力3.需求分析(1)编写图基本操作函数。
①建立图的邻接表,邻接矩阵Create_Graph( LGraph lg. MGraph mg )②邻接表表示的图的递归深度优先遍历LDFS( LGraph g, int i )③邻接矩阵表示的图的递归深度优先遍历MDFS( MGraph g,int i, int vn )④邻接表表示的图的广度优先遍历LBFS( LGraph g, int s, int n )⑤邻接矩阵表示的图的广度优先遍历MBFS(MGraph g, int s, int n )(2)调用上述函数实现下列操作。
①建立一个图的邻接矩阵和图的邻接表。
②采用递归深度优先遍历输出图的邻接矩阵③采用递归深度优先遍历输出图的邻接表。
④采用图的广度优先调历输出图的邻接表。
⑤采用图的广度优先遍历输出图的邻接矩阵4.概要设计(1)结构体typedef struct{char vexs[MAX_VERTEX_NUM]; // 顶点向量int acrs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵int vexnum,arcnum; // 图当前顶点数和弧数}MGraph ;typedef struct ArcNode{int adjvex; // 该弧所指向的顶点的位置福建师范大学物光院计算机教学辅导讲义struct ArcNode *nextarc; // 指向下一条弧的指针}ArcNode;typedef struct VNode{char data; // 顶点信息ArcNode *firstarc; // 指向第一条依附该顶点的弧的指针}VNode, AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum; // 图当前顶点数和弧数}LGraph;typedef struct Queue{int arry[MAX_VERTEX_NUM];int front,rear;}Queue;(2)本程序主要包含6个函数:•主函数main()•建立图的邻接矩阵,邻接表Create_Graph ()•邻接表表示的图的递归深度优先遍历LDFS ()•邻接矩阵表示的图的递归深度优先遍历MDFS ()•邻接表表示的图的广度优先遍历LBFS ()•邻接矩阵表示的图的广度优先遍历MBFS()各函数间调用关系如下:福建师范大学物光院计算机教学辅导讲义(3)主函数的伪码main(){ 定义邻接矩阵和邻接表;建立邻接矩阵和邻接表;邻接矩阵MDFS深度优先遍历;邻接矩阵MBFS广度优先遍历;邻接表LDFS深度优先遍历;邻接表LBFS广度优先遍历}5详细设计#include<stdio.h>#include<malloc.h>#include<stddef.h>#include<math.h>#define OK 1#define ERROR 0#define MAX_VERTEX_NUM33int visited[MAX_VERTEX_NUM];typedef struct{int vexnum,arcnum; // 图当前顶点数和弧数char vexs[MAX_VERTEX_NUM]; // 顶点向量int acrs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵}MGraph ;typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode;typedef struct VNode{char data;ArcNode *firstarc;}VNode, AdjList[MAX_VERTEX_NUM];typedef struct{AdjList vertices;int vexnum,arcnum;}LGraph;typedef struct Queue{int arry[MAX_VERTEX_NUM];int front,rear;}Queue;Queue Q;void InitQueue(){Q.front=Q.rear=0;}int QueueEmpty(Queue *Q){if(Q->front==Q->rear)return 1;elsereturn 0;}void EnQueue(Queue *Q,int w){if((Q->rear+1)%MAX_VERTEX_NUM==Q->front) printf("Error!");else{Q->arry[Q->rear]=w;Q->rear=(Q->rear+1)%MAX_VERTEX_NUM;}int DeQueue(Queue *Q){int u;if(Q->front==Q->rear)return -1;u=Q->front;Q->front=(Q->front+1)%MAX_VERTEX_NUM;return u;}int Locatevex(MGraph *Mg , char v){int i;for(i=0;Mg->vexs[i]!=v;i++);if(i>Mg->vexnum)printf("ERROR ");return i;}int Create_Graph( MGraph *Mg , LGraph *Lg ) {int i , j , k ;char v1 , v2 ;ArcNode *q,*p;printf("输入图的顶点数和弧数: ");scanf("%d %d",&Mg->vexnum,&Mg->arcnum); getchar();Lg->vexnum=Mg->vexnum;Lg->arcnum=Mg->arcnum;for(i=0;i<Mg->vexnum;i++){printf("请输入一个字符作为图的顶点:");scanf("%c" , &Mg->vexs[i]);getchar();Lg->vertices[i].data=Mg->vexs[i];Lg->vertices[i].firstarc=NULL;}for(i=0;i<Mg->vexnum;i++)for(j=0;j<Mg->vexnum;j++)Mg->acrs[i][j]=0 ;for(k=0;k<Mg->arcnum;k++){printf("请输入一条边连接的2个顶点:");scanf("%c %c",&v1,&v2);getchar();i=Locatevex(Mg,v1);j=Locatevex(Mg,v2);Mg->acrs[j][i]=Mg->acrs[i][j]=1;p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=i;p->nextarc=Lg->vertices[j].firstarc;Lg->vertices[j].firstarc=p;q=(ArcNode *)malloc(sizeof(ArcNode));q->adjvex=j;q->nextarc=Lg->vertices[i].firstarc;Lg->vertices[i].firstarc=q;}return OK ;}int LAdjVex(LGraph *Lg,int k){ArcNode *p;for(p=Lg->vertices[k].firstarc;p!=NULL;p=p->nextarc) if(!visited[p->adjvex])return p->adjvex;福建师范大学物光院计算机教学辅导讲义return -1;}void LDFS(LGraph *Lg,int i){int k;visited[i]=OK;printf("%c",Lg->vertices[i].data);for(k=LAdjVex(Lg,i);k>=0;k=LAdjVex(Lg,k))if(!visited[k])LDFS(Lg,k);}int AdjVes(MGraph *Mg,int k){int i;for(i=0;i<Mg->vexnum;i++)if(Mg->acrs[k][i]&&(!visited[i]))return i;return -1;}void MDFS(MGraph *Mg,int i){int k;福建师范大学物光院计算机教学辅导讲义visited[i]=1;printf("%c",Mg->vexs[i]);for(k=AdjVes(Mg,i);k>=0;k=AdjVes(Mg,k))if(!visited[k])MDFS(Mg,k); // 递归}void LBFS( LGraph *Lg ){int i,u,w;for(i=0;i<Lg->vexnum;++i)visited[i]=0;InitQueue();for(i=0;i<Lg->vexnum;++i)if(!visited[i]){visited[i]=1;printf("%c",Lg->vertices[i].data);EnQueue(&Q,i);while(!QueueEmpty(&Q)){u=DeQueue(&Q);for(w=LAdjVex(Lg,u);w>=0;w=LAdjVex(Lg,u))if(!visited[w]){visited[w]=1;printf("%c",Lg->vertices[w].data);EnQueue(&Q,w);}}}}void MBFS(MGraph *Mg ){int i,w,u;for(i=0;i<Mg->vexnum;i++)visited[i]=0;InitQueue();for(i=0;i<Mg->vexnum;++i)if(!visited[i]) // 没被访问过{visited[i]=1;printf("%c",Mg->vexs[i]);EnQueue(&Q,i);while(!QueueEmpty(&Q)){u=DeQueue(&Q);for(w=AdjVes(Mg,u);w>=0;w=AdjVes(Mg,u))if(!visited[w]) // 没被访问过{visited[w]=1;printf("%c",Mg->vexs[w]);EnQueue(&Q,w); // 入队}}}}void main(){int i ;MGraph Mg;LGraph Lg;Create_Graph( &Mg, &Lg);printf("邻接表深度优先遍历LDFS:\t");for(i=0;i<Lg.vexnum;++i)visited[i]=0;for(i=0;i<Lg.vexnum;++i)if(!visited[i])LDFS(&Lg,i);printf("\n");printf("邻接矩阵深度优先遍历MDFS:\t");for(i=0;i<Mg.vexnum;i++)visited[i]=0;for(i=0;i<Mg.vexnum;i++)if(!visited[i])MDFS(&Mg,i);printf("\n邻接表广度优先遍历LBFS:\t");LBFS(&Lg) ;printf("\n邻接矩阵广度优先遍历MBFS:\t");MBFS(&Mg) ;printf("\n");}6测试结果。
实验4 图的基本操作
实验4 图的基本操作实验目的1.掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表存储结构。
2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和广度优先遍历算法,复习栈和队列的应用。
实验内容程序1/* 定义邻接矩阵类型*/typedef int adjmatrix[n+1][n+1];/* 建立图的邻接矩阵 */void CreatMatrix(adjmatrix GA)/* 从初始点v出发深度优先遍历邻接矩阵GA表示的图 */void DfsMatrix(adjmatrix GA,int v)/*从初始点v出发广度优先遍历邻接矩阵GA表示的图*/void BfsMatrix(adjmatrix GA,int v)程序2/* 邻接表的结点类型 */typedef struct arc{int adjvex;struct arc *next;}ArcNode;typedef struct VexNode{int vertex;ArcNode *firstarc;}VerNode;typedef VerNode AdjList[MAXNODE];/* 建立图的邻接表 */void CreatAdjlist(AdjList GL)/* 从初始点v出发深度优先遍历邻接表GL表示的图 */void DfsAdjlist(AdjList GL,int v)/*从初始点v出发广度优先遍历邻接表GL表示的图*/void BfsAdjlist(AdjList GL,int v)参考源程序程序一:以邻接表为存储结构时的遍历算法实现#define MAXNODE 10#define NULL 0typedef struct arc{int adjvex;struct arc *next;}ArcNode;typedef struct VexNode{int vertex;ArcNode *firstarc;}VerNode;typedef VerNode AdjList[MAXNODE];int visited[MAXNODE];int vexnum,arcnum;void creatgraph(AdjList GL){int i,j,k;ArcNode *p;printf("请输入顶点个数和边的个数:");scanf("%d%d",&vexnum,&arcnum);printf("请输入顶点(顶点用整型数代表):\n");for(i=1;i<=vexnum;i++){scanf("%d",&GL[i].vertex);GL[i].firstarc=NULL;}printf("请输入图的所有边(一条边的两个端点中间用,分隔): , \n"); for(k=1;k<=arcnum;k++){scanf("%d,%d",&i,&j);if(i&&j){p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;p->next=GL[i].firstarc;GL[i].firstarc=p;p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=i;p->next=GL[j].firstarc; GL[j].firstarc=p;}}}void DfsAdjlist(AdjList GL,int v){int i;for(i=1;i<=vexnum;i++) visited[i]=0;if(!visited[v]) dfs(GL,v);}int dfs(AdjList G,int v){ArcNode *q;if(!visited[v]) printf("%d,",G[v].vertex);visited[v]=1;q=G[v].firstarc;while(q!=NULL){if(!visited[q->adjvex]) dfs(G,q->adjvex);q=q->next;}}int BfsAdjlist(AdjList GL,int v){int k,i,j,Q[MAXNODE],front=0,rear=0; ArcNode *p;for(i=1;i<=vexnum;i++) visited[i]=0;visited[v]=1;printf("%d ",GL[v].vertex);rear=(rear+1)%MAXNODE;Q[rear]=v;while(front!=rear){front=(front+1)%MAXNODE;k=Q[front];p=GL[k].firstarc;while(p!=NULL){if(!visited[p->adjvex]){visited[p->adjvex]=1;printf("%d ",p->adjvex);rear=(rear+1)%MAXNODE;Q[rear]=p->adjvex;}p=p->next;}}}main(){AdjList GL;int v;creatgraph(GL);printf("请输入深度优先遍历的开始结点:"); scanf("%d",&v);printf("深度优先遍历序列是:"); DfsAdjlist(GL,v);printf("\n");printf("请输入广度优先遍历的开始结点:"); scanf("%d",&v);printf("广度优先遍历序列是:");BfsAdjlist(GL,v);}程序二:以邻接矩阵为存储结构时的遍历算法实现#define n 5#define MAXSIZE 10 /*广度优先遍历时所使用的队列的最大容量*/ #define MaxNum 10000 /*定义一个最大数*//* 定义邻接矩阵类型*/typedef int adjmatrix[n+1][n+1]; /* 0号单元没用*/int visited[n+1]; /* 0号单元没用*/int arcnum; /*边的个数*//* 建立图的邻接矩阵*/void CreatMatrix(adjmatrix GA){int i,j,k;printf("图中有%d个顶点\n",n);for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(i==j) GA[i][j]=0; /*对角线的值置为0*/else GA[i][j]=MaxNum; /*其它位置的值初始化为一个最大数*/ printf("请输入边的个数(限制在1到10的范围内):");scanf("%d",&arcnum);printf("请输入图的所有边(一条边的两个端点中间用,分隔): , \n");for(k=1;k<=arcnum;k++){scanf("%d,%d",&i,&j); /*读入边的信息*/GA[i][j]=1;GA[j][i]=1;}}/* 从初始点v出发深度优先搜索邻接矩阵GA表示的图*/void DfsMatrix(adjmatrix GA,int v){int j;visited[v]=1; printf("%d,",v);for(j=1;j<=n;j++)if(v!=j&&GA[v][j]!=MaxNum&&!visited[j]) DfsMatrix(GA,j);}void BfsMatrix(adjmatrix GA,int v){int i,k,j,Q[MAXSIZE],front=0,rear=0;for(i=1;i<=n;i++) visited[i]=0;visited[v]=1;printf("%d ",v);rear=(rear+1)%MAXSIZE; /*开始遍历的顶点入队列*/Q[rear]=v;while(front!=rear){front=(front+1)%MAXSIZE; /*队头元素出队*/k=Q[front];for(j=1;j<=n;j++)if((!visited[j])&&(GA[k][j]==1)) /*访问与队头元素邻接的还未被访问的结点*/ {visited[j]=1;printf("%d ",j);rear=(rear+1)%MAXSIZE;Q[rear]=j;}}}main(){adjmatrix GA;int v;CreatMatrix(GA);printf("请输入深度优先遍历的开始结点:");scanf("%d",&v);printf("深度优先遍历序列是:");DfsMatrix(GA,v);printf("\n");printf("请输入广度优先遍历的开始结点:");scanf("%d",&v);printf("广度优先遍历序列是:");BfsMatrix(GA,v);}。
数据结构实验七 图及图的操作实验
实验报告七图及图的操作实验班级: 2010XXX 姓名: HoogLe 学号: 2010XXXX 专业: XXXX*****************一、实验目的:1、掌握图的基本概念和术语2、掌握图的存储结构及创建算法。
3、掌握图的遍历算法(递归算法)。
二、实验内容:1、图邻接矩阵存储结构表示及基本操作算法实现[实现提示] (同时可参见教材及ppt上的算法)函数、类名称等可自定义,部分变量请加上学号后3位。
也可自行对类中所定义的操作进行扩展。
所加载的库函数或常量定义及类的定义:(1)邻接矩阵存储结构类定义:自定义如下:#include <iostream>using namespace std;const int MaxSize=12;const int INFINITY=65535;template<class T>class Mgraph{public:Mgraph(T a[],int n,int e);//构造函数,a[]表示节点数组,n表示顶点个数,e表示边数void printGraph(); //输出void BFS(int v,int visited[]); //广度优先搜索private:T vertex[MaxSize];int arc[MaxSize][MaxSize];int vertexNum,arcNum;void createUG(T a[],int n,int e); //无向图void createUW(T a[],int n,int e); //无向网void createHG(T a[],int n,int e); //有向图void createHW(T a[],int n,int e); //有向网};template<class T>Mgraph<T>::Mgraph(T a[],int n,int e){int kind;cout<<"请输入所需创建的图的类型:"<<endl;cout<<"1.无向图"<<endl;cout<<"2.无向网"<<endl;cout<<"3.有向图"<<endl;cout<<"4.有向网"<<endl;cin>>kind;switch(kind){case 1:createUG(a,n,e);break;case 2:createUW(a,n,e);break;case 3:createHG(a,n,e);break;case 4:createHW(a,n,e);break;default:cout<<"输入错误!"<<endl;}}(2)创建邻接矩阵算法创建无向图邻接矩阵算法:template <class T>void Mgraph<T>::createUG(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{ cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2):";cin>>i>>j; //边依附的两个顶点的序号arc[i-1][j-1]=1; //置有边标志arc[j-1][i-1]=1;}}创建无向网邻接矩阵算法:无向网的创建:template <class T>void Mgraph<T>::createUW(T a[],int n,int e){//创建无向网int w;//权值vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=INFINITY;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2 权值):";cin>>i>>j>>w;//边依附的两个顶点的序号arc[i-1][j-1]=w; //置有边标志arc[j-1][i-1]=w;}}创建有向图邻接矩阵算法:template <class T>void Mgraph<T>::createHG(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{ cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2):";cin>>i>>j; //边依附的两个顶点的序号arc[i-1][j-1]=1; //置有边标志}}创建有向网邻接矩阵算法:template <class T>void Mgraph<T>::createHW(T a[],int n,int e){//创建无向图vertexNum=n; //顶点数arcNum=e; //边数int i,j,k;int w;for (i=0; i<vertexNum; i++)vertex[i]=a[i];for (i=0; i<vertexNum; i++) //初始化邻接矩阵for (j=0; j<vertexNum; j++)arc[i][j]=0;for (k=0; k<arcNum; k++)//依次输入每一条边,并修改邻接矩阵的相应元素{cout<<"请输入第"<<k+1<<"条边(格式:顶点1 顶点2 权值):";cin>>i>>j>>w; //边依附的两个顶点的序号arc[i-1][j-1]=w; //置有边标志}}(3)输出邻接矩阵结果算法template <class T>void Mgraph<T>::printGraph(){//输出邻接矩阵int i,j;for(i=0;i<vertexNum;i++){for(j=0;j<vertexNum;j++)cout<<arc[i][j]<<ends;cout<<endl;}}测试结果粘贴如下:void main(){int a[6]={1,2,3,4,5,6};Graph<int> graph1(a,6,5);graph1.printGraph();}2、图邻接表存储结构表示及基本操作算法实现[实现提示]函数、类名称等可自定义,部分变量请加上学号后3位。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图的基本操作实验报告图的基本操作实验报告实验名称图的基本操作实验目的1.掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表的存储结构;2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和广度优先遍历的算法,复习栈和队列的应用;3.掌握以邻接矩阵作为存储结构的生成图的最小生成树的普利姆算法;实验内容编制一个演示图的邻接表的创建、深度遍历、广度遍历操作的程序。
问题描述用数据结构相关知识,实现邻接表的定义和操作。
该程序包括图的邻接表的结点类型定义以及对图操作的具体的函数定义(包括:建立图的邻接表、深度优先遍历图、广度优先遍历图)。
问题分析该实验是基于C语言和数据结构知识基础的对图的基本操作的检验,无需设计复杂的算法,程序语句也相对简单。
因此,我直接按要求定义了对图操作的具体函数,并于主函数中实现对应的功能调用。
实验步骤1.需求分析本演示程序用VC++编写,完成图的邻接表的生成、遍历基本操作。
① 输入的形式和输入值的范围:在输入邻接表顶点信息前,必须先确定该信息能正确创建邻接表。
②输出的形式:在所有三种操作中都显示操作是否正确以及操作后图的内容。
③程序所能达到的功能:完成图的邻接表的生成、深度优先遍历、广度优先遍历基本操作。
④测试数据:创建操作中依次输入7,7作为顶点数和边数,以(0,1)(0,2)(1,3)(1,5)(3,4)(3,6)(4,5)作为各顶点信息生成一个邻接表。
2.概要设计1)为了实现上述程序功能,需要定义二叉树的抽象数据类型:ADT Graph {数据对象:顶点的有穷非空集合和边的集合数据关系:结点具有相同的数据类型及层次结构基本操作:Void InitGraph(ALGraph *G)初始条件:无操作结果:初始化图Void DFSTraverse(ALGraph *G)初始条件:图Graph已存在操作结果:按深度优先遍历图的邻接表Void BFSTraverse(ALGraph *G)初始条件:图Graph已存在操作结果:按广度优先遍历图的邻接表2)本程序包含7个函数:①主函数main() ②建立一个图的邻接表函数CreateGraphAL ()③深度优先遍历图DFS ()④广度优先遍历BFS()函数说明#include <stdio.h>#include <stdlib.h>#define MaxVertexNum 100#define QueueSize 30typedef enum{FALSE,TRUE}Boolean;Boolean visited[MaxVertexNum];typedef char VertexType;typedef int EdgeType;typedef struct node //边表结点{int adjvex; //邻接点域struct node *next; //域链//若是要表示边上的权,则应增加一个数据域}EdgeNode;typedef struct vnode //顶点边结点{VertexType vertex; //顶点域EdgeNode *firstedge;//边表头指针}VertexNode;typedef VertexNode AdjList[MaxVertexNum]; //AdjList是邻接表类型typedef struct{AdjList adjlist; //邻接表int n,e; //图中当前顶点数和边数}ALGraph;void CreateGraphAL (ALGraph *G){int i,j,k;EdgeNode * s;printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");scanf("%d,%d",&(G->n),&(G->e)); // 读入顶点数和边数printf("请输入顶点信息(输入格式为:顶点号<CR>)每个顶点以回车作为结束:\n");for (i=0;i<G->n;i++) // 立有n个顶点的顶点表{scanf("\n%c",&(G->adjlist[i].vertex)); // 读入顶点信息G->adjlist[i].firstedge=NULL; // 点的边表头指针设为空}printf("请输入边的信息(输入格式为:i,j):\n");for (k=0;k<G->e;k++) // 建立边表{scanf("\n%d,%d",&i,&j); // 读入边<Vi,Vj>的顶点对应序号s=new EdgeNode; // 生成新边表结点ss->adjvex=j; // 邻接点序号为js->next=G->adjlist[i].firstedge; // 将新边表结点s插入到顶点Vi的边表头部G->adjlist[i].firstedge=s;s=new EdgeNode;s->adjvex=i;s->next=G->adjlist[j].firstedge;G->adjlist[j].firstedge=s;}}/************************************************************************/ /* 深度优先遍历*/ /************************************************************************/ void DFS(ALGraph *G,int i){//以vi为出发点对邻接表表示的图G进行深度优先搜索EdgeNode *p;printf("visit vertex:%c\n",G->adjlist[i].vertex); // 访问顶点vivisited[i]=TRUE; //标记vi已访问p=G->adjlist[i].firstedge; //取vi边表的头指针while(p){ //依次搜索vi的邻接点vj,这里j=p->adjvex if (!visited[p->adjvex]) //若vi尚未被访问DFS(G,p->adjvex); //则以Vj为出发点向纵深搜索p=p->next; //找vi的下一邻接点}}void DFSTraverseM(ALGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE;for(i=0;i<G->n;i++)if(!visited[i])DFS(G,i);}/************************************************************************/ /* 广度优先遍历*/ /************************************************************************/ typedef struct{int front;int rear;int count;int data[QueueSize];}CirQueue;void InitQueue(CirQueue *Q){Q->front=Q->rear=0;Q->count=0;}int QueueEmpty(CirQueue *Q){return Q->front==Q->rear;}int QueueFull(CirQueue *Q){return (Q->rear+1)%QueueSize==Q->front;}void EnQueue(CirQueue *Q,int x){if (QueueFull(Q))printf("Queue overflow");else{Q->count++;Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;}}int DeQueue(CirQueue *Q){int temp;if(QueueEmpty(Q)){printf("Queue underflow");return false;}else{temp=Q->data[Q->front];Q->count--;Q->front=(Q->front+1)%QueueSize;return temp;}}void BFS(ALGraph*G,int k){ // 以vk为源点对用邻接表表示的图G进行广度优先搜索int i;CirQueue Q; //须将队列定义中DataType改为intEdgeNode *p;InitQueue(&Q); //队列初始化printf("visit vertex:%c\n",G->adjlist[k].vertex); //访问源点vkvisited[k]=TRUE;EnQueue(&Q,k); //vk已访问,将其人队。
(实际上是将其序号人队)while(!QueueEmpty(&Q)){ //队非空则执行i=DeQueue(&Q); //相当于vi出队p=G->adjlist[i].firstedge; //取vi的边表头指针while(p){ //依次搜索vi的邻接点vj(令p->adjvex=j) if(!visited[p->adjvex]){ //若vj未访问过printf("visit vertex:%c\n",G->adjlist[p->adjvex].vertex); //访问vjvisited[p->adjvex]=TRUE;EnQueue(&Q,p->adjvex); //访问过的vj人队}p=p->next; //找vi的下一邻接点}}}void BFSTraverseM(ALGraph *G){int i;for (i=0;i<G->n;i++)visited[i]=FALSE;for (i=0;i<G->n;i++)if (!visited[i])BFS(G,i);}/************************************************************************/ /* 主函数调用*/ /************************************************************************/ int main(){int n;ALGraph G;CreateGraphAL(&G);printf("深度优先遍历:\n");DFSTraverseM(&G);printf("广度优先遍历:\n");BFSTraverseM(&G);return 0;}程序流程图调试报告发现问题:1.在创建图的邻接表以后,得到的深度优先遍历和自己在草稿纸上演算得到的序列不符。