额…,最近博客有一段时间没有更新了,本来打算每周两篇的打算被打断了,不断的意识到坚持一件事长久的做下去是多么的不易,当然也不是说上周什么事情都没有做,只是计算机图形学的作业确实是花了一段时间,虽然最终的效果可能没有那么理想,但确实是自己想要做好的一件事,所以觉得花的时间也是值得的,学一些新的技术固然不错,但个人觉得计算机系的必须要有着坚实的基础,所以数据结构与算法一定是我坚持的方向,好了,先展示下我作业的效果再开始正题吧…
一、 算法描述
Dijistra主要用于求得单源最短路径,对带权有向图G = (V,E),源点v0属于V,设置两个顶点集合S和T = V – S,集合S中存放已找到最短路径的顶点,集合T存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点v0,然后不断从集合T中选取到顶点v0路径长度最短的顶点u加入集合S中,集合S每加入一个新的顶点u,都要修改顶点v0到集合T中剩余顶点的最短路径长度值,集合T中各顶点新的最短路径长度值为原来的最短路径长度值与顶点u的最短路径长度值加上u到改顶点的路径长度中的较小值。此过程不断重复,直到集合T的顶点全部加入到S中为止。
二、 算法过程
三、算法实现
/*
*Dijkstra算法求得单源最短路径,运用邻接矩阵进行图的储存
*/
#include<stdio.h>
#include<malloc.h>
#define MaxVertexNum 100
#define MAX 9999
typedef char VertexType ;
typedef int EdgeType ;
/*
*定义图的存储结构
*/
typedef struct
{
VertexType vexs[MaxVertexNum][3] ; //定义顶点表
EdgeType edges[MaxVertexNum][MaxVertexNum] ; //定义边表
int n , e ; //定义顶点数与边数
} MGraph ;
/*
*创建栈,保存路径
*/
typedef struct
{
VertexType way[MaxVertexNum][3] ;
int top ;
} Stack ;
/*
*构建图邻接矩阵
*/
void CreateMGraph(MGraph *G)
{
int i , j , k , w ;
printf("请输入定点数与边数(输入格式为:顶点数,边数):") ;
scanf("%d,%d" , &G->n , &G->e) ;
printf("请输入顶点信息(输入格式为:顶点号<CR>):\n") ;
for(i = 0 ; i < G->n ; i++)
{
scanf("%s" , G->vexs[i]) ;
}
//初始化邻接矩阵
for(i = 0 ; i < G->n ; i++)
{
for(j = 0 ; j < G->n ; j++)
{
G->edges[i][j] = MAX ;
}
}
printf("请输入每条边对应的两个顶点序号以及权值(输入格式为:i,j,w):\n") ;
for(k = 0 ; k < G->e ; k++)
{
scanf("%d,%d,%d" , &i , &j , &w) ;
G->edges[i][j] = w ;
}
for(i = 0 ; i < G->n ; i++)
{
for(j = 0 ; j < G->n ; j++)
{
printf("%04d " , G->edges[i][j]) ;
}
printf("\n") ;
}
}
int finall[MaxVertexNum] ; //定义全局变量,记录顶点是否已求出最短路径
/*
*求得单源最短路径算法,即Dijkstra算法
*G为邻接矩阵 , v0为源点 , P为v0到各顶点v的路径 , D为最短路径长度
*/
void ShortestPath_1(MGraph G , int v0 , Stack *sw , int *D)
{
int v , w , i , j , min , k ;
for(w = 0 ; w < G.n ; w++)
{
sw[w].top = -1 ; //将路径置空
}
for(v = 0 ; v < G.n ; v++)
{
finall[v] = 0 ;
D[v] = G.edges[v0][v] ;
if(D[v]<MAX)
{
//对该点当前最短路径进行初始化
sw[v].top++;
for(k = 0 ; k < 3 ; k++)
{
sw[v].way[sw[v].top][k] = G.vexs[v0][k];
}
sw[v].top++;
for(k = 0 ; k < 3 ; k++)
{
sw[v].way[sw[v].top][k] = G.vexs[v][k];
}
}
}
D[v0] = 0 ;
finall[v0] = 1 ;
for(i = 1 ; i < G.n ; i++)
{
min = MAX ;
//在每次循环中找到当前路径最短的点
for(w = 0 ; w < G.n ; w++)
{
if(!finall[w])
{
if(D[w] < min)
{
v = w ;
min = D[w] ;
}
}
}
finall[v] = 1 ;
for(w = 0 ; w < G.n ; w++)
{
if(!finall[w]&&((min + G.edges[v][w]) < D[w]))
{
// 修改路径与路径长度
sw[w].top = sw[v].top ;
for(j = 0 ; j <= sw[v].top ; j++)
{
for(k = 0 ; k < 3 ; k++)
{
sw[w].way[j][k] = sw[v].way[j][k] ;
}
}
sw[w].top++ ;
for(k = 0 ; k < 3 ; k++)
{
sw[w].way[j][k] = G.vexs[w][k];
}
D[w] = min + G.edges[v][w] ;
}
}
}
}
/*
*测试代码
*/
void main()
{
MGraph *G ;
Stack w[MaxVertexNum] ;
int i , j ;
int P[MaxVertexNum][MaxVertexNum] , D[MaxVertexNum] ;
G = (MGraph*)malloc(sizeof(MGraph)) ;
CreateMGraph(G) ;
ShortestPath_1(*G , 0 , w , D) ;
//对最短路径与最短路径长度进行输出
for(i = 0 ; i < G->n ; i++)
{
if(D[i] < MAX)
{
for(j = 0 ; j <= w[i].top ; j++)
{
printf("%s->" , w[i].way[j]) ;
}
printf("---%d \n" , D[i]) ;
}
}
}