一、 题目:图的抽象数据类型实现 利用 VC++的工作环境实现教材里图的基本抽象数据类型。按照课本的要求运用 c 语言 以及数据结构课程所学的知识,设计合理的数据存储结果,实现图的基本操作。 二、 抽象数据类型定义以及各基本操作的简要描述 ADT MGraph{ 数据对象:n=n 是具有相同特征的数据元素集合,称为顶点集。 数据关系:DR={|v,w∈n 且表示从 v 指向 w 的弧} 基本操作: CreateMGraph 初始条件:n 是图的顶点集,e 是图的边集 操作结果:按和 n 的 e 定义构造图 G DestroyGraph 初始条件: 图 G 存在 操作结果: 销毁图 G GetVex 初始条件: 图 G 存在,v 是 G 中某个顶点 操作结果: 返回 v 的值 LocateVex 初始条件:图 G 存在,v 和 G 中顶点有相同特征 操作结果:若 G 中存在顶点 v,则返回该顶点再图中的位置;否则返回 空 PutVex 初始条件: 图 G 存在,v 是 G 中某个顶点 操作结果: 对 v 赋值 u FirstAdjVex 初始条件: 图 G 存在,v 是 G 中某个顶点 */ 操作结果: 返回的第一个邻接顶点。若顶点在 G 中没有邻接顶点,则返 回空 NextAdjVex 初始条件: 图 G 存在,v 是 G 中某个顶点,w 是 v 的邻接顶点 操作结果: 返回 v(相对 w)的下一个邻接顶点。若 w 是 v 的最后一个 邻接点,则返回空 InsertVex 初始条件: 图 G 存在,v 和图 G 中顶点有相同特征 操作结果: 在图 G 中增添新顶点 v(不增添与顶点相关的边 ,留待 InsertArc()去做) DeleteVex 初始条件: 图 G 存在,v 是 G 中某个顶点 操作结果: 删除 G 中顶点 v 及其相关的弧 InsertArc 初始条件: 图 G 存在,v 和 W 是 G 中两个顶点 操作结果: 在 G 中增添弧 DeleteArc 初始条件: 图 G 存在,v 和 w 是 G 中两个顶点 操作结果: 在 G 中删除弧 DFSTraverseM 初始条件:图 G 存在 操作结果:对图进行深度优先遍历 BFSTraverseM 初始条件:图 G 存在 操作结果:对图进行广度优先遍历 }ADT MGraph 三、存储结构定义 头文件:#include #include #define MaxLen 10/*最大输入长度*/ #define False 0 #define True 1 #define Error printf #define QueueSize 30 #define Null 0 #define OK 1 ypedef struct { char vexs[MaxLen]; int edges[MaxLen][MaxLen]; int n,e; }MGraph; /*定义全局变量*/ int visited[10]; /*辅助队列的定义*/ typedef struct { int front; int rear; int count; int data[QueueSize]; }CirQueue; void InitQueue(CirQueue *Q) { Q->front=Q->rear=0; Q->count=0; } 1 int QueueEmpty(CirQueue *Q) { return Q->count=QueueSize; } int QueueFull(CirQueue *Q) { return Q->count==QueueSize; } void EnQueue(CirQueue *Q,int x) { if (QueueFull(Q)) Error("Queue overflow"); else { Q->count++; Q->data[Q->rear]=x; Q->rear=(Q->rear+1)%QueueSize; }//else }//EnQueue(CirQueue *Q,int x) int DeQueue(CirQueue *Q) { int temp; if(QueueEmpty(Q)) { Error("Queue underflow"); return Null; }//if(QueueEmpty(Q)) else { temp=Q->data[Q->front]; Q->count--; Q->front=(Q->front+1)%QueueSize; return temp; }//else }//DeQueue(CirQueue *Q) 2 四、程序源代码 void CreateMGraph(MGraph &G) { /* 初始条件:n 是图的顶点集,e 是图的边集*/ /* 操作结果:按和 n 的 e 定义构造图 G*/ int i,j,k; char ch1,ch2; printf("\t\t 请输入顶点数和边数(输入格式为:顶点数,边数):\n\t\t"); scanf("%d,%d",&(G.n),&(G.e)); printf("\t\t 请输入顶点信息(字符型)每个顶点以回车作为结束:\n"); for(i=0;iG.n) Error("没有该顶点"); else { printf("第%d 个顶点的值为:",v); printf("%c",G.vexs[v-1]); }//else printf("\n"); printf("\n"); system("pause"); return G.vexs[v-1]; }//GetVex(MGraph G) int LocateVex(MGraph G,char v) { /*初始条件:图 G 存在,v 和 G 中顶点有相同特征*/ /*操作结果:若 G 中存在顶点 v,则返回该顶点再图中的位置;否则返回空 */ printf("\t\t 请输入要查找的顶点信息(字符类型)以回车作为结束:\n"); scanf("%c",&v); int i; for(i=0;i<=G.n;++i) if(v==G.vexs[i]) { printf("\t\t 该接点在图中是第%d 个顶点!\n",i+1); printf("\n"); printf("\n"); system("pause"); return i+1; }//if(v==G.vexs[i]) printf("\t\t 没有与之匹配的顶点!\n"); printf("\n"); printf("\n"); 4 system("pause"); return Null; }//LocateVex(MGraph G,char v) int PutVex(MGraph &G,char v,char u) {/* 初始条件: 图 G 存在,v 是 G 中某个顶点 */ /* 操作结果: 对 v 赋值 u*/ printf("\t\t 请输入要查找的顶点信息(字符类型)以回车作为结束:\n"); scanf("%c",&v); int i; for(i=0;i<=G.n;++i) if(v==G.vexs[i]) { printf("\t\t 该接点已经找到,它在图中是第%d 个顶点!\n",i+1); getchar(); printf("\t\t 请输入要赋给该顶点的值(字符类型)以回车作为结束:\n"); scanf("%c",&u); G.vexs[i]=u; printf("\t\t 已将%c 顶点改为%c\n",v,u); printf("\n"); printf("\n"); system("pause"); return G.vexs[i]; }//if(v==G.vexs[i]) printf("\t\t 查找不到该顶点!\n"); printf("\n"); printf("\n"); system("pause"); }//PutVex(MGraph &G,char v,char u) int FirstAdjVex(MGraph G,char v) {/* 初始条件: 图 G 存在,v 是 G 中某个顶点 */ /* 操作结果: 返回的第一个邻接顶点。 若顶点在 G 中没有邻接顶点, 则返回 "空"*/ printf("\t\t 请输入要查找的顶点信息(字符类型)以回车作为结束:\n"); scanf("%c",&v); int i,j; for(i=0;ij;m--) { if(NextAdjVex(G,v,m)) { G.edges[j][m-1]=G.edges[j][m]; G.edges[j][m]=Null; G.e--; } else { G.edges[m-1][j-1]=G.edges[m][j]; G.edges[j][m]=Null; G.e--; } }//for(m=G.n;m>j;m--) for(k=i+1;k<=G.n+1;k++) { G.vexs[k-1]=G.vexs[k];//删除顶点 v 并将后续顶点前移 } G.n--; 8 printf("\t\t 顶点%c 已经删除!\n",v); printf("\n"); printf("\n"); system("pause"); return OK; }// if(G.vexs[i]==v) } while(G.vexs[i]==v); Error("\t\t%c 不是图中顶点\n",v); printf("\n"); printf("\n"); system("pause"); return 0; }//int DeleteVex(MGraph &G,char v) int InsertArc(MGraph &G,char v,char w) { /* 初始条件: 图 G 存在,v 和 W 是 G 中两个顶点 */ /* 操作结果: 在 G 中增添弧 */ printf("\t\t 请依次输入要添加弧的两个顶点(格式 i,j)以回车作为结束:\n"); scanf("%c,%c",&v,&w); int i,j; for(i=0;i<=G.n;i++) for(j=0;j<=G.n;j++) if(G.vexs[i]==v&&G.vexs[j]==w) { if(!G.edges[i][j]) { G.edges[i][j]=1; G.e++; printf("\t\t 弧%c%c 已经添加!\n",v,w); printf("\n"); printf("\n"); system("pause"); return G.edges[i][j]; }//if(!G.edges[i][j] else printf("\t\t 该弧已经存在!\n"); printf("\n"); printf("\n"); system("pause"); return Null; }//if(G.vexs[i]==v&&G.vexs[j]==w) }//InsertArc(MGraph &G,char v,char w) int DeleteArc(MGraph &G,char v,char w) 9 {/* 初始条件: 图 G 存在,v 和 w 是 G 中两个顶点 */ /* 操作结果: 在 G 中删除弧 */ printf("\t\t 请依次输入要删除弧的两个顶点(格式 i,j)以回车作为结束:\n"); scanf("%c,%c",&v,&w); int i,j; for(i=0;i<=G.n;i++) for(j=0;j<=G.n;j++) if(G.vexs[i]==v&&G.vexs[j]==w) { if(G.edges[i][j]) { G.edges[i][j]=Null; G.e--;//弧减一 printf("\t\t 弧%c%c 已经删除!\n",v,w); printf("\n"); printf("\n"); system("pause"); return OK; }//if(G.edges[i][j]) else printf("\t\t 弧%c%c 不存在!\n",v,w); printf("\n"); printf("\n"); system("pause"); return 0; }//if(G.vexs[i]==v&&G.vexs[j]==w) }//DeleteArc(MGraph &G,char v,char w) void DFSM(MGraph G,int i) { int j; printf("\t\t 深度优先遍历结点:结点%C\n",G.vexs[i]); visited[i]=True; for(j=0;j 创建图:(建图菜单) 13 输入: 5,3 回车; 依次输入:a 回车;b 回车;c 回车;d 回车;f 回车; 依次输入:a,b 回车;b,d 回车;f,c 回车 图的邻接矩阵建立完毕。输入:任意键; 图子菜单 14 <2>销毁图:输入:2 回车; <3>按步骤<1>重建图的邻接矩阵; <4>返回顶点 v 的位置:输入:3 回车;f 回车; <5>返回顶点 v 的值:输入:4 回车; 4 回车,d 回车; <6>对顶点 v 赋值:输入:5 回车;d 回车;r 回车; <7>返回顶点 v 的第一个邻接点: 输入:6 回车;d 回车; 15 <8>返回 v 相对 w 的下一个邻接点:输入:7 回车;c 回车;e 回车; <9>插入顶点 v:输入:8 回车;o 回车; <10>删除顶点 v:输入:9 回车;z 回车; <11>插入边:输入 10 回车;a,v 回车; <12>删除边:输入:11 回车;a,r 回车; 16 <13>深度优先遍历:输入:12 回车 <14>广度优先遍历:输入:13 回车 六、 实验总结 ADT 抽象数据类型课程设计是对一学期的数据结构课程的很好总结与提 高,通过做一个完整的 ADT 我们可以触类旁通的学习到一些数据结构基本 类型的建立,此次我做的图的 ADT,基本的操作比较多,存储的方式也有 很多种, 由于时间的关系和本人编程能力的关系,我选择了相对来说易于操 作的邻接矩阵的存储结构.在编程的过程中遇到了各种各样的问题,通过网 络,图书馆,和与别人讨论,这些问题都一一的解决了,在解决的问题中我 觉得自己进步了许多,通过做完这个 ADT,对 C/C++的学习也起了很大的 帮助, 提高了编程的能力, 当做完一个作品后会觉得很高兴。 尽管这个 ADT 还存在着一些这样那样的问题,但是总的来说收获很多,我将会在以后的时 间里继续完善它。 17