C语言实现路径矢量路由算法和链路状态路由算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>

//定义结构体
struct node{
	
	int d_num;//跳数
	int d_next;//下一跳节点
	
};


//定义链路状态算法的结构体
struct lsnode{
	int visited;//1代表已访问
	char path[40];//路径
	int index;//路径字符数量
}lsn[40];

int main(){
	struct node no_1[40][40], no_2[40][40];
	int N=0,num=0;
	int flag=0;//是否有节点出现,链路状态路由算法在所有节点都已经访问完成or找到目标节点的最短路径的时候结束
	int f1=0,f2=1,f3=0;//是否满足交换条件的标志
	int i=0,j=0,k=0,r=0,rl=0,m=0,n=0;
	int min=0;//寻找权值最小的节点
	int temp;
	int quan;
	char begin,end;
	int beginNode=0,endNode=0;
	
	char map[40][40];//坐标图
	int node[50][2];//节点的坐标,最多100个节点,0横坐标、1纵坐标
	int nearNodes[40][2];//2个相邻节点保存在数组
	int nearnum=0;//相邻节点数组的大小
	int topmap[40][40];//双向图二维表
	struct node *routeHeaders[40];//保存每个链表的头指针
	struct node *copyHeaders[40];//复制每个链表的头指针
	typedef struct node* np;//开辟节点内存用到
	struct node *p, *p1, *p2, *p3, *p4, *p5;//添加节点用到
	
	//初始化40*40的地图
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			map[i][j]='*';
			//printf("* ");
			if(i != j)topmap[i][j]=10000;
			else topmap[i][j]=0;
		}
		//printf("\n");
	}
	printf("请输入节点数量:\n");
	scanf("%d",&N);
	//随机生成坐标
	srand(time(NULL));
	for(i=0;i<N;i++){
		
		node[i][0]=rand(i+1)%40;
		node[i][1]=rand(i+10)%40;
		//printf("%c ",i+1);
	}
	//printf("%d %d",node[0][0],node[0][1]);
	//printf("%d %d",node[6][0],node[6][1]);
	//printf("%d %d",node[6][0],node[6][1]);
	//打印有节点的坐标图,
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			for(k=0;k<N;k++){
				if(i==node[k][0] && j==node[k][1]){
					flag=1;//有节点出现在这个坐标
					printf("%c ",(char)(k+65));
					break;
				}
			}
			if(flag==1){
				flag=0;
			}else{
				printf("* ");
			}
		}
		printf("\n");
	}
	//打印连接情况
	
	//while(1){
	
	printf("请输入节点信号覆盖半径:\n");
	scanf("%d",&r);
	//printf("节点--------直线距离----------节点\n");
	k=0;
	for(i=0;i<N;i++){
		for(j=i+1;j<N;j++){
			//(x1-x1)的平方+(y1-y2)的平方<=r*r
			rl=(node[i][0]-node[j][0])*(node[i][0]-node[j][0])+(node[i][1]-node[j][1])*(node[i][1]-node[j][1]);
			if(rl <= r*r){//保存相邻信息,这里是相邻节点数组
				nearNodes[k][0]=i;
				nearNodes[k][1]=j;
				k++;
				nearNodes[k][0]=j;
				nearNodes[k][1]=i;
				k++;
				//printf(" %c-------------%d--------------%c\n",(char)(65+i),(int)(sqrt(rl*1.0)),(char)(65+j));
				topmap[i][j]=(int)(sqrt(rl*1.0));
				topmap[j][i]=(int)(sqrt(rl*1.0));

			}
		}
		nearNodes[k][0]=100;//结束标志
		nearNodes[k][1]=100;
		nearnum=k;//保存相邻节点的个数
		//printf("\n");
	}
	
	//}
	//打印最佳路径
	getchar();
	printf("请输入起始节点:\n");
	scanf("%c",&begin);
	beginNode=(int)begin;
	//printf("%d\n",beginNode);
	getchar();
	printf("请输入终点节点:\n");
	scanf("%c",&end);
	endNode=(int)end;
	//printf("%d\n",endNode);
	printf("\n\n***********************距离矢量路由算法*******************************\n\n");
	
	//初始化结构体二维数组
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			no_1[i][j].d_num=100;//跳数,头节点
			no_1[i][j].d_next=100;//下一跳,头节点
			//printf("%d %d %d\n",no_1[i][j].d_node,no_1[i][j].d_num,no_1[i][j].d_next);
			no_2[i][j].d_num=100;//跳数,头节点
			no_2[i][j].d_next=100;//下一跳,头节点
			
		}
	}

	
	//根据相邻节点数组,初始化邻居相关的目的地、跳数、下一跳
	
	for(i=0;i<nearnum;i++){
		no_1[nearNodes[i][0]][nearNodes[i][1]].d_num=1;//【源下标】【邻居下标】
		no_1[nearNodes[i][0]][nearNodes[i][1]].d_next=95;//下一跳,95直接交付
		
	}
	/*
	//打印数组
	printf("起始节点	终点节点	跳数	下一跳节点(第一次找到邻居)\n");
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			if(no_1[i][j].d_num != 100 && no_1[i][j].d_next != 100){
				printf(" %c\t\t%c\t\t%d\t%c\n",(char)(65+i),(char)(65+j),no_1[i][j].d_num,(char)(no_1[i][j].d_next));
			}
		}
	}
	*/
	//备份数组,进行相关的修改
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			if(no_1[i][j].d_num != 100 && no_1[i][j].d_next != 100){
				no_2[i][j].d_num=no_1[i][j].d_num+1;//跳数+1
				no_2[i][j].d_next=i+65;//下一跳改为自己的下标
			}
		}
	}
	

	/*
	//打印表头指针备份数组
	printf("起始节点	终点节点	跳数	下一跳节点(备份)\n");
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			if(no_2[i][j].d_num != 100 && no_2[i][j].d_next != 100){
				printf(" %c\t\t%c\t\t%d\t%c\n",(char)(65+i),(char)(65+j),no_2[i][j].d_num,(char)(no_2[i][j].d_next));
			}
		}
	}
	*/
	
	while(f3==0){//当没有改动时,结束交换信息的循环
		num++;
		f3=1;//若无改变,则结束循环
		//遍历相邻节点数组,下标0本节点,1相邻节点,交换信息
		//让0的实际数组根据1的备份数组来改动
		for(i=0;i<nearnum;i++){//遍历相邻节点数组,实际数组no_1[nearNodes[i][0]][k],备份数组no_2[nearNodes[i][1]][j]
			for(j=0;j<40;j++){//逐条使用备份数组no_2[nearNodes[i][1]][j]
				if(no_2[nearNodes[i][1]][j].d_num != 100 && no_2[nearNodes[i][1]][j].d_next != 100){//若这个备份数组元素是有效的
					for(k=0;k<40;k++){//逐条使用实际数组no_1[nearNodes[i][0]][k]
						if(no_1[nearNodes[i][0]][k].d_num != 100 && no_1[nearNodes[i][0]][k].d_next != 100){//若这个实际数组元素是有效的
							if(j==k){//若目的地一样
								f1=1;//存在一个实际数组元素的目的地跟备份数组元素的目的地一样
								//若副本数组的下一跳是邻居节点自己 && 实际数组下一跳不是邻居节点  && 实际数组下一跳不是95
								if(no_2[nearNodes[i][1]][j].d_next==nearNodes[i][1] && no_1[nearNodes[i][0]][k].d_next!=nearNodes[i][1] && no_1[nearNodes[i][0]][k].d_next!=95){
									//则更新实际数组
									f3=0;//0表示有改动
									
									no_1[nearNodes[i][0]][k].d_num = no_2[nearNodes[i][1]][j].d_num;
									no_1[nearNodes[i][0]][k].d_next = no_2[nearNodes[i][1]][j].d_next;
								}
								//若副本数组的下一跳不是邻居节点自己,且实际数组元素的跳数大于备份数组元素的跳数
								if(no_2[nearNodes[i][1]][j].d_next!=nearNodes[i][1] && no_1[nearNodes[i][0]][k].d_num > no_2[nearNodes[i][1]][j].d_num){
									//则更新实际数组
									f3=0;//0表示有改动
									
									no_1[nearNodes[i][0]][k].d_num = no_2[nearNodes[i][1]][j].d_num;
									no_1[nearNodes[i][0]][k].d_next = no_2[nearNodes[i][1]][j].d_next;
								}
							}
						}
					}//for k
					//若目的地不一样(该实际数组元素无效,且备份数组元素有效),且备份数组元素的目的地不是实际数组元素下标
					// && 实际数组的元素不可以是直接交付  && 实际数组的元素必须是还没被用上的 
					if(j!=k && j!=nearNodes[i][0] && no_1[nearNodes[i][0]][j].d_next!=95 && no_1[nearNodes[i][0]][j].d_num==100){
						//则把该副本数组元素添加到实际数组元素,
						//printf("改变%d  %d\n",no_1[nearNodes[i][0]][j].d_num,no_1[nearNodes[i][0]][j].d_next);
						f3=0;//0表示有改动
						
						no_1[nearNodes[i][0]][j].d_num = no_2[nearNodes[i][1]][j].d_num;
						no_1[nearNodes[i][0]][j].d_next = no_2[nearNodes[i][1]][j].d_next;
					}
				}
			}//for j
		}//for i
		//备份数组,进行相关的修改
		for(i=0;i<40;i++){
			for(j=0;j<40;j++){
				if(no_1[i][j].d_num != 100 && no_1[i][j].d_next != 100){
					no_2[i][j].d_num=no_1[i][j].d_num+1;//跳数+1
					no_2[i][j].d_next=i+65;//下一跳改为自己的下标
				}else{
					no_2[i][j].d_num=100;//跳数100
					no_2[i][j].d_next=100;//下一跳100
				}
			}
		}
	
	}//while
	
	//打印数组
	printf("起始节点	终点节点	跳数	下一跳节点(交换次数:%d)\n",num);
	for(i=0;i<40;i++){
		for(j=0;j<40;j++){
			if(no_1[i][j].d_num != 100 && no_1[i][j].d_next != 100){
				printf(" %c\t\t%c\t\t%d\t%c\n",(char)(65+i),(char)(65+j),no_1[i][j].d_num,(char)(no_1[i][j].d_next));
			}
		}
	}
	
	//打印路径
	printf("\n开始节点:%c\t结束节点:%c\n\n",(char)(beginNode),(char)(endNode));
	
	f2=0;
	f3=beginNode;
	if(no_1[f3-65][endNode-65].d_next == 100) printf("%c-->%c没有路径可走",(char)(beginNode),(char)endNode);
	else if(no_1[f3-65][endNode-65].d_next == 95) printf("%c-->%c",(char)(beginNode),(char)endNode);
	else{
		while(f3 != 95){
			f2++;
			if(no_1[f3-65][endNode-65].d_next == 95) break;
			if(f2==1) printf("%c-->%c",(char)f3,(char)no_1[f3-65][endNode-65].d_next);
			else printf("-->%c",(char)no_1[f3-65][endNode-65].d_next);
			f3=no_1[f3-65][endNode-65].d_next;
		}
		printf("-->%c",(char)endNode);
		//else printf("%c-->%c没有路径可走",(char)(beginNode),(char)endNode);
	}
	printf("\n\n\n");


	printf("\n***********************链路状态路由算法*******************************\n\n");
	printf("拓扑图转换为二维表\n");
	
	printf(" ");
	for(i=0;i<N;i++){
		printf(" %c",(char)(65+i));//列头
	}
	printf("\n");
	for(i=0;i<N;i++){
		printf("%c",(char)(65+i));//行头
		for(j=0;j<N;j++){
			if(topmap[i][j]==10000) printf(" -");
			else printf(" %d",topmap[i][j]);
		}
		printf("\n");
	}
	
	//printf("\n\n318\n\n");
	//初始化节点数组
	for(j=0;j<40;j++){
		lsn[j].visited=0;//访问标志
		for(i=0;i<40;i++){
			lsn[j].path[i]=NULL;//路径
		}
		lsn[j].path[0]=(char)beginNode;//把起始节点保存到每个节点的路径数组开始
		lsn[j].index =1;//路径字符数量
	}
	
	//在所有节点都已经访问完成or找到目标节点的最短路径的时候结束
	
	while(min!=20000){
		min=20000;//若min无变化,则循环结束
		for(j=0;j<N;j++){//逐个使用begin这一行的元素(权值)
			//begin这一行权值最小 && 节点访问标志是0的节点 && 权值不是0(0表示节点到自己)
			if(topmap[beginNode-65][j] < min && lsn[j].visited==0 && topmap[beginNode-65][j] != 0){
				min = topmap[beginNode-65][j];//选出最小值
				temp=j;//记录下标
			}
		}//获得权值最小的节点
		//if(min == 20000) break;//若全部节点都被访问
		//若min是10000,访问到不可直接到达路径
		if(min==10000){//该节点是不可以直接到达的点
			lsn[temp].visited=1;//该节点被访问
			lsn[temp].path[lsn[temp].index]=(char)(temp+65);//该节点的路径加入该节点
			lsn[temp].index++;//路径元素数量+1
		}else{//该节点是可以直接到达的点
			lsn[temp].visited=1;//该节点被访问
			lsn[temp].path[lsn[temp].index]=(char)(temp+65);//该节点的路径加入该节点
			lsn[temp].index++;//路径元素数量+1
			for(j=0;j<N;j++){//逐个使用temp这一行的元素(权值)
				//temp这一行找到出度(权值比begin这一行的权值要小 && begin的这个节点未被访问过 && temp这一行的出度节点不可以是自己)
				if(topmap[temp][j]<topmap[beginNode-65][j] && lsn[j].visited==0 && temp != j){
				
					topmap[beginNode-65][j]=topmap[temp][j];//更新begin这一行
					for(i=1;i<lsn[temp].index;i++){
						lsn[j].path[i]=lsn[temp].path[i];//后面节点使用前面节点的路径
					}
					//lsn[j].path[i]=(char)(j+65);
					lsn[j].index=lsn[temp].index;
				}
			}
		}
		
	}
	printf("\n开始节点:%c\t结束节点:%c\n\n",(char)(beginNode),(char)(endNode));
	printf("链路状态路由算法得出最短路径:\n");
	if(topmap[beginNode-65][endNode-65]==10000) printf("%c-->%c没有最短路径",(char)(beginNode),(char)(endNode));
	else if(topmap[endNode-65][beginNode-65]>0 && topmap[endNode-65][beginNode-65]<r) printf("%c-->%c",(char)(beginNode),(char)(endNode));
	else {
		for(j=0;j<lsn[endNode-65].index;j++){
			if(j==0)printf("%c",lsn[endNode-65].path[j]);
			else printf("-->%c",lsn[endNode-65].path[j]);
		}
	}
	printf("\n\n");

	return 0;
}





发布了10 篇原创文章 · 获赞 2 · 访问量 5263

猜你喜欢

转载自blog.csdn.net/qq_36686441/article/details/90141266