图论:最短路径(广度优先搜索、C语言实现)
要用到的数据结构有:
队列、表、邻接表
分为六个文件-
|--Main.c 应用文件:main函数所在。读取各边到邻接表,然后调用计算机最小路径函数。求解。
|--code.c 最小路径函数:最小路径函数所在。
|--Queue.c 数据结构:队列
|--Table.c 数据结构:表
|--AdjList.c数据结构:邻接表
|--Graph.h 将所有数据结构文件包含进来
邻接表和队列的源泉代码可以从文章列表中找到。
算法为广度优先搜索。将路径和点记录在一张表中。最后用打印函数递归的打印出路径。思路可见《数据结构与算法分析》。
各文件源代码如下:
Graph.h:#ifndef _Graph_h
#include "Queue.c"
#include "Table.c"
#endif
Main.c:
#include "code.c"
int main()
{
Vertex Graph = NULL ; Table T ;
int x, y, s, a ;
/*读取各边并插入*/
for(scanf("%d %d", &x, &y); x != -1 ; scanf("%d %d", &x, &y))
Graph = InsertEdge(x, y, Graph) ;
/*创建用于簿记的表,并初化始表:将图中各点格式化入表中*/
T = CreatTable(SizeOfGraph(Graph)) ;
TableInit(T, Graph) ;
/*获取起点*/
printf("Input the start vertex: ") ;
scanf("%d", &s) ;
/*计算各点的最短路径,并记录表中*/
ShortestPath(s, Graph, T) ;
/*得到终点*/
printf("Input the aim vertex: ") ;
scanf("%d", &a) ;
/*打印出该路径,未尾会*/
TablePrint(s, a, T) ;
printf("\n") ;
/*释放内存*/
GraphDestory(Graph) ;
TableDestory(T) ;
return 0;
}
code.c:
#include "Graph.h"
void ShortestPath(int S, Vertex Graph, Table T)
{
Queue Q ; int NumVertex ;
int tmp ; int V, W ;
Ind_Node Ind ; int DistCount = 0;
//init what should be init
/*计算图中的点数*/
NumVertex = SizeOfGraph(Graph) ;
/*创建队列*/
Q = CreatQueue(NumVertex) ;
//enter the start vertex into queue
/*找到起点*/
tmp = TableFind(S, T) ;
/*初始化起点*/
T->Array[tmp].Know = True ;
T->Array[tmp].Path = 0 ;
T->Array[tmp].Dist = 0 ;
/*将起点推入队列之中,以驱动下面的代码*/
Enqueue(tmp, Q) ;
/*第一次运行至此,队列不为空,因为插入起点*/
while(!QueueIsEmpty(Q))
{
/*读取一点*/
V = Dequeue(Q) ;
/*读取V的各个入度*/
Ind = (T->Array[V].prototype)->Indegree ;
while(Ind != NULL)
{
/*W为当前读取到的入度点*/
W = TableFind(Ind->Number, T) ;
if(T->Array[W].Dist == Infinity)
{
/*如果W以前没有处理过,那么进行处理*/
T->Array[W].Dist = T->Array[V].Dist +1 ;
T->Array[W].Path = (T->Array[V].prototype)->Number ;
/*然后推入队列之中*/
Enqueue(W, Q) ;
}
/*处理下一入度点*/
Ind = Ind->Next ;
}
}
/
QueueDestory(Q) ;
}
Table.c:
#include <stdio.h>
#include <stdlib.h>
#include "AdjList.c"
#include "limits.h"
#define Infinity INT_MAX
#define True 1
#define False 0
typedef struct table_element_tag
{
/*将向邻接表中的点*/
Vertex prototype ;
/*路径长度*/
int Dist ;
/*记录该点在最短路径中的上一个点。*/
int Path ;
}*TableElement ;
typedef struct table_tag
{
/*这里是表头,第一个是记录表大小,第二个是数组(数组实现表)*/
int Size ;
TableElement Array ;
}*Table ;
Table CreatTable(int Max)
{
/*分配好内存,返回*/
Table T ;
T = calloc(1, sizeof(struct table_tag)) ;
if(!T) { fprintf(stderr, "Out of space!\n"); exit(1) ;}
T->Array = calloc(Max, sizeof(struct table_element_tag)) ;
if(!T->Array){ fprintf(stderr, "Out of space!") ; exit(1) ;}
T->Size = Max ;
return T ;
}
void TableInit(Table T, Vertex Graph)
{
/*将表中各点记录表中*/
int i = 0;
while(Graph != NULL && i < T->Size)
{
//calloc will init Know
T->Array[i].prototype = Graph ;
/*记录为无穷大,表示该点未知*/
T->Array[i].Dist = Infinity ;
T->Array[i].Path = Infinity ;
i++ ;
Graph = Graph->Next ;
}
}
int TableFind(int f, Table T)
{
TableElement te ; int size ; int i ;
if(!T){ fprintf(stderr, "Graph was empty or miss!\n") ; exit(1) ;}
te = T->Array ; size = T->Size ;
for( i = 0; i < size; i++)
if( (te[i].prototype)->Number == f)
break ;
if(i < size)
return i ;
else /*如果没有找到就返回无穷大*/
return Infinity ;
}
void TablePrint(int s, int a, Table T)
{
int tmp ;
if(a != s)
{
tmp = TableFind(a, T) ;
if(tmp == Infinity){ fprintf(stderr, "No Found the vertex: %d\n", a) ; exit(1) ;}
TablePrint(s, T->Array[tmp].Path, T) ;
printf(" to ") ;
}
printf("%d", (T->Array[TableFind(a, T)].prototype)->Number) ;
}
void TableDestory(Table T)
{
/*释放内存*/
if(T)
{
if(T->Array)
free(T->Array) ;
free(T) ;
}
}