1、图遍历的定义
从图中的某一顶点出发,沿着一些边访遍图中所有的顶点,使得每个顶点仅被访问一次。
2、方法分类
- 深度优先搜索(Depth First Search)
- 广度优先搜索(Breadth First Search)
3、DFS 示例
4、DFS 算法描述
5、算法实现
/*
深度优先,遍历graph所指图中的每个顶点
* 参数:
graph: 指向图的指针
v: 起始顶点
pfunc: 显示回调函数
* 返回值:
无
*/
static void recursive_dfs(TLGraph *tgraph,int v,int *visited,LGraph_Printf* pfunc)
{
//首先,访问结点v
pfunc(tgraph->data[v]);
printf("\t");
visited[v] = 1;
TListnode *node = NULL;
//然后,遍历它的“子结点”,如果该”子结点“未被访问,则以它为顶点,再次递归...
for(int i = 0; i < List_Length(tgraph->la[v]); i++)
{
node = (TListnode*)List_Get(tgraph->la[v], i);
if(node != NULL)
{
if(!visited[node->v])
{
recursive_dfs(tgraph, node->v, visited, pfunc);
}
}
}
}
void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pfunc)
{
TLGraph *tgraph = (TLGraph*)graph;
int *visited = NULL;
int condition = (tgraph != NULL);
condition = condition && (0 <= v) && (v < tgraph->count);
condition = condition && (pfunc != NULL);
//申请标记数组空间,并初始化为0
condition = condition && ((visited = (int*)calloc(tgraph->count, sizeof(int))) != NULL);
if(condition)
{
//以v为初始顶点,递归访问它的“子结点”,程序转向recursive_dfs函数执行
recursive_dfs(tgraph, v, visited, pfunc);
//recursive_dfs函数执行完毕后,检查是否还有结点没有被遍历,如果有,再以它为
//初始顶点,递归访问它的”子结点”
for(int i = 0; i < tgraph->count; i++)
{
if(!visited[i])
{
recursive_dfs(tgraph, i, visited, pfunc);
}
}
}
free(visited);
visited = NULL;
}
6、BFS 示例
7、BFS 算法描述
注意:因为BFS是一种层次遍历,所以该算法需要借助队列来实现!
8、BFS 算法实现
/*
广度优先,遍历graph所指图中的每个顶点
* 参数:
graph: 指向图的指针
v: 起始顶点
pfunc: 显示回调函数
* 返回值:
无
*/
static void bfs(TLGraph *tgraph, int v, int *visited, LGraph_Printf* pfunc)
{
//创建一个队列
LinkQueue *queue = LinkQueue_Create();
if(queue != NULL)
{
//因为队列实现中保存的是地址,所以该值不能为0(即NULL),而结点序号v可能为0,
//因此我们在v上加一个基地址tgraph->data,构成一个”虚拟地址”,使用时再减去
LinkQueue_Append(queue, tgraph->data + v);
visited[v] = 1;
//循环访问队列中的结点,直到队列为空
while (LinkQueue_Length(queue) > 0)
{
//转换“虚拟地址”为真实序号
int temp = (LVertex**)LinkQueue_Retrieve(queue) - tgraph->data;
//访问该结点
pfunc(tgraph->data[temp]);
printf("\t");
TListnode *node = NULL;
//访问该结点后,遍历它的所有”子结点“,如果它没有被访问,则将它加入队列
//以备遍历,如此循环
for(int i = 0; i < List_Length(tgraph->la[temp]); i++)
{
node = (TListnode*)List_Get(tgraph->la[temp], i);
if(node != NULL)
{
if(!visited[node->v])
{
LinkQueue_Append(queue, tgraph->data + node->v);
visited[node->v] = 1;
}
}
}
}
}
LinkQueue_Destroy(queue);
}
void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pfunc)
{
TLGraph *tgraph = (TLGraph*)graph;
int *visited = NULL;
int condition = (tgraph != NULL);
condition = condition && ( 0<= v) && (v < tgraph->count);
condition = condition && (pfunc != NULL);
//申请标记数组空间,并初始化为0
condition = condition && ((visited = (int*)calloc(tgraph->count, sizeof(int))) != NULL);
if(condition)
{
//以v为初始顶点,开始遍历,程序转向bfs函数执行
bfs(tgraph, v, visited, pfunc);
//bfs函数执行完后,检查是否还有结点没有被遍历,如果有,则以它为顶点,继续遍历
for(int i = 0; i < tgraph->count; i++)
{
if(!visited[i])
{
bfs(tgraph, i, visited, pfunc);
}
}
}
free(visited);
visited = NULL;
}
9、完整源码下载
github地址:稍后更新…