图的广度优先遍历

图的广度优先遍历与二叉树的层序遍历思想类似,原理见代码:

void BFS(int v)
{
	node_ptr w;
	queue_ptr front,rear;
	front = rear = NULL;
	Visit(v);
	visited[v] = TRUE;
	addq(&front,&rear,v);
	while(front)
	{
		v = deleteq(&front);
		printf("->%d<-\n",v);
		for(w=graph[v];w;w=w->link)
			if(!(visited[w->vertex]))
			{
				Visit(w->vertex);
				addq(&front,&rear,w->vertex);
				visited[w->vertex] = TRUE;
			}
	}
}
测试程序:

#include <stdio.h>
#include <malloc.h>


#define MAX_VERTEX_NUM 50 
#define FALSE 0
#define TRUE 1

typedef struct node* node_ptr;
typedef struct node
{
	int vertex;
	node *link;
}node;
node_ptr graph[MAX_VERTEX_NUM];
short int visited[MAX_VERTEX_NUM];

typedef struct queue *queue_ptr;
typedef struct queue
{
	int vertex;
	queue_ptr link;
}queue;

void addq(queue_ptr *Qhead,queue_ptr*Qrear,int v)
{
	queue_ptr pt = (queue_ptr)malloc(sizeof(queue));
	pt->vertex = v;
	pt->link = NULL;
	if(*Qhead == NULL)
	{
		*Qhead = *Qrear = pt;
	}
	else
	{
		(*Qrear)->link = pt;
		(*Qrear) = pt;
	}
}
int deleteq(queue_ptr *Qhead)
{
	if(*Qhead)
	{
		int v = (*Qhead)->vertex;
		queue_ptr pt = (*Qhead)->link;
		free(*Qhead);
		*Qhead = pt;
		return v; 
	}
	return -1;
}

void ResetVisited(short int visited[],int node_num)
{
	for (int i=0;i<node_num;i++)
		visited[i] = FALSE;
}
void BuildGraph(node_ptr *graph,int node_num)
{
//	InitGraph(graph,node_num);
	int v;
	for(int i=0;i<node_num;i++)
	{
		while(1)
		{	
			scanf("%d",&v);
			if(v == -1)
			{
				break;
			}
			else
			{
				/*insert to head*/ 
				node_ptr ptr = (node_ptr)malloc(sizeof(node)) ;
				ptr->vertex = v - 1;
				ptr->link = graph[i];
				graph[i] = ptr;				
			}
		}
	}
}

void GraphShow(node_ptr *graph,int node_num)
{
	for(int i=0;i<node_num;i++)
	{
		node_ptr tmp = graph[i];
		printf("%d",i+1);
		while(tmp) 
		{
			printf("->%d",tmp->vertex+1);
			tmp = tmp->link;
		}
		printf("->#\n");
	}
}

void ClearGraph(node_ptr *graph,int node_num)
{
	for(int i=0;i<node_num;i++)
	{
		node_ptr tmp = graph[i];
		while(tmp)
		{
			graph[i]  = tmp->link;
			free(tmp);
			tmp = graph[i];
		}
//		graph[i] = NULL;	
	}	 
}

void Visit(int v)
{
	printf("Visiting Vertex : %d\n",v+1);
}

void  DFS(int v)
{
	node_ptr p;
	visited[v] = TRUE;
	Visit(v);
	for(p=graph[v];p;p=p->link)
		if(!(visited[p->vertex]))
			DFS(p->vertex);
}

void BFS(int v)
{
	node_ptr w;
	queue_ptr front,rear;
	front = rear = NULL;
	Visit(v);
	visited[v] = TRUE;
	addq(&front,&rear,v);
	while(front)
	{
		v = deleteq(&front);
		//printf("->%d<-\n",v);
		for(w=graph[v];w;w=w->link)
			if(!(visited[w->vertex]))
			{
				Visit(w->vertex);
				addq(&front,&rear,w->vertex);
				visited[w->vertex] = TRUE;
			}
	}
}
int main()
{
	ResetVisited(visited,5);
	ClearGraph(graph,5);
	BuildGraph(graph,5);

	GraphShow(graph,5);
	printf("DFS:\n");
	DFS(3);
	
	ResetVisited(visited,5);
	printf("BFS:\n");
	BFS(3);
	ClearGraph(graph,5);

	
} 
测试输入:

2 3 -1
4 1 -1
1 4 -1
2 3 5 -1
4 -1
测试输出:

1->3->2->#
2->1->4->#
3->4->1->#
4->5->3->2->#
5->4->#
DFS:
Visiting Vertex : 4
Visiting Vertex : 5
Visiting Vertex : 3
Visiting Vertex : 1
Visiting Vertex : 2
BFS:
Visiting Vertex : 4
Visiting Vertex : 5
Visiting Vertex : 3
Visiting Vertex : 2
Visiting Vertex : 1

REF:

1,数据结构(C语言版) Ellis Horowitz



基于邻接表存储的广度优先搜索遍历和树的层序遍历原理相同,采用队列来实现BFS,同时会用到辅助数组Visited数组,其余根据BFS的基本原理实现即可,实现过程较为简单[^2]。 给定一个无向G,用邻接表作为的存储结构进行广度优先遍历,需输出G的广度优先遍历序列,并在遍历过程中计算G的连通分量个数。在遍历过程中,若同时出现多个待访问的顶点,则优先选择编号最小的一个进行访问[^3]。 以邻接表为例,广度优先遍历的计算方法是对于一个节点,访问它的所有邻接节点,并按某种顺序(例如按照节点编号、字母顺序等)递归地进行遍历。一旦遍历完成后,返回到上一个节点,继续遍历其他邻接节点[^4]。 需要注意的是,对于稀疏来说,虽然邻接表的广度优先遍历比较复杂,但相比邻接矩阵,邻接矩阵在广度优先遍历时因较多位置为空却仍需检查是否为空,相对更吃亏,所以还是会采用邻接矩阵的广度优先遍历[^1]。 以下为简单的Python代码示例,用于演示基于邻接表的广度优先遍历: ```python from collections import deque def bfs(graph, start): visited = set() queue = deque([start]) visited.add(start) result = [] while queue: vertex = queue.popleft() result.append(vertex) for neighbor in sorted(graph[vertex]): if neighbor not in visited: queue.append(neighbor) visited.add(neighbor) return result # 示例的邻接表表示 graph = { 0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2] } start_vertex = 0 bfs_result = bfs(graph, start_vertex) print("广度优先遍历结果:", bfs_result) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值