zoukankan      html  css  js  c++  java
  • 算法与数据结构--图的实现、基本操作及应用

    #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<<"
    ";
    	cout<<"  ***************图的基本操作及应用******************
    ";
    	cout<<"  *  1 无向图的基本操作及应用                      *
    ";
    	cout<<"  *  2 有向图的基本操作及应用                      *
    ";
        cout<<"  *  3 无向网的基本操作及应用                      *
    ";
    	cout<<"  *  4 有向网的基本操作及应用                      *
    ";
    	cout<<"  *  5 退出                                        *
    ";
    	cout<<"  ***************************************************
    ";
    }
    /*
    *无向图的函数集
    */
    //创建无向图的邻接矩阵
    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<<"
    ";
    		cout<<"  ***************无向图的基本操作及应用***************
    ";
    	    cout<<"  *  1 创建无向图的邻接矩阵                         *
    ";
    		cout<<"  *  2 创建无向图的邻接表                           *
    ";
    	    cout<<"  *  3 无向图的深度优先遍历                         *
    ";
    	    cout<<"  *  4 无向图的广度优先遍历                         *
    ";
    		cout<<"  *  5 退出                                         *
    ";
    	    cout<<"  ****************************************************
    ";
    		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<<"错误。又一次输入
    ";
    		}
    	}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<<"
    ";
    		cout<<"  ***************有向图的基本操作及应用***************
    ";
    	    cout<<"  *  1 创建有向图的邻接矩阵                         *
    ";
    		cout<<"  *  2 创建有向图的邻接表                           *
    ";
    	    cout<<"  *  3 拓扑排序                                     *
    ";
    		cout<<"  *  4 退出                                         *
    ";
    	    cout<<"  ****************************************************
    ";
    		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<<"错误,又一次输入
    ";
    		}
    	}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<<"
    ";
    		cout<<"  ***************无向网的基本操作及应用***************
    ";
    	    cout<<"  *  1 创建无向网的邻接矩阵                         *
    ";
    		cout<<"  *  2 创建无向网的邻接表                           *
    ";
    	    cout<<"  *  3 prim算法求最小生成树                         *
    ";
    		cout<<"  *  4 kruskal算法求最小生成树                      *
    ";
    		cout<<"  *  5 退出                                         *
    ";
    	    cout<<"  ****************************************************
    ";
    		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<<"错误,又一次输入
    ";
    		}
    	}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<<"
    ";
    		cout<<"  ***************有向网的基本操作及应用***************
    ";
    	    cout<<"  *  1 创建有向网的邻接矩阵                         *
    ";
    		cout<<"  *  2 创建有向网的邻接表                           *
    ";
    	    cout<<"  *  3 关键路径                                     *
    ";
    		cout<<"  *  4 单源顶点最短路径问题                         *
    ";
    		cout<<"  *  5 退出                                         *
    ";
    	    cout<<"  ****************************************************
    ";
    		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<<"错误,又一次输入
    ";
    		}
    	}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<<"错误,又一次输入
    ";
    		}
    	}while(n!=5);
    }


  • 相关阅读:
    了解 DICOM 基本协议与其相关
    C# PropertyInfo 反射实体部分字段
    ref(引用参数) 和 out(输出参数) 区别
    Linq Where Expression<Func<T,bool>> 查询条件
    随笔规范
    C# 集合分析
    C# 几种常用的数据类型
    关于 C# 方法参数的理解
    打算开始写博客了
    有趣的算法、逻辑面试题
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5094762.html
Copyright © 2011-2022 走看看