算法与数据结构--图的实现、基本操作及应用
#include<iostream> #include<queue> #include<stack> using namespace std; #define INFINITY DBL_MAX //无穷大 #define MAX_VERTEX_NUM 20 //最大顶点个数 enum GraphKind //图的类型 { DG,DN,UDG,UDN//有向图、有向网、无向图、无向网 }; //弧结构 typedef struct ArcCell { double adj;//权值,无权图用1表示 }AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵图结构 struct MGraph { int vexs[MAX_VERTEX_NUM];//顶点集合 AdjMatrix arecs;//邻接矩阵 int vexnum,arcnum;//顶点数、弧数 GraphKind kind;//图的类型 }; //表节点 struct ArcNode { int adjvex;//弧的顶点位置 ArcNode * nextarc; double adj;//弧的权值 }; //头节点 typedef struct VNode { int data;//顶点序号信息 ArcNode * firstarc; }AdjList[MAX_VERTEX_NUM]; //邻接表 struct ALGraph { int vexs[MAX_VERTEX_NUM];//顶点集合 AdjList vertices; //邻接链表 int vexnum,arcnum;//顶点数、弧数 int kind;//图的类型 }; //显示主菜单 void ShowMainMenu() { cout<<"\n"; cout<<" ***************图的基本操作及应用******************\n"; cout<<" * 1 无向图的基本操作及应用 *\n"; cout<<" * 2 有向图的基本操作及应用 *\n"; cout<<" * 3 无向网的基本操作及应用 *\n"; cout<<" * 4 有向网的基本操作及应用 *\n"; cout<<" * 5 退出 *\n"; cout<<" ***************************************************\n"; } /* *无向图的函数集 */ //创建无向图的邻接矩阵 bool CreatUDG_M(MGraph & MG) { MG.kind = UDG; cout<<"请输入该无向图的顶点个数、弧的条数:"<<endl; cin>>MG.vexnum>>MG.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<MG.vexnum;i++) cin>>MG.vexs[i]; //初始化邻接矩阵 for(int i = 0;i<MG.vexnum;i++) { for(int j = 0;j<MG.vexnum;j++) { MG.arecs[i][j].adj = INFINITY; } } //构造邻接矩阵 for(int i = 0;i<MG.arcnum;i++) { int v1,v2; cout<<"依次输入弧的两个顶点序号:"<<endl; cin>>v1>>v2; int *p1 = find(MG.vexs,MG.vexs+MG.vexnum,v1); int *p2 = find(MG.vexs,MG.vexs+MG.vexnum,v2); if(p1==MG.vexs+MG.vexnum||p2==MG.vexs+MG.vexnum) return false; MG.arecs[(p1-MG.vexs)][(p2-MG.vexs)].adj = 1; //无向图的邻接矩阵是对称矩阵 MG.arecs[(p2-MG.vexs)][(p1-MG.vexs)].adj = 1; } //输出该邻接矩阵 cout<<"该邻接矩阵为(-1代表无穷大):"<<endl; for(int i = 0;i<MG.vexnum;i++) { for(int j = 0;j<MG.vexnum;j++) { if(MG.arecs[i][j].adj==INFINITY) cout<<"∞ "; else { cout<<MG.arecs[i][j].adj<<" "; } } cout<<endl; } return true; } //创建无向图的邻接表 bool CreatUDG_ALG(ALGraph & ALG) { ALG.kind = UDG; cout<<"请输入该无向图的顶点个数、弧的条数:"<<endl; cin>>ALG.vexnum>>ALG.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<ALG.vexnum;i++) cin>>ALG.vexs[i]; //构造邻接表 for(int i = 0;i<ALG.vexnum;i++) { //初始化头结点的data信息 ALG.vertices[i].data = ALG.vexs[i]; ALG.vertices[i].firstarc = 0; //循环输入该头结点的邻接弧 cout<<"输入与序号为"<<ALG.vexs[i]<<"节点相邻的节点序号"<<endl; int v1; ArcNode * rp = ALG.vertices[i].firstarc; while (cin>>v1) { int *p1 = find(ALG.vexs,ALG.vexs+ALG.vexnum,v1); if(p1==ALG.vexs+ALG.vexnum)return false; ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode)); if(!pA) return false; pA->adj = 1; pA->adjvex = p1-ALG.vexs; pA->nextarc = 0; if(0==ALG.vertices[i].firstarc) {ALG.vertices[i].firstarc = pA; rp = pA;} else{rp->nextarc = pA; rp = pA;} } cin.clear();//清空输入流 } //输出邻接表 for(int i = 0;i<ALG.vexnum;i++) { cout<<"'"<<ALG.vexs[i]<<"'"; for(ArcNode * rp = ALG.vertices[i].firstarc;rp!=0;rp = rp->nextarc) { cout<<"--->"<<(*rp).adjvex; } cout<<endl; } return true; } //无向图的深度优先遍历 void Visit_fun(int & t) { t++; } void UDG_DFS(ALGraph &ALG,int v,bool visited[],void(*visit)(int& t)) { visited[v] = true;visit(ALG.vexs[v]); for(ArcNode * rp = ALG.vertices[v].firstarc;rp!=0;rp = rp->nextarc) { if(!visited[(*rp).adjvex]) UDG_DFS(ALG,(*rp).adjvex,visited,visit); } } void UDG_DFSTraverse(ALGraph &ALG,void(*visit)(int &t)) { bool *visited = new bool[ALG.vexnum]; for(int i = 0;i<ALG.vexnum;i++) visited[i] = false; for(int i = 0;i<ALG.vexnum;i++) { if(!visited[i]) UDG_DFS(ALG,i,visited,visit); } //測试数据序号是否都被改动 cout<<"測试结果(遍历每一个节点,并将节点的序号加一):"<<endl; for(int i = 0;i<ALG.vexnum;i++) { cout<<ALG.vexs[i]<<" "<<endl; } } //无向图的广度优先遍历 void UDG_BFSTraverse(ALGraph &ALG,void(*visit)(int &t)) { //辅助訪问数组 bool *visited = new bool[ALG.vexnum]; for(int i = 0;i<ALG.vexnum;i++) visited[i] = false; //辅助队列 queue<int> Queue; for(int i= 0;i<ALG.vexnum;i++) { if(!visited[i]) { visited[i] = true; //先訪问再如队列 visit(ALG.vexs[i]); Queue.push(i); while (!Queue.empty()) { int v = Queue.front();//出队 Queue.pop(); for(ArcNode * rp = ALG.vertices[v].firstarc;rp!=0;rp = rp->nextarc) { if(!visited[(*rp).adjvex]) { visited[(*rp).adjvex] = true; visit(ALG.vexs[(*rp).adjvex]); Queue.push((*rp).adjvex); } } } } } //測试数据序号是否都被改动 cout<<"測试结果(遍历每一个节点,并将节点的序号加一):"<<endl; for(int i = 0;i<ALG.vexnum;i++) { cout<<ALG.vexs[i]<<" "<<endl; } } //无向图操作菜单 void UndirectedGraph() { MGraph MG; ALGraph ALG; int n; do { cout<<"\n"; cout<<" ***************无向图的基本操作及应用***************\n"; cout<<" * 1 创建无向图的邻接矩阵 *\n"; cout<<" * 2 创建无向图的邻接表 *\n"; cout<<" * 3 无向图的深度优先遍历 *\n"; cout<<" * 4 无向图的广度优先遍历 *\n"; cout<<" * 5 退出 *\n"; cout<<" ****************************************************\n"; cin>>n; switch(n){ case 1: CreatUDG_M(MG); break; case 2: CreatUDG_ALG(ALG); break; case 3: UDG_DFSTraverse(ALG,Visit_fun); break; case 4: UDG_BFSTraverse(ALG,Visit_fun); break; default: if (n!=5) cout<<"错误。又一次输入\n"; } }while(n!=5); } /* *有向图的函数集 */ //创建有向图的邻接矩阵 bool CreatDG_M(MGraph& MDG) { MDG.kind = DG; cout<<"请输入该有向图的顶点个数、弧的条数:"<<endl; cin>>MDG.vexnum>>MDG.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<MDG.vexnum;i++) cin>>MDG.vexs[i]; //初始化邻接矩阵 for(int i = 0;i<MDG.vexnum;i++) { for(int j = 0;j<MDG.vexnum;j++) { MDG.arecs[i][j].adj = INFINITY; } } //构造邻接矩阵 for(int i = 0;i<MDG.arcnum;i++) { int v1,v2; cout<<"依次输入弧的弧尾序号、弧头序号:"<<endl; cin>>v1>>v2; int *p1 = find(MDG.vexs,MDG.vexs+MDG.vexnum,v1); int *p2 = find(MDG.vexs,MDG.vexs+MDG.vexnum,v2); if(p1==MDG.vexs+MDG.vexnum||p2==MDG.vexs+MDG.vexnum) return false; MDG.arecs[(p1-MDG.vexs)][(p2-MDG.vexs)].adj = 1; } //输出该邻接矩阵 cout<<"该邻接矩阵为:"<<endl; for(int i = 0;i<MDG.vexnum;i++) { for(int j = 0;j<MDG.vexnum;j++) { if(MDG.arecs[i][j].adj==INFINITY) cout<<"∞ "; else { cout<<MDG.arecs[i][j].adj<<" "; } } cout<<endl; } return true; } //创建有向图的邻接表 bool CreatDG_ALG(ALGraph & ALDG) { ALDG.kind = DG; cout<<"请输入该有向图的顶点个数、弧的条数:"<<endl; cin>>ALDG.vexnum>>ALDG.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<ALDG.vexnum;i++) cin>>ALDG.vexs[i]; //构造邻接表 for(int i = 0;i<ALDG.vexnum;i++) { //初始化头结点的data信息 ALDG.vertices[i].data = ALDG.vexs[i]; ALDG.vertices[i].firstarc = 0; //循环输入该头结点的邻接弧 cout<<"输入以序号为"<<ALDG.vexs[i]<<"节点为弧尾的弧头节点序号"<<endl; int v1; ArcNode * rp = ALDG.vertices[i].firstarc; while (cin>>v1) { int *p1 = find(ALDG.vexs,ALDG.vexs+ALDG.vexnum,v1); if(p1==ALDG.vexs+ALDG.vexnum)return false; ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode)); if(!pA) return false; pA->adj = 1; pA->adjvex = p1-ALDG.vexs; pA->nextarc = 0; if(0==ALDG.vertices[i].firstarc) {ALDG.vertices[i].firstarc = pA; rp = pA;} else{rp->nextarc = pA; rp = pA;} } cin.clear();//清空输入流 } //输出邻接表 for(int i = 0;i<ALDG.vexnum;i++) { cout<<"'"<<ALDG.vexs[i]<<"'"; for(ArcNode * rp = ALDG.vertices[i].firstarc;rp!=0;rp = rp->nextarc) { cout<<"--->"<<(*rp).adjvex; } cout<<endl; } return true; } //拓扑排序 bool TopologicalSort(ALGraph & ALDG) { //入度数组 int *indegree = new int[ALDG.vexnum]; //初始化入度数组 for(int i = 0;i<ALDG.vexnum;i++) { int re= 0; for(int j = 0;j<ALDG.vexnum;j++) { if(j!=i)//查找入度 { for(ArcNode * rp = ALDG.vertices[j].firstarc;rp!=0;rp = rp->nextarc) { if((*rp).adjvex==i) re++; } } } indegree[i] = re; } //保存入度为0的栈 stack<int> Stack; for(int i = 0;i<ALDG.vexnum;i++) { if(0==indegree[i]) Stack.push(i); } int count = 0;//记录输出节点的个数 while (!Stack.empty()) { int v = Stack.top();//出栈 Stack.pop(); count++; //输出 cout<<ALDG.vexs[v]<<" "; for(ArcNode * rp = ALDG.vertices[v].firstarc;rp!=0;rp = rp->nextarc) { --indegree[(*rp).adjvex]; if(0==indegree[(*rp).adjvex]) Stack.push((*rp).adjvex); } } if(count<ALDG.vexnum) { return false; } return true; } //有向图操作菜单 void DirectedGraph () { MGraph MDG;//有向图邻接矩阵 ALGraph ALDG;//有向图邻接表 int n; do { cout<<"\n"; cout<<" ***************有向图的基本操作及应用***************\n"; cout<<" * 1 创建有向图的邻接矩阵 *\n"; cout<<" * 2 创建有向图的邻接表 *\n"; cout<<" * 3 拓扑排序 *\n"; cout<<" * 4 退出 *\n"; cout<<" ****************************************************\n"; cin>>n; switch(n){ case 1: CreatDG_M(MDG); break; case 2: CreatDG_ALG(ALDG); break; case 3: TopologicalSort(ALDG); break; default: if (n!=4) cout<<"错误,又一次输入\n"; } }while(n!=4); } /* *无向网的函数集 */ //创建无向网的邻接矩阵 bool CreatUDN_M(MGraph &MG) { MG.kind = UDN; cout<<"请输入该无向网的顶点个数、弧的条数:"<<endl; cin>>MG.vexnum>>MG.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<MG.vexnum;i++) cin>>MG.vexs[i]; //初始化邻接矩阵 for(int i = 0;i<MG.vexnum;i++) { for(int j = 0;j<MG.vexnum;j++) { MG.arecs[i][j].adj = INFINITY; } } //构造邻接矩阵 for(int i = 0;i<MG.arcnum;i++) { int v1,v2; double w; cout<<"依次输入弧的两个顶点序号及权值:"<<endl; cin>>v1>>v2>>w; int *p1 = find(MG.vexs,MG.vexs+MG.vexnum,v1); int *p2 = find(MG.vexs,MG.vexs+MG.vexnum,v2); if(p1==MG.vexs+MG.vexnum||p2==MG.vexs+MG.vexnum) return false; MG.arecs[(p1-MG.vexs)][(p2-MG.vexs)].adj = w; //无向图的邻接矩阵是对称矩阵 MG.arecs[(p2-MG.vexs)][(p1-MG.vexs)].adj = w; } //输出该邻接矩阵 cout<<"该邻接矩阵为(-1代表无穷大):"<<endl; for(int i = 0;i<MG.vexnum;i++) { for(int j = 0;j<MG.vexnum;j++) { if(MG.arecs[i][j].adj==INFINITY) cout<<"∞ "; else { cout<<MG.arecs[i][j].adj<<" "; } } cout<<endl; } return true; } //创建无向网的邻接表 bool CreatUDN_ALG(ALGraph &ALN) { ALN.kind = UDN; cout<<"请输入该无向网的顶点个数、弧的条数:"<<endl; cin>>ALN.vexnum>>ALN.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<ALN.vexnum;i++) cin>>ALN.vexs[i]; //构造邻接表 for(int i = 0;i<ALN.vexnum;i++) { //初始化头结点的data信息 ALN.vertices[i].data = ALN.vexs[i]; ALN.vertices[i].firstarc = 0; //循环输入该头结点的邻接弧 cout<<"输入与序号为"<<ALN.vexs[i]<<"节点相邻的节点序号、弧的权值"<<endl; int v1; double w; ArcNode * rp = ALN.vertices[i].firstarc; while (cin>>v1) { cin>>w; int *p1 = find(ALN.vexs,ALN.vexs+ALN.vexnum,v1); if(p1==ALN.vexs+ALN.vexnum)return false; ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode)); if(!pA) return false; pA->adj = w; pA->adjvex = p1-ALN.vexs; pA->nextarc = 0; if(0==ALN.vertices[i].firstarc) {ALN.vertices[i].firstarc = pA; rp = pA;} else{rp->nextarc = pA; rp = pA;} } cin.clear();//清空输入流 } //输出邻接表 for(int i = 0;i<ALN.vexnum;i++) { cout<<"'"<<ALN.vexs[i]<<"'"; for(ArcNode * rp = ALN.vertices[i].firstarc;rp!=0;rp = rp->nextarc) { cout<<"--->"<<(*rp).adjvex; } cout<<endl; } return true; } //prim算法求最小生成树 typedef struct { int adjvex;//顶点序号 double lowcost;//最短距离 }Closedge[MAX_VERTEX_NUM]; bool MiniSpanTree(MGraph & MN) { Closedge closedge;//记录未选节点到已选节点中最短的距离 int k = 0; //初始化辅组数组 for(int i = 0;i<MN.vexnum;i++) { if(i!=k) {closedge[i].lowcost = MN.arecs[i][k].adj;closedge[i].adjvex = MN.vexs[k];} } closedge[k].lowcost = 0;//标识为已选 for(int i = 1;i<MN.vexnum;i++)//选择其余的n-1个顶点 { //求出未选节点中的最短距离 double low = INFINITY+1; for(int j = 0;j<MN.vexnum;j++) { if((closedge[j].lowcost!=0)&&(closedge[j].lowcost<low)) { k = j; low = closedge[j].lowcost; } } //打印该路线 cout<<MN.vexs[k]<<" "<<closedge[k].adjvex<<" "<<closedge[k].lowcost<<endl; //标识为已选 closedge[k].lowcost = 0; //更新最短距离 for(int j = 0;j<MN.vexnum;j++) { if(closedge[j].lowcost>MN.arecs[j][k].adj) { closedge[j].adjvex =MN.vexs[k]; closedge[j].lowcost = MN.arecs[j][k].adj; } } } return true; } // kruskal算法求最小生成树 void Kruskal(MGraph & MN) { int i,j,k; int n = MN.vexnum; AdjMatrix S;//用来表示连通关系 AdjMatrix Q;//表示节点之间的权值 //初始化 for(i=0;i<n;i++) for(j=0;j<n;j++){ if(i==j) S[i][j].adj=1; else S[i][j].adj=0; Q[i][j].adj = MN.arecs[i][j].adj; } k=1; while(k<n) { //找到权值最小的边 double low = INFINITY+1; int Begin,End; for(i=0;i<n;i++) for(j=0;j<n;j++){ if(Q[i][j].adj<low) { Begin = i; End = j; low = Q[i][j].adj; } } Q[Begin][End].adj = INFINITY;//归无穷 if(0==S[Begin][End].adj) { cout<<MN.vexs[Begin]<<"---"<<MN.vexs[End]<<" "<<MN.arecs[Begin][End].adj<<endl; k++; //更新全局的连通关系 for(i = 0;i<n;i++) { if(S[Begin][i].adj!=0) { S[End][i].adj = S[i][End].adj = 1; //更新相连分支 for(int j = 0;j<n;j++) { if(S[End][j].adj!=0) { S[j][i].adj = S[i][j].adj = 1; } } } } for(i = 0;i<n;i++) { if(S[End][i].adj!=0) { S[Begin][i].adj = S[i][Begin].adj = 1; //更新相连分支 for(int j = 0;j<n;j++) { if(S[Begin][j].adj!=0) { S[j][i].adj = S[i][j].adj = 1; } } } } }//if }//while } //无向网操作菜单 void IndirectedNet() { MGraph MN; ALGraph ALN; int n; do{ cout<<"\n"; cout<<" ***************无向网的基本操作及应用***************\n"; cout<<" * 1 创建无向网的邻接矩阵 *\n"; cout<<" * 2 创建无向网的邻接表 *\n"; cout<<" * 3 prim算法求最小生成树 *\n"; cout<<" * 4 kruskal算法求最小生成树 *\n"; cout<<" * 5 退出 *\n"; cout<<" ****************************************************\n"; cin>>n; switch(n){ case 1: CreatUDN_M(MN); break; case 2: CreatUDN_ALG(ALN); break; case 3: MiniSpanTree(MN); break; case 4: Kruskal(MN); break; default: if (n!=5) cout<<"错误,又一次输入\n"; } }while(n!=5); } /* *有向网的函数集 */ //创建有向网的邻接矩阵 bool CreatDN_M(MGraph &MDN ) { MDN.kind = DG; cout<<"请输入该有向网的顶点个数、弧的条数:"<<endl; cin>>MDN.vexnum>>MDN.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<MDN.vexnum;i++) cin>>MDN.vexs[i]; //初始化邻接矩阵 for(int i = 0;i<MDN.vexnum;i++) { for(int j = 0;j<MDN.vexnum;j++) { MDN.arecs[i][j].adj = INFINITY; } } //构造邻接矩阵 for(int i = 0;i<MDN.arcnum;i++) { int v1,v2; double w; cout<<"依次输入弧的弧尾序号、弧头序号、权值:"<<endl; cin>>v1>>v2>>w; int *p1 = find(MDN.vexs,MDN.vexs+MDN.vexnum,v1); int *p2 = find(MDN.vexs,MDN.vexs+MDN.vexnum,v2); if(p1==MDN.vexs+MDN.vexnum||p2==MDN.vexs+MDN.vexnum) return false; MDN.arecs[(p1-MDN.vexs)][(p2-MDN.vexs)].adj = w; } //输出该邻接矩阵 cout<<"该邻接矩阵为:"<<endl; for(int i = 0;i<MDN.vexnum;i++) { for(int j = 0;j<MDN.vexnum;j++) { if(MDN.arecs[i][j].adj==INFINITY) cout<<"∞ "; else { cout<<MDN.arecs[i][j].adj<<" "; } } cout<<endl; } return true; } //创建有向网的邻接表 bool CreatDN_ALG(ALGraph & ALDN) { ALDN.kind = DG; cout<<"请输入该有向网的顶点个数、弧的条数:"<<endl; cin>>ALDN.vexnum>>ALDN.arcnum; //初始化顶点集合 cout<<"依次输入顶点序号"<<endl; for(int i = 0;i<ALDN.vexnum;i++) cin>>ALDN.vexs[i]; //构造邻接表 for(int i = 0;i<ALDN.vexnum;i++) { //初始化头结点的data信息 ALDN.vertices[i].data = ALDN.vexs[i]; ALDN.vertices[i].firstarc = 0; //循环输入该头结点的邻接弧 cout<<"输入以序号为"<<ALDN.vexs[i]<<"节点为弧尾的弧头节点序号、弧的权值"<<endl; int v1; double w; ArcNode * rp = ALDN.vertices[i].firstarc; while (cin>>v1) { cin>>w; int *p1 = find(ALDN.vexs,ALDN.vexs+ALDN.vexnum,v1); if(p1==ALDN.vexs+ALDN.vexnum)return false; ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode)); if(!pA) return false; pA->adj = w; pA->adjvex = p1-ALDN.vexs; pA->nextarc = 0; if(0==ALDN.vertices[i].firstarc) {ALDN.vertices[i].firstarc = pA; rp = pA;} else{rp->nextarc = pA; rp = pA;} } cin.clear();//清空输入流 } //输出邻接表 for(int i = 0;i<ALDN.vexnum;i++) { cout<<"'"<<ALDN.vexs[i]<<"'"; for(ArcNode * rp = ALDN.vertices[i].firstarc;rp!=0;rp = rp->nextarc) { cout<<"--->"<<(*rp).adjvex; } cout<<endl; } return true; } //关键路径 bool TopologicalOrder(ALGraph & ALDN,stack<int> & T,double ve[] )//T用于保存拓扑排序 { //入度数组 int *indegree = new int[ALDN.vexnum]; //初始化入度数组 for(int i = 0;i<ALDN.vexnum;i++) { int re= 0; for(int j = 0;j<ALDN.vexnum;j++) { if(j!=i)//查找入度 { for(ArcNode * rp = ALDN.vertices[j].firstarc;rp!=0;rp = rp->nextarc) { if((*rp).adjvex==i) re++; } } } indegree[i] = re; } //保存入度为0的栈 //初始化事件最早发生数组 stack<int> Stack; for(int i = 0;i<ALDN.vexnum;i++) { if(0==indegree[i]) Stack.push(i); ve[i] = 0; } int count = 0;//记录输出节点的个数 while (!Stack.empty()) { int v = Stack.top();//出栈 Stack.pop(); count++; T.push(v); for(ArcNode * rp = ALDN.vertices[v].firstarc;rp!=0;rp = rp->nextarc) { --indegree[(*rp).adjvex]; if(0==indegree[(*rp).adjvex]) Stack.push((*rp).adjvex); if(ve[v]+(*rp).adj>ve[(*rp).adjvex]) ve[(*rp).adjvex] = ve[v]+(*rp).adj; } } if(count<ALDN.vexnum) { return false; } return true; } bool CriticalPath(ALGraph & ALDN ) { stack<int> T;//保存拓扑排序 double * ve = new double[ALDN.vexnum];//事件最早发生数组 if(!TopologicalOrder(ALDN,T,ve)) return false; double * vl = new double[ALDN.vexnum];//事件最迟发生数组 //初始化最迟发生数组 for(int i = 0;i<ALDN.vexnum;i++) { vl[i] = ve[T.top()]; } //依照拓扑逆序求各项的最迟发生时间 while(!T.empty()) { int j = T.top(); T.pop(); ArcNode *p = ALDN.vertices[j].firstarc; for(;p!=0;p=p->nextarc) { if((vl[(*p).adjvex]-(*p).adj)<vl[j]) vl[j] = (vl[(*p).adjvex]-(*p).adj); } } //查找关键路径 for(int i = 0;i<ALDN.vexnum;i++) { for(ArcNode *p = ALDN.vertices[i].firstarc;p!=0;p=p->nextarc) { if(ve[i] == (vl[p->adjvex] - p->adj)) { cout<<"* :"<<ALDN.vexs[i]<<"---"<<ALDN.vexs[p->adjvex]<<" :"<<ve[i]<<"<--"<<p->adj<<"-->"<<vl[p->adjvex]<<endl; } } } return true; } //单源顶点最短路径问题 bool ShortestPath(MGraph &MDN,int v0) { AdjMatrix P;//p[v][w]用于记录v0到v点最短路径上的节点 为true则在该最短路径上 double *D = new double[MDN.vexnum];//记录v0到每一点的最短距离 bool *fina = new bool[MDN.vexnum];//记录v0是否已经找到到每一点的最短路径 //初始化參数 for(int i = 0;i<MDN.vexnum;i++) { fina[i] = false; D[i] = MDN.arecs[v0][i].adj; //先把全部路径置空 for(int j = 0;j<MDN.vexnum;j++) P[i][j].adj = 0; if(D[i]<INFINITY) { P[i][v0].adj = 1; P[i][i].adj = 1; } } D[v0] = 0; fina[v0] = true; //为剩下的n-1个节点查找最短距离 for(int i = 1;i<MDN.vexnum;i++) { double min = INFINITY+1;//记录剩下的节点到v0的最短距离 int mV;//记录剩下的节点到v0的最短距离的节点 //找出最短距离 for(int j= 0;j<MDN.vexnum;j++) { if(!fina[j]) { if(D[j]<min) { mV= j; min = D[j]; } } } //mV增加找到最短路径集合 fina[mV] = true; //更新剩下的每一个点到v0的最短距离集合 及 最短路径集合 for(int j= 0;j<MDN.vexnum;j++) { if(!fina[j]&&(min+MDN.arecs[mV][j].adj<D[j])) { D[j] = min+MDN.arecs[mV][j].adj; //更新最短路径集合 for(int a = 0;a<MDN.vexnum;a++) { P[j][a].adj = P[mV][a].adj; } P[j][j].adj = 1; } } } //输出測试数据 for(int j= 0;j<MDN.vexnum;j++) { //先推断是否存在最短路径 if(D[j]==INFINITY) { cout<<MDN.vexs[j]<<" 无"<<endl; } else { //先输出最短路径 cout<<MDN.vexs[j]<<" "; for(int i = 0;i<MDN.vexnum;i++) { if(1==P[j][i].adj) { cout<<MDN.vexs[i]<<" "; } } cout<<"最短距离: "<<D[j]<<endl; } } return true; } //有向网操作菜单 void DirectedNet() { MGraph MDN; ALGraph ALDN; int n; do{ cout<<"\n"; cout<<" ***************有向网的基本操作及应用***************\n"; cout<<" * 1 创建有向网的邻接矩阵 *\n"; cout<<" * 2 创建有向网的邻接表 *\n"; cout<<" * 3 关键路径 *\n"; cout<<" * 4 单源顶点最短路径问题 *\n"; cout<<" * 5 退出 *\n"; cout<<" ****************************************************\n"; cin>>n; switch(n){ case 1: CreatDN_M(MDN); break; case 2: CreatDN_ALG(ALDN); break; case 3: CriticalPath(ALDN); break; case 4: ShortestPath(MDN,0); break; default: if (n!=5) cout<<"错误,又一次输入\n"; } }while(n!=5); } void main() { int n; do{ ShowMainMenu(); cin>>n; switch(n){ case 1: UndirectedGraph(); break; case 2: DirectedGraph(); break; case 3: IndirectedNet(); break; case 4: DirectedNet(); break; default: if (n!=5) cout<<"错误,又一次输入\n"; } }while(n!=5); }