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

📄 最短路径算法.txt

📁 一个用C语言实现的最短路径算法(华南农业大学信息学院计算机系).
💻 TXT
字号:
/*GIS 环境下的最短路径规划算法,此处最短路理解为路径长度最小的路径*/
/*设计人:刘继忠*/
/*学号:2002374117*/
/*建议用C++编译程序编译,若用TURBOC 2.0可能会造成源程序的排版混乱*/

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE -1
#define MAXSIZE 20       /*处理图的最大结点数*/
#define INFINITY 30000   /*允许的节点间的权值的最大值*/
#define ERROR 0
#define SUCCEED 1

typedef struct
{
 int vexs[MAXSIZE];         /*存放图的各顶点数据信息*/
 int arcs[MAXSIZE][MAXSIZE]; /*定义邻接矩阵*/
 int vexnum;
 int arcnum;               /*vexnum为图的顶点数,arcnum为图的边的条数*/
}MGraph;

void Welcome()    /*程序初始化界面,介绍程序的功能、特点及相关提示*/
{
 textmode(C80);
 clrscr();
 textcolor(13);
 cprintf("\nWelcome to shortest path searching system.\r\n\n\n");
 textcolor(10);
 textbackground(1);
 cprintf("                                Instructions                                    \r\n");
 textbackground(0);
 textcolor(11);
 cprintf("Function: \r\n         1. Personal travelling route choosing.\r\n         2. Assistan helper in city's traffic design.\r\n         3. Shortes path choose in the comlicated traffic net of the city.\r\n");
 cprintf("\nCharacteristic:\r\n               It is convient,you could set vital point you must travel,and the\r\n               point you must avoid.\r\n");
 cprintf("\nPrompt:\r\n       If the condition is too secret ,maybe there will have no path available.\r\n") ;
 cprintf("\r\nDesigner: Liu jizhong.\r\nComplate-data: 2004. 3. 21\r\n");
 cprintf("CopyRight: Shared program,welcome to improve it.");
 textcolor(15+128);
 cprintf("\r\n\nPress anykey to enter the program...");
 getch();
}


void CreatGraph(MGraph *G,char buf[])            /*把图用邻接矩阵的形式表示*/
{
 int i,j,k,count;     /*i,j为循环控制变量,count为计数变量*/
 int x,y,ERROR_x;     /*x,y为相应的屏幕控制辅助变量*/
 int dist;            /*dist为相应的边的权值*/
 int temp;   /*temp为零时性中间变量*/
 int flag,flag1,flag2;            /*flag1flag2为标志位变量*/
 textmode(C80);
 clrscr();
 do{
	 textcolor(3);
	 clrscr();
	 textcolor(4);
	 textbackground(10);
	 cprintf("Gather information about the graph:\r\n\n");
	 textbackground(0);
	 textcolor(15);
	 cprintf("Customize codes for the vexs(end up by -1):");    /*为各结点自定义编号*/
	 flag=1;
	 G->vexnum=0;
	 i=0;
	 while(1)   /*循环控制当输入的自定义的结点有重复时,自动撤销输入的该组结点,给出出错提示信息,并要求重新输入*/
	  {
		scanf("%d",&temp);
		if(temp==-1)
		  break;
		G->vexs[i++]=temp;
		G->vexnum++;
		for(j=0;j<G->vexnum-1&&G->vexnum>=2;j++)
		  if(temp==G->vexs[j])
			flag=0;
	   }
	 if(flag==0)
		{
		 textcolor(5);
		 cprintf("ERROR: repetitious code!\r\nPlease check and input again.\r\n");
		 getch();
		}
  }while(!flag);
 if(G->vexnum<=1)  /*当用户自定义的结点数小于2时,给出出错提示信息,并退出程序*/
   {
	textcolor(4);
	cprintf("\r\n\nERROE:the ammount of the node is less than two,the program will terminate!\r\nPress anykey to exit...");
	getch();
	exit(0);
   }

 for(i=0;i<G->vexnum;i++)   /*初始化邻接矩阵*/
   {
	for(j=0;j<G->vexnum;j++)
	  G->arcs[G->vexs[i]][G->vexs[j]]=INFINITY;
   }

 G->arcnum=0;
 count=0;
 textcolor(9);
 clrscr();
 textbackground(10);
 textcolor(4);
 cprintf("Gather information about the graph:\r\n\n");
 textcolor(15);
 textbackground(0);
 cprintf("The code you customized:");
 textcolor(3);
 for(i=0;i<G->vexnum;i++)
	cprintf("%d ",G->vexs[i]);
 textcolor(15);
 cprintf("\r\n\nInput the arcs's vexs and powers(end up by evaluate -1 to jump-off point):\r\n\n");  /*录入有向图的数据信息,各边的起点、终点和边上的权值*/
 textcolor(5);
 cprintf("serial number       jump-off point           end-point          power\r\n");
 while(1)
   {
	while(1)
	  {
	   flag1=flag2=0;    /*用来记录输入各边的起点和终点的合法性*/
	   textcolor(11);
	   if(count<10)
		 cprintf("      %d                  ",count++);
	   else
		 cprintf("     %d                  ",count++);
	   x=wherex();
	   scanf("%d",&i);
	   if(i==-1)       /*用来控制结束信息的输入*/
		 break;
	   gotoxy(x+24, wherey()-1);
	   x=wherex();
	   scanf("%d",&j);
	   gotoxy(x+17,wherey()-1);
	   scanf("%d",&dist);
	   ERROR_x=wherey()-1;
	   for(k=0;k<G->vexnum;k++)
		 {
		  if(i==G->vexs[k])
			flag1=1;
		  if(j==G->vexs[k])
			flag2=1;
		 }
	   if(flag1&&flag2&&dist<INFINITY&&i!=j)   /*当各边的信息合法时接受该组数据信息*/
		 break;
	   else
		 {
		  textcolor(4);
		  if(dist>=INFINITY)  /*当输入边的权值大于程序允许的范围时*/
			cprintf("                  ERROR:The power of the arcs is out of range!\r\n");
		  else
			if(i==j)   /*当图中存在环时*/
			  cprintf("                 ERROE:arc from ome point to itselt is Illegal.\r\n");
			else      /*当输入的边的起点或终点的编号不为用户刚定义的结点编号时*/
			  cprintf("                 ERROR:The code of the vex is illegal!\r\n");
		 }
	   textcolor(10);
	   cprintf("                 Please check the data,then input again.");  /*要求用户检查数据并重新输入*/
	   textcolor(9);
	   getch();
	   while(wherey()!=ERROR_x-1)
		 {
		  gotoxy(1,wherey());
		  clreol();
		  gotoxy(1,wherey()-1);
		 }
	   gotoxy(1,wherey()+1);
	   count--;

	  }
	if(i!=-1)
	  {
	   G->arcs[i][j]=dist;   /*将合法的结点信息赋入邻接矩阵中*/
	   G->arcnum++;
	  }
	else
	  break;
   }
  gettext(1,1,80,23,buf);  /*将输入结点的相关信息存入内存的buf中,以便以后查看各结点的信息*/
}



int  ShortestPath(MGraph *G,int jump,int end,int avoid[],int P[MAXSIZE][MAXSIZE],int *pSHDist,int ShPath[]) /*根据用户给出的起点、终点、必经结点、避开结点进行分段查找*/
{
 int i,j,k,m,w;       /*均为循环控制变量*/
 int v,min;
 int Dist[MAXSIZE]; /*记录各结点的当前找到的最短路径的长度*/
 int final[MAXSIZE];  /*final[]为记录已找最短路径的结点*/
 for(i=0;i<(*G).vexnum;i++)  /*将用来记录用户给出的起点到图中其他各点的最短路径的路径路的长度的数组Dist[]初始化*/
   {
	final[G->vexs[i]]=FALSE;
	Dist[G->vexs[i]]=(*G).arcs[jump][G->vexs[i]];   /*给Dist数组赋初值*/
	for(j=0;j<(*G).vexnum;j++)
	   P[G->vexs[i]][j]=FALSE;
   }
 Dist[jump]=0;                    /*初始化*/
 final[jump]=TRUE;                /*初始化*/
 for(i=0;i<(*G).vexnum;i++) /*P[]][]为记录用户给定的起点到其他各点到目前为止找到的最短路径*/
  {
   if(((*G).arcs[jump][G->vexs[i]])<INFINITY)  /*当从用户给定的起点到其他的各点间有直接的路径时才处理*/
	 {
	  P[G->vexs[i]][0]=jump;
	  P[G->vexs[i]][1]=G->vexs[i];
	 }
  }

 for(i=0;avoid[i]!=-1;i++)
  for(j=0;j<G->vexnum;j++)
   if(avoid[i]==G->vexs[j])
	 final[G->vexs[j]]=TRUE; /*把用户给定的要避开的结点视为已找到最短路径的结点,则在找由jump到的end最短路径时将避开这些结点*/
 for(i=1;i<G->vexnum;i++)
   {
	min=INFINITY;
	for(j=0;j<G->vexnum;j++)  /*找出尚未求出最短路径的结点中的的结点的当前的路径长度的最小值*/
	  {
	   if(final[G->vexs[j]]==FALSE&&Dist[G->vexs[j]]<min)     /*final[G->vexs[j]]==FALSE,尚未求出到该顶点的最短路径*/
		 {
		  v=G->vexs[j];
		  min=Dist[G->vexs[j]];
		 }
	  }
	if(min<INFINITY)
	  {
	   final[v]=TRUE;
	   Dist[v]=min;
	  }
	else      /*如果已没有可用的路径时*/
	  break;

	if(v==end) /*当结点end的最短路径已找到时跳出循环*/
	  break;
	for(w=0;w<G->vexnum;w++)
	   if(final[G->vexs[w]]==FALSE&&(min+(*G).arcs[v][G->vexs[w]]<Dist[G->vexs[w]])&&(*G).arcs[v][G->vexs[w]]<INFINITY)  /*符合迪杰斯特拉条件*/
		 {
		  Dist[G->vexs[w]]=min+(*G).arcs[v][G->vexs[w]]; /*修改该结点的当前最短路径的路径长度值*/
		  if(v!=G->vexs[w])  /*修改记录该结点的当前找到的最短路径所经过结点序列*/
			{
			 for(j=0;P[v][j]!=FALSE&&P[v][j]!=v;j++)
				P[G->vexs[w]][j]=P[v][j];
			}
		  if(P[v][j]!=v)  /*完善已找到最短路径的结点所经的结点序列*/
			P[v][j]=v;
		  P[G->vexs[w]][j]=v;
		  P[G->vexs[w]][++j]=G->vexs[w];
		 }
   }
 if(v==end) /*将分段查找到的最短路径所经的结点存入记录最终最短路径的数组中,将分段查找到的最短路径的权值累加*/
   {
	for(i=0;ShPath[i]!=-1;i++);
	 if(i==0)
		j=0;
	 else
	   j=i-1;
	for(m=0;P[v][m]!=-1;j++)
	  ShPath[j]=P[v][m++];
	*pSHDist=*pSHDist+Dist[v];
	return SUCCEED;
  }
 else /*当分段最短路径查找失败时*/
   {
	textcolor(5);
	cprintf("\r\nThere is no path available between city[%d] and city[%d]!",jump,end);
	textcolor(11);
	getch();
	return ERROR;
   }
}


void Print(int jump,int end,int SHDist,int ShPath[]) /*输出找到的最短路径所经的结点和路径长度*/
{
 int i;
 textcolor(4);
 textbackground(10);
 cprintf("The shortest path searching result:\r\n\n");
 textbackground(0);
 textcolor(11);
 printf("The length between city [%d] and city [%d]: %d",jump,end,SHDist);
 printf("\nThe shortest path between city [%d] and city [%d]:",jump,end);
 printf("%d ",ShPath[0]);
 for(i=1;ShPath[i]!=-1;i++)
   printf("->%d ",ShPath[i]);
}

main()
{
 int i,j,k,n;  /*循环控制变量*/
 int flag[MAXSIZE],flag1,flag2; /*标志变量*/
 int vital_n; /*记录必经结点的数量*/
 int avail[MAXSIZE];
 char choice;
 int SHDist;  /*记录用户要求的最短路径的长度(权值)*/
 int jump,end;   /*jump记录用户给出的起点,end记录用户给出的终点*/
 int P[MAXSIZE][MAXSIZE]; /*用来记录各点当前找到的最短路径所经过的结点*/
 int vital[MAXSIZE]; /*记录用户给出的必经结点*/
 int avoid[MAXSIZE]; /*记录用户给出的要避开的结点*/
 int ShPath[MAXSIZE]; /*用来存放用户需要的最短路径所经的各结点*/
 char buf[80*25*2];  /*用来存放在图的相关信息录入时的界面信息,以便以后查看各结点的信息*/
 MGraph G; /*定义用来存放图的信息的邻接矩阵*/
 textmode(BW80);
 clrscr();
 Welcome();
 CreatGraph(&G,buf);
 textcolor(11);
 clrscr();
 while(1)
  {
   for(i=0;i<MAXSIZE;i++) /*初始化用来存放用户需要的最短路径所经的各结点的数组*/
	  ShPath[i]=-1;
   for(i=0;i<G.vexnum;i++) /*初始化用来记录各点当前找到的最短路径所经过的结点的数组*/
	 for(j=0;j<MAXSIZE;j++)
	  P[G.vexs[i]][j]=-1;
   for(i=0;i<MAXSIZE;i++)
     avail[i]=ERROR;
   n=0;
   SHDist=0;
   textcolor(4);
   textbackground(10);
   cprintf("Shortest Path searching:\r\n\n");
   textbackground(0);
   textcolor(11);
   printf("The node you customized:"); /*输出用户已自定义的各结点的编号以便用户检查输入的合法性*/
   for(i=0;i<G.vexnum;i++)
	 printf("%d ",G.vexs[i]);
  while(1)
	 {
	  flag1=flag2=0;
	  printf("\n\nPlease input the jump-off points and the end-point:");
	  scanf("%d %d",&jump,&end);
	  for(j=0;j<G.vexnum;j++) /*检查起点的合法性*/
		if(jump==G.vexs[j])
		  {
		   flag1=1;
		   break;
		  }
	  for(j=0;j<G.vexnum;j++) /*检查终点的合法性*/
		if(end==G.vexs[j])
		  {
		   flag2=1;
		   break;
		  }
	  if(flag1&&flag2)
		break;
	  if(!flag1)  /*若起点不合法*/
		{
		 textcolor(5);
		 cprintf("ERROE:Illegal jump-off point!\r\n");
		 textcolor(11);
		}
	  if(!flag2)  /*若终点不合法*/
		{
		 textcolor(5);
		 cprintf("ERROR:Illegal end-point!\r\n");
		 textcolor(11);
		}
	 }

   while(1)
	 {
	  printf("please input the vital points(end up by -1):");
	  for(k=0;k<MAXSIZE;k++)
		flag[k]=-1;
	  i=0;
	  while(1)   /*录入用户要求必经的结点,并同时检查其合法性*/
		{
		 scanf("%d",&vital[i++]);
		 if(vital[i-1]==-1)
			break;
		 for(j=0;j<G.vexnum&&vital[i-1]!=G.vexs[j];j++);
		 if(j==G.vexnum)
		   {
			textcolor(5);
			cprintf("ERROR:Illegal vital point [%d]!\r\n",vital[i-1]);
			textcolor(11);
			flag[i-1]=0;
		   }
		 else
		   flag[i-1]=1;
		}
	  for(k=0;k<MAXSIZE;k++)
		if(flag[k]==0)
		   break;
	  if(k==MAXSIZE)
		  break;
	 }
   vital_n=i-1;
   while(1) /*录入用户要求避开的结点,并同时检查其合法性*/
	 {
	  printf("please input the avoiding points(end up by -1):");
	  for(k=0;k<MAXSIZE;k++)
		flag[k]=-1;
	  i=0;
	  while(1)
		{
		 scanf("%d",&avoid[i++]);
		 if(avoid[i-1]==-1)
		   break;
		 for(j=0;j<G.vexnum&&avoid[i-1]!=G.vexs[j];j++);
		 if(j==G.vexnum)
		   {
			textcolor(5);
			cprintf("ERROR:Illegal avoid point [%d]!\r\n",avoid[i-1]);
			textcolor(11);
			flag[i-1]=0;
		   }
		  else
			flag[i-1]=1;
		}
	  for(k=0;k<MAXSIZE;k++)
		if(flag[k]==0)
		   break;
	  if(k==MAXSIZE)
		  break;
	 }
   printf("press any key to watch the result...");
   getch();
   clrscr();
   if(vital_n==0) /*当用户没用给出要求必经的结点时*/
	  vital[0]=end;
   avail[0]=ShortestPath(&G,jump,vital[0],avoid,P,&SHDist,ShPath);
   if(vital_n>=2) /*根据用户给出的起点、终点、必经结点、避开结点进行分段查找*/
	 for(i=0;vital[i+1]!=-1;i++)
            {
	      avail[n++]=ShortestPath(&G,vital[i],vital[i+1],avoid,P,&SHDist,ShPath);
	      /*printf("jump=%d end=%d\n",vital[i],vital[i+1]);*/
        }

   if(vital_n>=1) /*当用户只给出了一个必经结点时*/
	 {
	  if(vital_n==1)
		i=-1;
	  avail[n]=ShortestPath(&G,vital[i],end,avoid,P,&SHDist,ShPath);
	 }
   for(i=0;i<=n;i++)
	 if(avail[i]==ERROR)
	   {
		textcolor(4);
		cprintf("\r\nPath searching failed!");
		textcolor(11);
		break;

	   }
   if(i==n+1)
	  Print(jump,end,SHDist,ShPath);
   getch();
   clrscr();
   while(1) /*询问用户是否重新定义起点、终点、必经结点、避开结点并进行再次查找*/
	 {
	  textcolor(10);
	  cprintf("Change the limitataive conditions,then try again?y/n [ ]\b\b");
	  textcolor(11);
	  choice=getche();
	  if(choice=='y'||choice=='Y'||choice=='n'||choice=='N')
		break;
	  gotoxy(0,wherey());
	  clreol();
	 }
   if(choice=='n'||choice=='N')
	 break;
   clrscr();
   printf("The information about the graph.");
   puttext(1,3,80,25, buf);
   getch();
   clrscr();
  }
}

⌨️ 快捷键说明

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