实验四 图的有关操作
目的要求:
1.掌握图的存储思想及其存储实现。
2.掌握图的深度、广度优先遍历算法思想及其程序实现。
3.掌握图的常见应用算法的思想及其程序实现。
实验内容:
1.键盘输入数据,建立一个有向图的邻接表。
2.输出该邻接表。
*3.建立一个无向图的十字链表。
4.在有向图的邻接表的基础上计算各顶点的度,并输出。
5.以有向图的邻接表为基础实现输出它的拓扑排序序列。
*6.采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。
7.采用邻接表存储实现无向图的深度优先非递归遍历。
8.采用邻接表存储实现无向图的广度优先遍历。
*9.采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。
*10.判断无向图任意两个顶点间是否有路径,若有输出路径上的顶点序列。
11.在主函数中设计一个简单的菜单,分别调试上述算法。
*12.综合训练:为计算机专业设计教学计划:4个学年,每学年2个学期,开设50门课程,每学期所开课程门数尽量均衡,课程的安排必须满足先修关系。
代码实现:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define Maxsize 200 using namespace std; int indegree[Maxsize],outdegree[Maxsize]; typedef char InfoType;///图的邻接表存储结构 typedef char VertexType; ///节点数据为字符型 typedef struct ArcNode ///表节点 { int adjvex; ///存放结点的下标 struct ArcNode *nextarc;///指向下一条边或弧的指针域 InfoType *info;///其他信息 } ArcNode; typedef struct VNode ///头结点 { VertexType data; ArcNode *firstarc; } VNode,AdjList[Maxsize]; typedef struct ///图结构 { AdjList vertices; int vexnum,arcnum;///图中顶点个数和边的个数 int kind; ///kind==0表示无向图,kind==1表示有向图 } ALGraph; int visited[Maxsize]; void Create(ALGraph &G) { char ch1,ch2; int k1,k2; printf("Please Input the Vexnum & Arcnum:\n"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("Please Input the Vexnums:\n"); for(int i=1; i<=G.vexnum; i++) ///图结构的下标从1开始用 { scanf(" %c",&G.vertices[i].data); G.vertices[i].firstarc=NULL; } printf("Please Input the Arcnums:\n"); for(int i=1; i<=G.arcnum; i++) { scanf(" %c %c",&ch1,&ch2); for(int p=1; p<=G.arcnum; p++) { if(G.vertices[p].data==ch1) { k1=p; break; } } for(int p=1; p<=G.arcnum; p++) { if(G.vertices[p].data==ch2) { k2=p; break; } } ArcNode *pp;///申请一个表节点之后进行前插,前插,特别注意 pp=(ArcNode*)malloc(sizeof(ArcNode)); pp->adjvex=k2; pp->nextarc=G.vertices[k1].firstarc; G.vertices[k1].firstarc=pp; } } void Dfs(ALGraph G,VertexType x)///深搜,从节点元素为x开始搜索 { //ALGraph G=GG; int k1; for(int i=1; i<=G.vexnum; i++) { if(G.vertices[i].data==x) { k1=i; break; } } printf("%c ",G.vertices[k1].data); visited[k1]=1; ArcNode *p; p=G.vertices[k1].firstarc; while(p)///如果该点的第一邻接点存在 { if(visited[p->adjvex]==0) ///如果第一邻接点没有被遍历过 { Dfs(G,G.vertices[p->adjvex].data); ///就去图中以该点的元素为起始点深度优先遍历 } p=p->nextarc;///不然的话,即如果说该点已经被遍历过了,就让p指针后移 } } void Bfs(ALGraph G,VertexType x)///按广度非递归优先遍历图G { struct { ArcNode *Q[Maxsize]; int front,rear; } QQ; ///队列中存放的是表节点的地址 ArcNode *p; QQ.front=QQ.rear=0;///队列初始化 int k1; for(int i=1; i<=G.vexnum; i++) { if(G.vertices[i].data==x) ///在图中遍历找到元素值为x的点,返回其下标k1 { k1=i; break; } } visited[k1]=1; printf("%c ",G.vertices[k1].data); QQ.rear=(QQ.rear+1)%Maxsize; QQ.Q[QQ.rear]=G.vertices[k1].firstarc; while(QQ.rear!=QQ.front) { QQ.front=(QQ.front+1)%Maxsize; p=QQ.Q[QQ.front]; while(p) { if(visited[p->adjvex]==0)///visited[]中的下标即为每个节点的标号,和图中的下标相对应 { visited[p->adjvex]=1; printf("%c ",G.vertices[p->adjvex].data); QQ.rear=(QQ.rear+1)%Maxsize; QQ.Q[QQ.rear]=G.vertices[p->adjvex].firstarc; } p=p->nextarc; } } } void Output(ALGraph G) { for(int i=1; i<=G.vexnum; i++) { printf("%c ",G.vertices[i].data); ArcNode *pp; pp=G.vertices[i].firstarc; while(pp) { printf("%c ",G.vertices[pp->adjvex].data); pp=pp->nextarc; } printf("\n"); } } void Degree(ALGraph G) { ArcNode *pp=NULL; for(int i=1; i<=G.vexnum; i++) { pp=G.vertices[i].firstarc; while(pp) { indegree[pp->adjvex]++; outdegree[i]++; pp=pp->nextarc; } } } int TopologicalSort(ALGraph G) { int S[Maxsize]; int top=0; for(int i=1; i<=G.vexnum; i++) { if(indegree[i]==0) { top++; S[top]=i; } } int countt=0; int ii=1; ArcNode *pp=NULL; while(top!=0) { ii=S[top]; top--; printf("%d %c ",ii,G.vertices[ii].data); countt++; for(pp=G.vertices[ii].firstarc; pp; pp=pp->nextarc) { int k=pp->adjvex; indegree[k]--; if(indegree[k]==0) { top++; S[top]=k; } } } if(countt<G.vexnum) return -1; else return 1; } int main() { ALGraph G; char chx; Create(G); printf("The Adjacency List is:\n"); Output(G); memset(indegree,0,sizeof(indegree)); memset(outdegree,0,sizeof(outdegree)); Degree(G); cout<<"The List of Indegree:"<<endl; for(int i=1; i<=G.vexnum; i++) { printf("%d ",indegree[i]); } cout<<endl; cout<<"The List of Outdegree:"<<endl; for(int i=1; i<=G.vexnum; i++) { printf("%d ",outdegree[i]); } cout<<endl; int flag=0; printf("The List of Topological are:\n"); flag=TopologicalSort(G); printf("\n"); if(flag==-1) { printf("Can not TopologicalSort!\n"); } else { printf("Topo Over!\n"); } memset(visited,0,sizeof(visited)); printf("Please Input the Start Data of the DFS:\n"); while(scanf(" %c",&chx)!=EOF) { if(chx=='0') break;///当输入起始元素为'0'时,该深度优先遍历结束 printf("The List of Dfs :\n"); Dfs(G,chx); cout<<endl; memset(visited,0,sizeof(visited)); } cout<<"DFS OVER!"<<endl; memset(visited,0,sizeof(visited)); printf("Please Input the Start Data of the BFS:\n"); while(scanf(" %c",&chx)!=EOF) { if(chx=='0') break;///当输入起始元素为'0'时,该广度优先遍历结束 printf("The List of Bfs :\n"); Bfs(G,chx); cout<<endl; memset(visited,0,sizeof(visited)); } cout<<"BFS OVER!"<<endl; return 0; }
///*测试样例 4 4 A B C D A B A D B C D B *///