算法与数据结构--图的实现、基本操作及应用

来源:互联网 发布:软件研发经理 编辑:程序博客网 时间: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
原创粉丝点击