算法与数据结构--图的实现、基本操作及应用
来源:互联网 发布:软件研发经理 编辑:程序博客网 时间:2024/05/08 07:16
#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);}
3 0
- 算法与数据结构--图的实现、基本操作及应用
- [数据结构与算法分析] 单链表基本操作的实现
- 《数据结构与算法》-单链表基本操作的C语言实现
- 算法与数据结构-堆的基本操作C语言实现
- 算法与数据结构-队列的基本操作C语言实现
- 算法与数据结构-栈的基本操作C语言实现
- 算法与数据结构-堆的基本操作C语言实现
- 数据结构 P62-62 算法实现 单链队列的创建及基本操作
- 数据结构串的基本操作及KMP算法
- 算法与数据结构-单向链表的基本操作C语言实现
- 算法与数据结构-二叉树的基本操作C语言实现
- 图的基本数据结构及算法汇总
- 数据结构 图的基本操作实现
- 数据结构 — 二叉树的基本操作实现(递归算法)
- 数据结构 P46-47 算法实现 顺序栈的基本操作
- 字典树的数据结构及基本算法的实现
- 新手学习数据结构与算法---单链表的基本操作
- 数据结构与算法系列-串-串的基本操作
- 复制-粘贴功能
- 经纬财富:泸州现货白银风险大吗
- 关于写入Windows Log Event却没有任何记录的问题
- 便携式医疗电子装置的设计考虑
- opengl学习笔记
- 算法与数据结构--图的实现、基本操作及应用
- hibernate helloworld
- 为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?
- 检查字符是否是整数,如果是,返回其整数值
- Android代码工具集——将输入流转换成字节数组
- 主持人
- ubuntu unity 左侧长条添加新启动
- Android代码工具集——网络Post请求
- mysql随机取数据,如何实现高效率?