#include<stdio.h>
#define VERTEX_MAX 26
#define MAXVALUE 32767
struct MatrixGraph
{
int Vertex[VERTEX_MAX]; //保存顶点信息(序号或字母)
int Edges[VERTEX_MAX][VERTEX_MAX]; //保存边的权
int isTrav[VERTEX_MAX]; //遍历标志
int VertexNum; //顶点数量
int EdgeNum; //边数量
int GraphType; //图的类型
};
void DFSM(MatrixGraph *G,int i) //从第一个结点开始深度遍历图
{
int j;
G->isTrav[i]=1; //标志该结点已遍历过
printf("%d->",i);
for(j=0;j<G->VertexNum;j++)
{
if(G->Edges[i][j]!=MAXVALUE&&!G->isTrav[i])
DFSM(G,j); //递归进行遍历
}
}
void DFSTraverse(MatrixGraph *G) //深度优先遍历
{
int i;
for(i=1;i<=G->VertexNum;i++) //清除各项顶点遍历标志
{
G->isTrav[i]=0;
}
printf("深度优先遍历结点:");
for(i=1;i<=G->VertexNum;i++)
{
if(!G->isTrav[i]) //若该点未遍历
{
DFSM(G,i); //调用函数遍历
}
}
printf("\n");
}
void CreateMatrixGraph(MatrixGraph *G)
{
int i,j,k,weight;
int start,end;
printf("输入各顶点信息\n");
for(i=0;i<G->VertexNum;i++) //输入顶点
{
printf("\n第%d个顶点",i+1);
scanf("%d",&G->Vertex[i]);
}
printf("输入构成各边的两个顶点及权值\n");
for(k=0;k<G->EdgeNum;k++)
{
printf("第%d条边:",k+1);
scanf("%d,%d,%d",&start,&end,&weight);
for(i=0;start!=G->Vertex[i];i++); //输入边的信息
for(j=0;end!=G->Vertex[j];j++);
G->Edges[i][j]=weight;
if(G->GraphType==0) //若是无向图
{
G->Edges[j][i]=weight; //在对角位置保存权值
}
}
}
void OutMatrix(MatrixGraph *G)
{
int i,j;
for(j=0;j<G->VertexNum;j++)
{
printf("\t%d",G->Vertex[j]); //在第一行输出顶点信息
}
printf("\n");
for(i=0;i<G->VertexNum;i++)
{
printf("%d",G->Vertex[i]);
for(j=0;j<G->VertexNum;j++)
{
if(G->Edges[i][j]==MAXVALUE) //若权值为最大值
printf("\t#"); //输出#号
else
printf("\t%d",G->Edges[i][j]);
}
printf("\n");
}
}
void Djkastra(MatrixGraph *G)
{
int weight[VERTEX_MAX]; //原点到各顶点的最短路径长度
int path[VERTEX_MAX]; //原点到终点经过的顶点集合的数组
int tmpvertex[VERTEX_MAX]; //最短路径的终点集合
int i, j, k, v0, min;
printf("\n请输入原点的编号:");
scanf("%d", &v0);
v0--; //编号自减1,(因数组是从0开始)
for(i = 0; i < G -> VertexNum; i++) //初始辅助数组
{
weight[i] = G -> Edges[v0][i]; //保存最小权值
if(weight[i] < MAXVALUE && weight[i] > 0) //有效权值
path[i] = v0; //初始化顶点集合为空
tmpvertex[i] = 0; //初始化顶点集合为空
}
tmpvertex[v0] = 1; //将顶点v0添加到集合U中
weight[v0] = 0; //将原点顶点的权值设为0
for(i = 0; i < G -> VertexNum; i++)
{
min = MAXVALUE; //将min中保存一个最大值
k = v0; //源顶点序号
for(j = 0; j < G -> VertexNum; j++) //在U集合中查找未用顶点的最小权值
if(tmpvertex[j] == 0 && weight[j] < min)
{
min = weight[j];
k = j;
}
tmpvertex[k] = 1; //将顶点k加入集合U
for(j = 0; j < G -> VertexNum; j++) //以顶点k为中间点,重新计算权值
if(tmpvertex[j] == 0 && weight[k] + G ->Edges[k][j] < weight[j])
{ //有更小的权值的路径
weight[j] = weight[k] + G -> Edges[k][j] ; //更新权值
path[j] = k;
}
}
printf("\n顶点%d到各顶点的最短路径为(终点 < 原点):\n", G -> Vertex[v0]);
for(i = 0; i < G -> VertexNum; i ++)
{
if(tmpvertex[i] == 1)
{
k = i;
while(k != v0) //顶点·序号不与原点相同
{
j = k;
printf("%d < " , G -> Vertex[k]); //输出经过的顶点
k = path[k]; //上一个顶点
}
printf("%d\n", G -> Vertex[k]); //源顶点
}else
printf("%d < - %d:无路径\n", G -> Vertex[i] , G -> Vertex[v0]);
}
}
int main()
{
MatrixGraph G;
int i,j;
printf("输入生成图类型(0:无向图,1:有向图):");
scanf("%d",&G.GraphType);
printf("输入图的顶点数量和各边数量:");
scanf("%d,%d",&G.VertexNum,&G.EdgeNum); //输入图顶点数和边数
for(i=0;i<G.VertexNum;i++)
for(j=0;j<G.VertexNum;j++)
G.Edges[i][j]=MAXVALUE;
CreateMatrixGraph(&G);
printf("邻接矩阵数据如下:\n");
OutMatrix(&G);
DFSTraverse(&G);
printf("图遍历完毕\n\n");
printf("最短路径:");
Djkastra(&G);
return 0;
}