数据结构——邻接矩阵表示的图的Dijkstra算法

#include <iostream>
#include
<iomanip>
using namespace std;

#define MAX_VERTEX_NUM 10 //最大顶点个数
#define TRUE 1
#define FALSE 0
#define INFINITY 32767 /* 用整型最大值代替∞ */

typedef
char VERTYPE;
typedef
struct
{
VERTYPE vexs[MAX_VERTEX_NUM];
//顶点向量
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
}mgraph, * MGraph;


typedef
int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef
int ShortPathTable[MAX_VERTEX_NUM];

void init_mgraph(MGraph &g) //初始化图
{
g
=(MGraph)malloc(sizeof(mgraph));
g
->vexnum=0;
g
->arcnum=0;
for(int i=0;i<MAX_VERTEX_NUM;i++)
g
->vexs[i]=0;
for(i=0;i<MAX_VERTEX_NUM;i++)
for(int j=0;j<MAX_VERTEX_NUM;j++)
g
->arcs[i][j]=INFINITY;
}

void add_vexs(MGraph &g) //增加顶点
{
cout
<<"请输入顶点的个数:"<<endl;
cin
>>g->vexnum;
cout
<<"请输入顶点的值"<<endl;
for(int i=0;i<g->vexnum;i++)
{
cin
>>g->vexs[i];
}
}
void add_arcs(MGraph &g) //增加边
{
cout
<<"请输入边的个数:"<<endl;
cin
>>g->arcnum;
VERTYPE ch1,ch2;
int row,col,weight;

for(int i=0;i<g->arcnum;i++)
{
cin
>>ch1>>ch2>>weight;
for(int j=0;j<g->vexnum;j++)
{
if(g->vexs[j]==ch1)
{
row
=j;
}
if(g->vexs[j]==ch2)
{
col
=j;
}
}
g
->arcs[row][col]=weight; //有向带权图只需把1改为weight
}
}

void creat_mgraph(MGraph &g) //创建图
{
add_vexs(g);
//增加顶点
add_arcs(g); //增加边
}

void print_mgraph(MGraph &g) //打印图
{
for(int i=0;i<g->vexnum;i++)
cout
<<" "<<g->vexs[i]<<" ";
cout
<<endl;
for(i=0;i<g->vexnum;i++)
{
cout
<<g->vexs[i]<<" ";
for(int j=0;j<g->vexnum;j++)
{
cout
<<setw(5)<<g->arcs[i][j]<<" ";
}
cout
<<endl;
}
}

void ShortestPath_DIJ(MGraph &g, int v0, PathMatrix *P, ShortPathTable *D)
{
// 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v]。
// 若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。
// final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。
int v,w,i,j,min;
int final[MAX_VERTEX_NUM];

for(v=0; v<g->vexnum; ++v)
{
final[v]
= FALSE;
(
*D)[v] = g->arcs[v0][v];
for(w=0; w<g->vexnum; ++w)
(
*P)[v][w] = FALSE; //设空路径
if((*D)[v] < INFINITY) //v0可以直接到达的点v
{
(
*P)[v][v0] = TRUE; //v0是v0直接到达v的路径的始点
(*P)[v][v] = TRUE; //v是v0直接到达v的路径的终点
}
}
//for
(*D)[v0] = 0;
final[v0]
= TRUE; //初始化,v0顶点属于S集

//开始主循环,每次求得v0到某个v顶点的最短路径,并加入v到S集
for(i=1; i<g->vexnum; i++) //其余g.vexnum-1个顶点
{
min
=INFINITY; //当前所知离v0顶点的最近距离
for(w=0; w<g->vexnum; w++)
{
if(!final[w] && (*D)[w]<min) //w顶点在V-S中
{
v
=w;
min
= (*D)[w]; //w顶点离v0顶点更近
}
}
final[v]
= TRUE; //离v0顶点最近的v加入S集
for(w=0; w<g->vexnum; w++)
{
//更新当前最短路径及距离
if(!final[w] && ( min+g->arcs[v][w]<(*D)[w] ) ) //如果经过v顶点的路径比现在这条路径的长度短的话
{
// 修改D[w]和P[w],w∈V-S
(*D)[w] = min + g->arcs[v][w]; //修改当前路径长度
for(j=0;j<g->vexnum;++j)
(
*P)[w][j]=(*P)[v][j]; //将经过v点的路径复制过来
(*P)[w][w]=TRUE; //最后的重点为TURE

}
}
}
}



int main()
{
MGraph G;
init_mgraph(G);
//初始化图
creat_mgraph(G); //创建图
print_mgraph(G); //打印图

PathMatrix P;
ShortPathTable D;
//求某点到其余各点的最短路径
cout<<"输入源点的序号:"<<endl;
int v0;
cin
>>v0;
ShortestPath_DIJ(G, v0,
&P, &D);

cout
<<"最短路径数组p[i][j]如下:"<<endl;
for(int i=0;i<G->vexnum;++i)
{
for(int j=0;j<G->vexnum;++j)
cout
<<P[i][j]<<" ";
cout
<<endl;
}
cout
<<"源点到各顶点的最短路径长度为:"<<endl;
for(i=1;i<G->vexnum;++i)
cout
<<G->vexs[0]<<" "<<G->vexs[i]<<" "<<D[i]<<endl;

return 0;
}

 

posted @ 2010-08-09 13:43  忧国忧铭  Views(2399)  Comments(0Edit  收藏  举报