实验九 图的应用

在下列图的应用中选做三项:
⑴求无向连通网的最小生成树;
⑵对有向图进行拓扑排序;
⑶求AOE网的关键路径;
⑷求单源点出发的最短路径。

/*

prim
6  
a 3   1 6  2 1  3 5 
b 3   0 6  2 5  4 3 
c 5   0 1  1 5  3 5  4 6  5 4
d 3   0 5  2 5  5 2
e 3   1 3  2 6  5 6
f 3   2 4  3 2  4 6 

topo

8
a 2  2 1  3 1  
b 1  4 1
c 1  5 1
d 1  6 1
e 1  6 1
f 1  7 1
g 1  7 1
h 0


Dijkstra

6
a 3  5 100  4 30  2 10
b 1  2 5
c 1  3 50
d 1  5 10
e 2  3 20  5 60
f 0
0


*/
#include<bits/stdc++.h>
#include<stack>
#define Maxv 66
//vertex顶点   arc 弧   Adjacency list邻接表 
typedef char ElemType;
int visit[Maxv]; //节点是否访问过  
using namespace std;
int visitcnt=0;//已经访问的个数 

typedef struct nodea{
	int head;
	int tail;
	int weight; 
	struct nodea *next;
}ANode,*ANodep;    //弧 
typedef struct{
	ElemType data;
	ANode *firstarc;
}VNode;    //顶点
typedef struct nodev{
	VNode vexs[Maxv];
	int vexnum;
	int arcnum;
}ALGraph; 


 
void CreateGraph(ALGraph &graph){
	graph.vexnum=0;
	graph.arcnum=0;
	cout<<"创建图模块"<<endl;
	cout<<"请输入图的结点个数t,再输入t行数据(数据 出度 (位置#权重))"<<endl;
	int t;
	cin>>t;//结点个数 
	graph.vexnum=t;
	for(int i=0;i<t;i++){
		char d;
		int n;
		cin>>d>>n;      //数据,出度 
		graph.arcnum+=n;
		graph.vexs[i].data=d;
		ANodep newarc,head,lastp;
		head=(ANodep)malloc(sizeof(ANode));//带头节点 
		head->next=NULL;
		if(!head) exit (-1);
		graph.vexs[i].firstarc=head;
		lastp=head;
		while(n--){
			int out,weight1;
			cin>>out>>weight1;
			ANodep newarc=(ANodep)malloc(sizeof(ANode));
			if(!newarc) exit(-1);
			newarc->head=i;
			lastp->next=newarc;
			newarc->next=NULL; 
			newarc->head=out;
			newarc->weight=weight1;  //默认权重都是1 
			lastp=lastp->next;
		}
	} 
	graph.arcnum/=2;
}

void output(ALGraph graph){
	cout<<"\n输出邻接表"<<endl; 
	for(int i=0;i<graph.vexnum;i++)
	{
		cout<<graph.vexs[i].data<<' ';
		ANodep nowp=graph.vexs[i].firstarc->next;
		while(nowp!=NULL){
			cout<<' '<<nowp->head<<'#'<<nowp->weight;
			nowp=nowp->next;
		}
			
			
		cout<<endl;
	}
	cout<<endl;
}


void prim(ALGraph graph){
	cout<<"最小生成树";
	int dis[Maxv];//记录i点距离已选所有点中的最小距离 
	int link[Maxv] ;//记录 i点最小距离是和 link【i】关联的 
	ALGraph newgraph;
	newgraph.arcnum=0;	
	newgraph.vexnum=graph.vexnum;
	
	for(int i=0;i<graph.vexnum;i++){
		newgraph.vexs[i].data=graph.vexs[i].data;
		ANodep newarc=(ANodep)malloc(sizeof(ANode));
		newgraph.vexs[i].firstarc=newarc;
		newarc->next=NULL;
	}
	
	memset(link,0,sizeof(link));
	memset(dis,0x3f,sizeof(dis));
	//0号顶点已经到位 
	dis[0]=0;
	int vexcnt=1;
	int newv=0;//刚选中的顶点下标 
	while(vexcnt<graph.vexnum){
		ANodep nowarc=graph.vexs[newv].firstarc->next;
		while(nowarc){
			int vexid=nowarc->head;
			if(nowarc->weight<dis[vexid]){
				link[nowarc->head]=newv;
				dis[vexid]=nowarc->weight;
			}
			nowarc=nowarc->next;
		}
		int min=0x3f3f3f3f,minid;
		for(int i=0;i<graph.vexnum;i++){
			if(dis[i]<min && dis[i]!=0 ){
				min=dis[i];
				minid=i;
			}
		}
		//找到了需要加入的点的下标minid,另一个是link[mindid] 
		ANodep linkp1=newgraph.vexs[minid].firstarc; 
		ANodep linkp2=newgraph.vexs[link[minid]].firstarc;  
		newgraph.arcnum+=2;	
		ANodep newarc1,newarc2;
		while(linkp1->next) linkp1=linkp1->next;
		while(linkp2->next) linkp2=linkp2->next;
		//找到了要插入的位置
		 newarc1=(ANodep)malloc(sizeof(ANode));
		 newarc2=(ANodep)malloc(sizeof(ANode));
		 newarc1->next=NULL;
		 newarc2->next=NULL;
		 newarc1->head=link[minid];
		 newarc1->weight=dis[minid];
		 newarc2->head=minid;
		 newarc2->weight=dis[minid];
		 dis[minid]=0;
		 linkp1->next=newarc1;
		 linkp2->next=newarc2;
		 vexcnt++;
		 newv=minid;
	} 
	output(newgraph);
	
}
	
void topo(ALGraph graph){
	cout<<"拓扑排序"<<endl; 
	
	int numarc[Maxv];//记录某个点的入度 
	memset(numarc,0,sizeof(numarc));
	
	for(int i=0;i<graph.vexnum;i++){
		ANodep newarc;
		newarc=graph.vexs[i].firstarc->next;
		while(newarc){
			numarc[newarc->head]++;
			newarc=newarc->next;
		
		}
	}
	int cnt=0;
	while(cnt<graph.vexnum){
		int k;
		for(k=0;k<graph.vexnum;k++){
			if(numarc[k]==0) break;
		}
		numarc[k]=0x3f3f3f3f;
		//找到入度为0的点k
		cout<<graph.vexs[k].data<<' ';
		ANodep newarcs;
		newarcs=graph.vexs[k].firstarc->next;//用于减少的入度 
		cnt++;
		 while(newarcs){
		 	numarc[newarcs->head]--;
		 	newarcs=newarcs->next;
		 }
	}
	cout<<endl;
}
	
void Dijkstra(ALGraph graph){
	int path[Maxv];
	memset(path,-1,sizeof(path));
	
	
	cout<<"最短路径"<<endl;
	cout<<"请输入起点下标" <<endl;
	int start;
	cin>>start;
	int initial=start;
	bool collected[Maxv];
	int dis[Maxv];
	memset(dis,0x3f,sizeof(dis)); 
	memset(collected,0,sizeof(collected));
	//全都没有选中;
	collected[start]=1;
	//选中起点;
	 dis[start]=0;
	 int cnt=1,j;
	 
	 while(cnt<graph.vexnum){
	 	ANodep newarc=graph.vexs[start].firstarc->next;
	 	while(newarc){
	 		if(dis[newarc->head]>dis[start]+newarc->weight){
	 			dis[newarc->head]=dis[start]+newarc->weight;
				path[newarc->head]=start; 
			 }
	 		
	 		newarc=newarc->next;
		 }
		int min=0x3f3f3f3f+1,minid;
	 	for(j=0;j<graph.vexnum;j++){//j是寻找的点的下标 
	 		if(dis[j]<min && collected[j]==0){
	 			min=dis[j];	
				 minid=j;		 
		    }
		 }//此时要加入的点时  minid,值为min 
		 collected[minid]=1;
		 start=minid;
		 cnt++;
	 }
	 //输出 
	 for(int i=0;i<graph.vexnum;i++){
	 	stack<int> st;
	 	if(dis[i]>=0x3f3f3f3f)
	 		cout<<"起点 "<<graph.vexs[initial].data<<" 到点 "<<graph.vexs[i].data<<" 不连通"<<endl;
	 	else 
	 	{
	 	cout<<"起点 "<<graph.vexs[initial].data<<" 到点 "<<graph.vexs[i].data<<" 的最短距离是  "<<dis[i]<<endl;
	 	st.push(i);
	 	int k=i;
		while(path[k]!=-1){
			st.push(path[k]);
			k=path[k];
		}
		cout<<" 路径是";
		while(!st.empty()){
			int pathi=st.top();
			cout<<" "<<graph.vexs[pathi].data;
			st.pop();
		}	
		cout<<endl;
		 }
	 	
	 }
}



int main()
{
	ALGraph graph;
	CreateGraph(graph);
	prim(graph);  

	CreateGraph(graph);
	topo(graph); 
	
	CreateGraph(graph);
	Dijkstra(graph);
	return 0; 
	
}
	
	

猜你喜欢

转载自blog.csdn.net/weixin_44532671/article/details/92353423