⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphicdemo.cpp

📁 C语言实现的图的遍历
💻 CPP
字号:
#include"head.h"
//--------------------------------------------------------------------------------
int Main_Menu()
{
	while(1)
	{
		int choicem=3;
		printf("\n");
		printf("	★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");
		printf("   	★                                                          ★\n");
		printf("   	★                  欢迎进入图的遍历演示系统                ★\n");
		printf("   	★                                                          ★\n");
		printf("   	★      本程序以邻接多重表为存储结构,在连通的无向图上实现  ★\n");
		printf("   	★  了连通无向图的深度优先和广度优先遍历。并以用户指定的结  ★\n");
		printf("   	★  点为起点,分别输出每种遍历下的结点访问序列和相应生成树  ★\n");
		printf("   	★  的边集。                                                ★\n");
		printf("   	★                                                          ★\n");
		printf("   	★    姓 名:关 琦    学 号:02D487    班 级:软双212       ★\n");
		printf("   	★                                                          ★\n");
		printf("	★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");
		printf("\n");
		printf("          ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
		printf("          ┃                    1.进入系统                        ┃\n");
		printf("          ┃                    0.退出系统                        ┃\n");
		printf("          ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
		printf("           请选择: ");
		scanf("%d",&choicem);
		fflush(stdin);
		switch(choicem)
		{
		case 1: AML_Menu();break;
		case 0:return choicem;
		default:{
					printf("	   输入有误,请重试。\n\n");
				}
		}//switch
	}//while
}
//--------------------------------------------------------------------------------
void main()
{
	int choice;
	while(1)
	{
		choice=Main_Menu();
		if(choice==0)break;
	}
	Dty_Gam(g);					//销毁图
	printf("\n	   谢谢您的光顾,欢迎下次再来!\n\n");
	system("PAUSE");
}

//销毁图函数-----------------------------------------------------------------
void Dty_Gam(AMGraph &g)
{
	NextEdge *p1,*p2;
	int j;
	for(int i=0; i<g.VexNum;i++)
	{ 
		while(g.Adjmulist[i].Edge)       
		{
			p2=g.Adjmulist[i].Edge;
			if(i==p2->Vertex1)
				j=p2->Vertex2;
			else j=p2->Vertex1;
			p1=g.Adjmulist[j].Edge;
			while(p1!=p2 && p1->Edge2!=p2 && p1->Edge1!=p2)
			{
				if(p1->Vertex2==j)
					p1=p1->Edge2;
				else p1=p1->Edge1;
			}
			if(p2->Vertex1==i)
				g.Adjmulist[i].Edge=p2->Edge1;
			else g.Adjmulist[i].Edge=p2->Edge2;
			
			if(p1==p2)
			{
				if(p2->Vertex1==j)
					g.Adjmulist[j].Edge=p2->Edge1;
				else g.Adjmulist[j].Edge=p2->Edge2;
			}
			else                                
			{                                 
				if(p1->Vertex2 == j)
				{
					if(p2->Vertex2==j)
						p1->Edge2=p2->Edge2;
					else p1->Edge2=p2->Edge1;
				}
				else
				{
					if(p2->Vertex2==j)
						p1->Edge1=p2->Edge2;
					else p1->Edge1=p2->Edge1;
				}
			}
			delete p2;    
		}
	}
}

//邻接表菜单------------------------------------------------------------------
void AML_Menu()
{
	while(1)
	{
		int choice=5;
		printf("			        邻接多重表演示\n");
		printf("          ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
		printf("          ┃                   1.生成邻接多重表                   ┃\n");
		printf("          ┃                   2.深度优先遍历                     ┃\n");
		printf("          ┃                   3.广度优先遍历                     ┃\n");
		printf("          ┃                   4.从北京到广州不经郑州             ┃\n");
		printf("          ┃                   0.退出系统                         ┃\n");
		printf("          ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
		printf("           请选择: ");
		scanf("%d",&choice);
		fflush(stdin);
		if(choice==0) break;
		switch(choice)
		{
		case 1: Init_AMnu();break;
		case 2: DFS_AMnu(g);break;
		case 3: BFS_AMnu(g);break;
		case 4: Path_AMnu(g,0);break;
		default:{
					printf("	   输入错误选项,请重试。\n\n");
				}
		}
	}
}

//初始化菜单-------------------------------------------------------------------
void Init_AMnu()
{
	char file[15];
	FILE *fp;
	if(state)
	{
		printf("	   图已生成,请继续其他操作.\n\n");
		return;
	}
	printf("	   请输入包含生成图信息的文件名(如:123.txt):");
	scanf("%s",file);
	if(strlen(file)==0||strlen(file)>15)
	{
		printf("	   请更改文件名为15位之内。\n\n");
		return;
	}
	if((fp=fopen(file,"r"))==NULL)
	{
		printf("	   数据文件不存在!\n\n");
		return;
	}
	else
	{
		Init_Gam(g);
		Creat_Gam(g,fp);		//调用生成图函数
		state=true;
	}
	fclose(fp);
}

//图初始化函数------------------------------------------------------------------
void Init_Gam(AMGraph &g)
{
	int i;
	//初始化邻接多重表,表示一个空的图。
	g.VexNum=0 ;
	g.EdgeNum=0 ;
	//全局变量初始化
	for(i=0;i<=VertexMax;i++)
		Visited[i]=0;			//初始化访问数组
	for(i=0;i<=60;i++)
		TreeEdge[i]=30;			//初始化边集数组
}

//生成图函数------------------------------------------------------------------
void Creat_Gam(AMGraph &g,FILE *fp)
{
	fscanf(fp,"%d,%d",&g.VexNum,&g.EdgeNum);
	printf("\n	   ------------------<生成连通无向图>------------------\n");
	printf("\n	   [顶点数]  %d, [边数]  %d\n\n",g.VexNum,g.EdgeNum);			//打印顶点数和边数
	printf("	   <顶点信息>\n");
	for(int i=0;i<g.VexNum;i++)
	{
		fscanf(fp,"%d.%s",&g.Adjmulist[i].id,&g.Adjmulist[i].data);
		printf("[%2d] %s\t",g.Adjmulist[i].id,g.Adjmulist[i].data);
		g.Adjmulist[i].Edge=NULL;
	}
	printf("\n\n	   <边信息>\n\n");
	printf("	   <边序>\t\t <两端顶点>\t\t<路程(公里)>\n");
	for(int k=0;k<g.EdgeNum;k++)
	{
		int v1,v2,len;
		fscanf(fp,"%d,%d,%d",&v1,&v2,&len);
		printf("	   [%2d]\t\t	%s , %s\t\t%8d\n",k+1,g.Adjmulist[v1].data,g.Adjmulist[v2].data,len);
		//建立无向连通图
		NextEdge *pointer=new  NextEdge;
		pointer->Vertex1=v1;
		pointer->Vertex2=v2;
		pointer->length=len;
		pointer->Edge1=g.Adjmulist[v1].Edge;
		pointer->Edge2=g.Adjmulist[v2].Edge;
		pointer->Mark=false;
		g.Adjmulist[v1].Edge=pointer;
		g.Adjmulist[v2].Edge=pointer;
	}
	printf("\n\n");
}

//深度遍历菜单------------------------------------------------------------------------------------
void DFS_AMnu(AMGraph g)
{
	int vnum;
	int i=1;
	if(!state)
	{
		printf("\n	   请先进行生成邻接多重表操作!\n\n");
		return;
	}
	while(1)
	{
		printf("\n	   请指定深度优先遍历的起点(编号):");
		scanf("%d",&vnum);
		if(vnum<0||vnum>=g.VexNum)
		{
			printf("	   起点不存在,请重试!\n\n");
			return;
		}
		else break;	
	}
	printf("\n从 [%s] 深度优先遍历顺序如下:\n\n",g.Adjmulist[vnum].data);
	printf("[Begin]==>");
	DFS_Gam(g,vnum,Visited);			//调用深度遍历函数进行遍历
	printf("[End]\n\n");
	printf("生成树的边为:\n");
	printf("<Begin>\n");
	for(int p=0;p<(g.VexNum-1)*2;p=p+2)	//打印边集数组中的边顶点
		printf("<%s,%s>\t",g.Adjmulist[TreeEdge[p]].data,g.Adjmulist[TreeEdge[p+1]].data);
	printf("\n<End>\n\n");
	//全局变量重新初始化
	for(i=0;i<g.VexNum;i++)
		Visited[i]=0;
	for(i=0;i<=60;i++)
		TreeEdge[i]=30;
	index=0;
}

//深度遍历函数------------------------------------------------------------------------
void DFS_Gam(AMGraph g,int vnum,int Visited[])
{
	NextEdge *Pointer;						
	Visited[vnum]=1;						//顶点vnum已查找
	Pointer=g.Adjmulist[vnum].Edge;
	printf("%s==>",g.Adjmulist[vnum].data);
	while(Pointer!=NULL)
	{
		if(Pointer->Vertex1==vnum&&!Visited[Pointer->Vertex2])
		{
			TreeEdge[index++]=Pointer->Vertex1;			//将边的顶点录入边集数组中
			TreeEdge[index++]=Pointer->Vertex2;
			DFS_Gam(g,Pointer->Vertex2,Visited);		//递归,对终点进行深度遍历
		}
		if(Pointer->Vertex2==vnum&&!Visited[Pointer->Vertex1])
		{
			TreeEdge[index++]=Pointer->Vertex2;			//将边的顶点录入边集数组中
			TreeEdge[index++]=Pointer->Vertex1;
			DFS_Gam(g,Pointer->Vertex1,Visited);		//递归,对起点进行深度遍历
		}
		if(Pointer->Vertex1==vnum) Pointer=Pointer->Edge1;
		else Pointer=Pointer->Edge2;
	}
}

//广度遍历菜单-----------------------------------------------------------------------------------------
void BFS_AMnu(AMGraph g)
{
	int vnum;
	int i=1;
	if(!state)
	{
		printf("\n	   请先进行生成邻接多重表操作!\n\n");
		return;
	}
	while(1)
	{
		printf("\n	   请指定广度优先遍历的起点(编号):");
		scanf("%d",&vnum);
		if(vnum<0||vnum>=g.VexNum)
		{
			printf("	   起点不存在,请重试!\n\n");
			return;
		}
		else break;
	}
	printf("\n从 [%s] 广度优先遍历顺序如下:\n\n",g.Adjmulist[vnum].data);
	printf("[Begin]==>");
	BFS_Gam(g,vnum,Visited);					//调用广度遍历函数进行遍历
	printf("[End]\n\n");	
	printf("生成树的边为:\n");
	printf("<Begin>\n");
	for(int p=0;p<(g.VexNum-1)*2;p=p+2)			//将边集数组中的边顶点打印
		printf("<%s,%s>\t",g.Adjmulist[TreeEdge[p]].data,g.Adjmulist[TreeEdge[p+1]].data);
	printf("\n<End>\n\n");
	//全局变量初始化
	for(i=0;i<g.VexNum;i++)
		Visited[i]=0;
	for(i=0;i<=60;i++)
		TreeEdge[i]=30;
	index=0;
}

//广度遍历函数-----------------------------------------------------------------------
void BFS_Gam(AMGraph g,int vnum,int Visited[])
{
	int num;
	NextEdge *Pointer;			
	Visited[vnum]=1;							//已查找
	printf("%s==>",g.Adjmulist[vnum].data);
	Pointer=g.Adjmulist[vnum].Edge;
	if(Pointer->Vertex1==vnum)
		Enqueue(Pointer->Vertex1);
	else Enqueue(Pointer->Vertex2);
	while(Front!=Rear)							//判断队列是否为空
	{
		vnum=Dequeue();
		Pointer=g.Adjmulist[vnum].Edge;
		while(Pointer!=NULL)
		{
			if(Pointer->Vertex1==vnum)
			{
				num=Pointer->Vertex2;
				Pointer=Pointer->Edge1;
			}
			else 
			{
				num=Pointer->Vertex1;
				Pointer=Pointer->Edge2;
			}
			if(!Visited[num])
			{
				Visited[num]=1;
				printf("%s==>",g.Adjmulist[num].data);		//打印顶点信息
				TreeEdge[index++]=vnum;						//将边的顶点录入边集数组
				TreeEdge[index++]=num;
				Enqueue(num);
			}
		}
	}
}
//入队列操作-------------------------------------------------------
int Enqueue(int Vertex)
{
	if(Rear>=QueueMax)
		return -1;
	else
	{
		Rear++;					//队列尾端指针后移
		Queue[Rear]=Vertex;		//将值存入队列中
		return 1;
	}
}

//出对列操作--------------------------------------------------------
int Dequeue()
{
	if(Front==Rear)
		return -1;
	else
	{
		Front++;				//对头指针后移
		return Queue[Front];	//返回对头指针
	}
}

//北京-广州(不经郑州)菜单---------------------------------------
void Path_AMnu(AMGraph g,int v)
{
	if(!state)
	{
		printf("\n	   请先进行生成邻接多重表操作!\n\n");
		return;
	}
	int index=0;
	printf("\n	   从北京到广州中途不过郑州的所有简单路径:\n\n");
	Path_Gam(g,v);						//调用Path_Gan寻找路径函数
	
}
//北京-广州(不经郑州)寻找路径函数---------------------------------------
void Path_Gam(AMGraph g,int v)
{
	NextEdge *pointer=g.Adjmulist[v].Edge;
	if(v==23)return;					//到达郑州,返回
	for(int j=0 ;j<index; j++)			//判断是否是简单路径
		if(TreeEdge[j]==v)break;
	if(j<index)return;						//如果是返回
	TreeEdge[index++]=v;				//将结点录入边集数组
	if(v==5)							//到达广州,打印
	{
		printf("[Begin]==>");
		for(int i=0; i<index;i++)
			printf("%s==>",g.Adjmulist[TreeEdge[i]].data);
		printf("[End]\n\n");
		printf("[总路程] %4d(公里)\n",length);
		printf("\n");
	}	
	while(pointer!=NULL)
	{		
		if(pointer->Mark==false)
		{	
			pointer->Mark=true;					//记录边为访问
			length+=pointer->length;			//累加路程
			if(pointer->Vertex1==v)
				Path_Gam(g,pointer->Vertex2);	//递归调用
			else				
				Path_Gam(g,pointer->Vertex1);
			length-=pointer->length;			//进行回溯
			pointer->Mark=false;
		}
		if(pointer->Vertex1==v)pointer=pointer->Edge1;
		else pointer=pointer->Edge2;	
	}
	index--;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -