码迷,mamicode.com
首页 > 其他好文 > 详细

图的遍历

时间:2015-04-26 09:33:06      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:遍历   dfs   bfs   

图的遍历:
定义:从图中的某一顶点出发,沿着边访问访问图中其余顶点,且使每个顶点仅被访问一次。

通常有两种遍历次序方案:
?深度优先遍历(dfs)---类似于前序遍历
?广度优先遍历(bfs)---类似于层序遍历

?深度优先遍历(dfs)

算法思想描述:
访问起始顶点v 
当 v 还有邻接顶点未被访问时:(起始条件)
    ?深度遍历未访问的邻接顶点w
当 v 的所有邻接顶点都被访问时:
    ?若图中所有顶点均已访问,算法结束(终止条件)
    ?若图中还有未访问的顶点,以未访问顶点作为起始顶点深度遍历


?广度优先遍历(bfs)

算法思想描述:
1.访问其实顶点v0
2.依次访问v0的各个邻接点v01,v02...
3.假设最近一次访问的顶点依次为vi1,vi2...,则依次访问vi1,vi2...的未被访问的邻接点
4.重复3,直到所有顶点均被访问

在邻接链表中实现深度优先遍历(DFS)与广度优先遍历(BFS)
static void dfs_recursive(tl_graph* graph, int v, int *visited, graph_printf* p_func)
{
	int i = 0;
	
	p_func(graph->v[v]);
	
	visited[v] = 1;
	
	printf(", ");
	
	for(i=0; i<LinkList_Length(graph->la[v]); i++)
	{
		t_list_node* node = (t_list_node*)LinkList_Get(graph->la[v], i);
		
		if(!visited[node->v])
		{
			dfs_recursive(graph, node->v, visited, p_func);	
		}	
	}
	
} 

void DFS_traverse(LGraph* graph, int v, graph_printf* p_func)
{
	tl_graph* t_graph = (tl_graph*)graph;
	int *visited = NULL;
	int ok = 1;
	ok = (ok) && (t_graph != NULL) && (p_func != NULL);
	ok = (ok) && (0 <= v) && (v < t_graph->count);
	
	/*借鉴其申请数组空间的方式*/
	ok = (ok) && ((visited = (int*)calloc(t_graph->count, sizeof(int))) != NULL);
	
	if(ok)
	{
		int i = 0;
		
		dfs_recursive(t_graph, v, visited, p_func); 
		
		for(i=0; i<t_graph->count; i++)
		{
			if(!visited[i])
			{
				dfs_recursive(t_graph, i, visited, p_func);
			}	
		}
		
		printf("\n");
		
	}
	
	free(visited);
}

static void bfs_recursive(tl_graph* graph, int v, int visited[], graph_printf* p_func)
{
	LinkQueue* queue = LinkQueue_Create();
	
	if(queue != NULL)
	{
		int i = 0;
		t_list_node* node = NULL;
		visited[v] = 1;
		
		/*将在图中下标为v的顶点放入队列,
		又vk可能为0,而在实现队列时,传入队列的参数不能为零,
		则加上graph->v的基地址(graph->v只是一个无用的地址),从而避免v为0时的错误。
		在取出队列元素是应减去该基地址*/
		LinkQueue_Append(queue, graph->v + v);
		
		while( LinkQueue_Length(queue) > 0 )
		{
			/*传入的是标号地址,传出自然也是标号地址*/
			v = (l_vertex**)LinkQueue_Retrieve(queue) - graph->v;
			
			p_func(graph->v[v]);
			
			printf(", ");
			
			for(i=0; i<LinkList_Length(graph->la[v]); i++)
			{
				node = (t_list_node*)LinkList_Get(graph->la[v], i);
				
				if(!visited[node->v])
				{
					LinkQueue_Append(queue, graph->v + node->v);
					
					visited[node->v] = 1;	
				}
			} 
			
		} 
		
		
	}
	
	LinkQueue_Destroy(queue);
}

void BFS_traverse(LGraph* graph, int v, graph_printf* p_func)
{
	tl_graph* t_graph = (tl_graph*)graph;
	int *visited = NULL;
	int ok = 1;
	ok = (ok) && (t_graph != NULL) && (p_func != NULL);
	ok = (ok) && (0 <= v) && (v < t_graph->count);
	
	/*借鉴其申请数组空间的方式*/
	ok = (ok) && ((visited = (int*)calloc(t_graph->count, sizeof(int))) != NULL);
	
	if(ok)
	{
		int i = 0;
	
		bfs_recursive(t_graph, v, visited, p_func); 
		
		for(i=0; i<t_graph->count; i++)
		{
			if(!visited[i])
			{
				bfs_recursive(t_graph, i, visited, p_func);
			}	
		}
		
		printf("\n");
		
	}
	
	free(visited);
}



在邻接矩阵中实现深度优先遍历(DFS)与广度优先遍历(BFS):
/*参数说明:
graph:指向图头结点的指针
v:顶点在整个顶点数组下的标号
visited:标记访问的顶点
p_func:打印结点信息函数 
*/
static void dfs_recursive(tm_graph* graph, int v, int *visited, graph_printf* p_func)
{
	int i = 0;
	
	p_func(graph->v[v]);
	
	visited[v] = 1;
	
	printf(", ");
	
	for(i=0; i<graph->count; i++)
	{
		if((graph->matrix[v][i] != 0) && (!visited[i]))
		{
			dfs_recursive(graph, i, visited, p_func);
		}
	} 

	
} 

void DFS_traverse(MGraph* graph, int v, graph_printf* p_func)
{
	tm_graph* t_graph = (tm_graph*)graph;
	int *visited = NULL;
	int ok = 1;
	ok = (ok) && (t_graph != NULL) && (p_func != NULL);
	ok = (ok) && (0 <= v) && (v < t_graph->count);
	
	/*借鉴其申请数组空间的方式*/
	ok = (ok) && ((visited = (int*)calloc(t_graph->count, sizeof(int))) != NULL);
	
	if(ok)
	{
		int i = 0;
		
		dfs_recursive(t_graph, v, visited, p_func); 
		
		for(i=0; i<t_graph->count; i++)
		{
			if(!visited[i])
			{
				dfs_recursive(t_graph, i, visited, p_func);
			}	
		}
		
		printf("\n");
		
	}
	
	free(visited);
}

static void bfs_recursive(tm_graph* graph, int v, int visited[], graph_printf* p_func)
{
	LinkQueue* queue = LinkQueue_Create();
	
	if(queue != NULL)
	{
		int i = 0;
		visited[v] = 1;
		
		LinkQueue_Append(queue, graph->v + v);
		
		while( LinkQueue_Length(queue) > 0 )
		{
			v = (m_vertex**)LinkQueue_Retrieve(queue) - graph->v;
			
			p_func(graph->v[v]);
			printf(", ");
			
			for(i=0; i<graph->count; i++)
			{
				if((graph->matrix[v][i]) && (!visited[i]))
				{
					LinkQueue_Append(queue, graph->v + i);
					
					visited[i] = 1;
				}	
			}
			
		} 		
		
	}
	
	LinkQueue_Destroy(queue);
}

void BFS_traverse(MGraph* graph, int v, graph_printf* p_func)
{
	tm_graph* t_graph = (tm_graph*)graph;
	int *visited = NULL;
	int ok = 1;
	ok = (ok) && (t_graph != NULL) && (p_func != NULL);
	ok = (ok) && (0 <= v) && (v < t_graph->count);
	
	/*借鉴其申请数组空间的方式*/
	ok = (ok) && ((visited = (int*)calloc(t_graph->count, sizeof(int))) != NULL);
	
	if(ok)
	{
		int i = 0;
	
		bfs_recursive(t_graph, v, visited, p_func); 
		
		for(i=0; i<t_graph->count; i++)
		{
			if(!visited[i])
			{
				bfs_recursive(t_graph, i, visited, p_func);
			}	
		}
		
		printf("\n");
		
	}
	
	free(visited);
}

注:
1、对于层次遍历的操作,均需要借助队列实现
2、使用队列时的弊端(是因为实现时造成的弊端)
实现广度优先遍历时,传入队列元素的值不能为0 ,则需注意传入的图下标的值不能为零。可在下标值的基础上上增加一定的数值,之后用的时候再减去原先加上的值。

图的遍历

标签:遍历   dfs   bfs   

原文地址:http://blog.csdn.net/u011467781/article/details/45271923

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!