图的遍历 - 广度优先

204 阅读3分钟

广度优先思想

广度优先(breadth first search): 先被访问的顶点, 其邻接点也先被访问, 借助visited[]数组来记录顶点是否已经被访问

邻接矩阵广度优先

图:

image.png

对应邻接矩阵:

image.png

初始化数组visit:

visit[0] = 0; visited[1] = 0; ...; visit[4] = 0;

顶点入队列流程

  • 顶点a入队列

visited[0] = 1;(表示a这个顶点已经被访问了)

image.png

  • 顶点a出队列, 通过邻接矩阵找到a的邻接点: b, c, e, 入队列

visited[1] = 1;(表示b这个顶点已经被访问了)

visited[2] = 1;(表示c这个顶点已经被访问了)

visited[4] = 1;(表示e这个顶点已经被访问了)

image.png

  • 顶点b出队列, 通过邻接矩阵找到b的邻接点且未被访问过: 不存在

image.png

  • 顶点c出队列, 通过邻接矩阵找到c的邻接点且未被访问过: d 入队列

visited[3] = 1;(表示d这个顶点已经被访问了)

image.png

  • 顶点e出队列, 通过邻接矩阵找到e的邻接点且未被访问过: 不存在

image.png

  • 顶点d出队列, 通过邻接矩阵找到d的邻接点且未被访问过: 不存在

image.png

整体流程

image.png

邻接矩阵广度优先步骤

  1. 创建数组: 用于表示顶点是否被访问过,并将该数组清零;
  2. 创建队列: 用于存放顶点的下标(不是存放顶点信息!因为下标更易操作);
  3. 从起始点出发, 访问标记, 并将该点入队列;
  4. 顶点出队列后, 依次访问该顶点未被访问过的邻接点, 并标记, 入队列
  5. 结束遍历的条件: 队列为空, 结束遍历.

代码实现(c语言)

void BFS_AMG(struct AMG_Graph* graph)
{
	int u;
	int i;
	int visited[MAX] = { 0 };
	printf("%c ", graph->Vex[0]); // 访问
	visited[0] = 1; // 标记
	enqueue(0); // 入队列

	while (!is_empty()) // 广度优先遍历结束的条件
	{
		u = dequeue(); // 出队列
		for (i = 0; i<graph->vex_num; ++i)
		{
			if ((graph->Edge[u][i] == 1) && (visited[i] == 0)) // 是否访问的条件
			{
                                printf("%c ", graph->Vex[i]); // 访问
				visited[i] = 1; // 标记
				enqueue(i); // 入队列
				
			}
		}
	}
	printf("\n");
}

完整版代码(c语言)

  • 队列头文件 - queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdio.h>

#define SIZE 512

void enqueue(int n);
int dequeue(void);
int is_empty(void);
int is_full(void);

extern int queue[SIZE];

#endif
  • 有向图邻接矩阵头文件 - directed_graph.h
#ifndef __DIRECTED_GRAPH_H__
#define __DIRECTED_GRAPH_H__

#define MAX 100

typedef struct connection {
	char tail;
	char head;
}connection;

typedef struct d_graph {
	int vex_num, edge_num;
	char Vex[MAX];
	connection con[MAX];
}d_graph;

struct AMG_Graph* Create_AMG_Graph(d_graph* d_graph_data);
void Show_AMG_Graph(struct AMG_Graph* graph);
int search_vex(struct AMG_Graph* graph, char c);
void BFS_AMG(struct AMG_Graph* graph);

#endif 
  • 队列文件 - queue.c
#include "queue.h" 

int queue[SIZE];

int head = 0, tail = 0;

void enqueue(int n)
{
	queue[tail] = n;
	tail = (tail + 1) % SIZE;
}

int dequeue(void)
{
	int n;
	n = queue[head];
	head = (head + 1) % SIZE;

	return n;
}

int is_empty(void)
{
	return head == tail;
}

int is_full(void)
{
	return (tail + 1) % SIZE == head;
}
  • 有向图邻接矩阵文件 - directed_graph.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
#include "directed_graph.h"

struct AMG_Graph
{
	int vex_num, edge_num;

	char Vex[MAX];
	int Edge[MAX][MAX];
};

struct AMG_Graph* Create_AMG_Graph(d_graph* d_graph_data)
{
	int i, j, a;
	char u, v;

	struct AMG_Graph* graph;

	graph = (struct AMG_Graph*)malloc(sizeof(struct AMG_Graph));

	graph->vex_num = d_graph_data->vex_num;
	graph->edge_num = d_graph_data->edge_num;

	for (i = 0; i < graph->vex_num; ++i)
		graph->Vex[i] = d_graph_data->Vex[i];

	for (i = 0; i < graph->vex_num; i++)
	{
		for (j = 0; j < graph->vex_num; j++)
			graph->Edge[i][j] = 0;
	}

	for(a=0; a<graph->edge_num; ++a)
	{
		u = d_graph_data->con[a].tail;
		v = d_graph_data->con[a].head;

		i = search_vex(graph, u);
		j = search_vex(graph, v);

		if (i != -1 && j != -1)
			graph->Edge[i][j] = 1;
		else
		{
			printf("You have entered wrong vex, please enter again.\n");
			return NULL;
		}
	}
	return graph;
}

void Show_AMG_Graph(struct AMG_Graph* graph)
{
	int i, j;

	printf("Show the vex: \n");
	for (i = 0; i < graph->vex_num; i++)
		printf("%c ", graph->Vex[i]);
	printf("\n");

	printf("Show the adjacency matrices:\n");
	for (i = 0; i < graph->vex_num; i++)
	{
		for (j = 0; j < graph->vex_num; j++)
			printf("%d\t", graph->Edge[i][j]);
		printf("\n");
	}
}

int search_vex(struct AMG_Graph* graph, char c)
{
	int i;

	for (i = 0; i < graph->vex_num; i++)
	{
		if (c == graph->Vex[i])
			return i;
	}

	return -1;
}

void BFS_AMG(struct AMG_Graph* graph)
{
	int u;
	int i;
	int visited[MAX] = { 0 };
	printf("%c ", graph->Vex[0]); // 访问
	visited[0] = 1; // 标记
	enqueue(0); // 入队列

	while (!is_empty())
	{
		u = dequeue(); // 出队列
		for (i = 0; i<graph->vex_num; ++i)
		{
			if ((graph->Edge[u][i] == 1) && (visited[i] == 0))
			{
				visited[i] = 1;
				enqueue(i);
				printf("%c ", graph->Vex[i]);
			}
		}
	}
	printf("\n");
}
  • 测试文件 - main.c
#include "directed_graph.h"
#include <stdlib.h>

d_graph* setData();

int main(void)
{
	d_graph* d_graph_data = setData();
	struct AMG_Graph* d_graph = Create_AMG_Graph(d_graph_data);
	Show_AMG_Graph(d_graph);

	printf("Traverse the graph through BFS:\n");
	BFS_AMG(d_graph);
	return 0;
}

d_graph* setData()
{
	d_graph* data = (d_graph*)malloc(sizeof(d_graph));
	data->vex_num = 5;
	data->edge_num = 7;

	data->Vex[0] = 'a';
	data->Vex[1] = 'b';
	data->Vex[2] = 'c';
	data->Vex[3] = 'd';
	data->Vex[4] = 'e';

	data->con[0].tail = 'a';
	data->con[0].head = 'b';

	data->con[1].tail = 'a';
	data->con[1].head = 'c';

	data->con[2].tail = 'a';
	data->con[2].head = 'e';

	data->con[3].tail = 'b';
	data->con[3].head = 'c';

	data->con[4].tail = 'c';
	data->con[4].head = 'd';

	data->con[5].tail = 'c';
	data->con[5].head = 'e';

	data->con[6].tail = 'd';
	data->con[6].head = 'e';

	return data;
}

运行结果如下

image.png