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.結果說明
首先通過輸入得出各個路由頂點以及頂點之間的距離。然後打印出來。然後程序通過距離向量選路算法得出最小路徑。最後打印出各個路由器之間的最短路徑,“上一跳”表示在初始路由器和終點路由器之間,且和終點路由器直接相連的一個路由器節點。如果沒有路徑,上一跳由“-”表示。在運行結果中,我省略了一部分截圖,裏面表示“ 路 由 表 無更新“;