距离向量选路算法

时间:2022-07-13 11:13:05

1.代码

#include<stdio.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<string.h>
#include<stdlib.h>
#include<io.h>
#include<math.h>
#include<sys/timeb.h>
#include<stdarg.h>
#include<time.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAX_NAME 9//顶点名称字符串最大长度+1
#define INFINITY 1000//用1000代替∞
#define MAX_VERTEX_NUM 26 //最大顶点个数
typedef int Status;
typedef int Boolean;
typedef int VRType;//定义顶点关系类型为整型,与INFINITY的类型一致
typedef char PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];//三维数组
typedef VRType DistancMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//二维数组 
typedef struct //边(弧)信息结构
{
    VRType adj;//顶点关系类型,对带权图,表示权值 
} ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//二维数组 
enum GraphKind{DG,DN,UDG,UDN} ;//{有向图、无向网、无向图、无向网}
struct VertexType//最简单的顶点信息类型(只有顶点名称)
{
    char name[MAX_NAME];//顶点名称 
    char routers[MAX_VERTEX_NUM][MAX_NAME];//定义最短路径中到目的节点的上一跳 
} ;
struct MGraph//图的结构
{
    VertexType vexs[MAX_VERTEX_NUM];//顶点向量
    AdjMatrix arcs;//邻接矩阵(二维数组)
    int vexnum,arcnum;//图的当前顶点数和弧数
    GraphKind kind; //图的种类标志 
} ;

int stable=0;//到达稳定前路由表交换次数 

void visit(VertexType ver)//访问顶点的函数
{
    printf("%s",ver.name);
}
void input(VertexType &ver) //输入顶点信息的函数 
{
scanf("%s",ver.name);   
}

int LocateVex(MGraph G,VertexType u)
{
    //查找顶点u,并返回其位置
    int i;
    for(i=0;i<G.vexnum;++i)
        if(strcmp(u.name,G.vexs[i].name)==0)
        return i;
}
void CreateDN(MGraph &G)//构造有向网G 
{
int i,j,k;
VRType w;//顶点关系类型 
 VertexType v1,v2;
 printf(" 请输入网络拓扑结构中的节点数、弧数");
 scanf("%d %d",&G.vexnum,&G.arcnum);
 printf(" 请输入%d个顶点的值(名称小于%d个字符):",G.vexnum,MAX_NAME);
 for(i=0;i<G.vexnum;i++)//构造顶点向量
  input(G.vexs[i]);    //输入节点名称
  for(i=0;i<G.vexnum;i++)//初始化二维邻接矩阵
  for(j=0;j<G.vexnum;j++)
  {
    G.arcs[i][j].adj=INFINITY;
  } 
  printf(" 请输入%d条弧的弧尾 弧头 权值:\n",G.arcnum);
  for(k=0;k<G.arcnum;k++)
  {
    scanf("%s %s %d",v1.name,v2.name,&w);
    i=LocateVex(G,v1);
    j=LocateVex(G,v2);
    G.arcs[i][j].adj=w;
    G.arcs[j][i].adj=w;
  } 
}
VertexType GetVex(MGraph G,int v)
{
    if(v>=G.vexnum||v<0)
    exit(OVERFLOW);
    return G.vexs[v];
}
void Display(MGraph G)
{
    int i,j,k;
    printf(" %d个顶点%d条弧的无向网。顶点依次是:",G.vexnum,G.arcnum);
    for(i=0;i<G.vexnum;i++)
    visit(GetVex(G,i));
    printf("\n 初 始 路 由 表 如 下(1000表示无穷远):\n");
    printf(" ");
        for(i=0;i<G.vexnum;i++)
        printf("%-8s",G.vexs[i].name);
        printf("\n");
         for(j=0;j<G.vexnum;j++)
     {   printf("%20s",G.vexs[j].name);
        for(k=0;k<G.vexnum;k++)
        printf(" %-5d",G.arcs[j][k].adj);
        printf("\n");
     }
} 

void ShortestPath_Floyd(MGraph G,PathMatrix P,DistancMatrix D)
{
    //用Floyd算法随机更新两顶点间最短路径、顶点路由表,若P[v][w][u]为true,则u是从v到w当前求得最短路径上的顶点
    int u,v,w,i,j,k;
    int change=1;//路由表有无交换 
    int bad=1;//不好的交换 
    for(v=0;v<G.vexnum;v++)
    for(w=0;w<G.vexnum;w++)
    {
        D[v][w]=G.arcs[v][w].adj;//顶点v到w的直接距离
        for(u=0;u<G.vexnum;u++)
        P[v][w][u]=FALSE;
        if(D[v][w]<INFINITY)//从V到W有直接路径 
        {
        strcpy(G.vexs[v].routers[w],G.vexs[v].name);
        P[v][w][v]=P[v][w][w]=TRUE; //由v到w的路径经过v和w两点
         }
         else 
         strcpy(G.vexs[v].routers[w],"-");
    } 
    srand((unsigned)time(NULL));//产生随机数种子,防止伪随机数 
    while(change==1)
    {
    for(;bad<20;)//连续20次随机交换无更新,为坏的交换,则停止随机交换 
    {
    v=rand()%G.vexnum;
    w=rand()%G.vexnum;
    if(D[v][w]<INFINITY&&v!=w)
    {
    printf("%s节点向%s节点发送距离向量,",G.vexs[w].name,G.vexs[v].name);
     change=0;
     for(u=0;u<G.vexnum;u++)
     {
     if(D[w][u]<INFINITY&&D[v][w]+D[w][u]<D[v][u])//从v经u到w的一条路径更短
      {
     D[v][u]=D[v][w]+D[w][u];//更新最短距离
     change=1;
     bad=0;   //一有更新,则不是坏的交换 
     if(w!=u)
     strcpy(G.vexs[v].routers[u],G.vexs[w].name);//记录上一跳节点名称 
     for(i=0;i<G.vexnum;i++)
     P[v][w][i]=P[v][u][i]||P[u][w][i];//从v到w的路径经过从v到u和从u到w的所有路径 

      }//if 
    }//for u
    if(change==1)
    {  
     stable++;  
    printf(" %s 的 路 由 表 如 下:\n",G.vexs[v].name);
    printf(" 目的节点 最短路径 上一跳\n");
    for(j=0;j<G.vexnum;j++)
    printf(" %8s %8d %8s\n",G.vexs[j].name,D[v][j],G.vexs[v].routers[j]);
    }// if change 
    else 
    {
    printf(" %s 的 路 由 表 无更新:\n\n",G.vexs[v].name); 
    bad++;
    }
    }//if
    }//for
    }//while
     printf("\n********************************************************************************\n");    
     printf(" 所以经过%d次交换,路由表达到稳定,最短路径矩阵为:\n",stable);
     printf(" ");
    for(i=0;i<G.vexnum;i++)
        printf("%-8s",G.vexs[i].name);
        printf("\n");
         for(j=0;j<G.vexnum;j++)
     {   printf("%20s",G.vexs[j].name);
        for(k=0;k<G.vexnum;k++)
        printf(" %-5d",D[j][k]);
        printf("\n");
     }
     for(i=0;i<G.vexnum;i++)
    {
       printf(" %s 的 路 由 表 如 下:\n",G.vexs[i].name);
    printf(" 目的节点 最短路径 上一跳\n");
    for(j=0;j<G.vexnum;j++)
    printf(" %8s %8d %8s\n",G.vexs[j].name,D[i][j],G.vexs[i].routers[j]);
    }
} 
 main()
 {
    MGraph g;
    int i,j,k;
    PathMatrix p;
    DistancMatrix d;
    printf("***********************本程序完成距离向量路由算法的模拟*************************\n"); 
    CreateDN(g);//构造有向网g
     for(i=0;i<g.vexnum;i++)
     g.arcs[i][i].adj=0;//顶点到自身距离为0
     Display(g);//输出有向网g 
     ShortestPath_Floyd(g,p,d);//求每对顶点的最短路径 

     return 1;
 } 

2.运行结果
距离向量选路算法

距离向量选路算法

3.结果说明
首先通过输入得出各个路由顶点以及顶点之间的距离。然后打印出来。然后程序通过距离向量选路算法得出最小路径。最后打印出各个路由器之间的最短路径,“上一跳”表示在初始路由器和终点路由器之间,且和终点路由器直接相连的一个路由器节点。如果没有路径,上一跳由“-”表示。在运行结果中,我省略了一部分截图,里面表示“ 路 由 表 无更新“;