BFS—— Breadth First Search 广度优先算法

2024-06-06 09:38

本文主要是介绍BFS—— Breadth First Search 广度优先算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Breadth First Search


              



         BFS家伙还是很有用的,特地从wiki扒了一个动态的图,来帮助感性的理解这个动态搜索的过程。


对于如下一个无权值的有向图,在进行广度优先搜索呢?这里我们的代码实现是,以节点3为入口



对于BFS的理论基础介绍,个人觉得还是看《DSAA》比较好.这里不做介绍,注重分析该搜索算法的实现。

如果对于图这种数据结构不熟悉,这个BFS一般是搞不定的...

下面分别是无向图的邻接表实现和邻接矩阵实现

http://blog.csdn.net/cinmyheart/article/details/41381845

http://blog.csdn.net/cinmyheart/article/details/41370465

---------------------------------------------


如果看过上面的图的实现,看下面的代码应该是非常“熟悉”的。很部分都是在上面的图基础上修改而来的。


首先我们,这里对图进行抽象,然后把关键的实现的API 放到头文件中。

/************************************************************
code file	: BFS.h
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:This file is a header file for out test program.
We are using digraph but not undirected graph in BFS.************************************************************/#ifndef _BFS_H_
#define _BFS_H_#include <stdio.h>#include <stdlib.h>#define CONNECTED    1#define DISCONNECTED 0#define SUCCESS  0#define FAILED  -1#define QUEUE_SIZE 10#define ARRAY_SIZE 20#define EMPTY_QUEUE   -1#define UNEMPTY_QUEUE  0 /***	We use these macro as index for struct table*/#define KNOW_OFFSET 0 //vertex that have been found#define DIST_OFFSET 1 //distance of vertex#define PATH_OFFSET 2 //parent vertex of current vertex#define FOUND	    1#define NOT_FOUND   0/***	Liitle trick. I use minus one to ** represent positive infinite :)*/#define INFINITE   -1#define ENTRY_POINT 3struct node{struct node* previous;struct node* next;int data;};struct vertex{int value;struct vertex* next;struct vertex* end;};struct graph{int num_vertex;int num_edge;struct vertex adjacent[0];};struct table{int height;int width;int msg[0];//we store message of table in this array.};void unweighted_path(struct table* p_table,struct graph* p_graph);struct graph* init_graph(int vertex,int edge);void   release_graph(struct graph* p_graph);int add_edge(struct graph* p_graph,char from_v,char to_v);int print_graph(struct graph* p_graph);/***	Creat and desctory a table which's size is row*col.*/struct table* init_table(int row,int col);void table_print(struct table* p_table);void release_table(struct table* p_table);/***	I implement some API to use ADT-Queue*/int queue_destory(struct node* p_queue_tail);int queue_enter(struct node** pp_queue_header,struct node** pp_queue_tail,int number);int queue_init(struct node** pp_queue_header,struct node** pp_queue_tail);int queue_out(struct node** pp_queue_header,struct node** pp_queue_tail);void queue_print(struct node* p_queue_tail);#endif

add_edge.c

/************************************************************
code file	: add_edge.c
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:This function will help us to add a new connection
between different vertex which is in the graph.*************************************************************/
#include "BFS.h"int add_edge(struct graph* p_graph,char from_v,char to_v)
{if(!p_graph || from_v < 0 || to_v < 0){return FAILED;}struct vertex* p_to_v    = (struct vertex*)malloc(sizeof(struct vertex));if(!p_to_v){printf("malloc failed in function %s()\n",__FUNCTION__);return FAILED;		}if(!(p_graph->adjacent[from_v].end)){p_graph->adjacent[from_v].next  = p_to_v;p_graph->adjacent[from_v].end   = p_to_v;p_to_v->next  = NULL;p_to_v->value = to_v;}else{p_graph->adjacent[from_v].end->next = p_to_v;p_graph->adjacent[from_v].end       = p_to_v;//update the new end node.p_to_v->next  = NULL;p_to_v->value = to_v;}return SUCCESS;
}

init_graph.c

/************************************************************
code file	: init_graph.c
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:This function is used for initializing the graph
with inputed parameter @vertex and @edge.************************************************************/
#include "BFS.h"struct graph* init_graph(int num_vertex,int num_edge)
{if(num_vertex <= 0 || num_edge <= 0){return NULL;}struct graph* p_graph = NULL;p_graph = (struct graph*)malloc(sizeof(struct graph) +\num_vertex*sizeof(struct vertex));if(!p_graph){printf("malloc failed in function %s()\n",__FUNCTION__);return NULL;}p_graph->num_vertex = num_vertex;p_graph->num_edge   = num_edge;int temp = 0;//initialize the adjacent relationshipfor(temp = 0;temp < num_vertex;temp++){p_graph->adjacent[temp].value = temp;p_graph->adjacent[temp].next  = NULL;p_graph->adjacent[temp].end   = NULL;}return p_graph;
}

init_table.c

/************************************************************
code file	: init_table.c
code writer	: EOF
code date	: 2014.11.23
e-mail		: jasonleaster@gmail.comcode description:This function will help us to create a table which's
size is @row multiply @col. And the size of each unit int
this table is sizeof(int).************************************************************/#include "BFS.h"struct table* init_table(int row,int col)
{if(row <= 0 || col <= 0){return NULL;}struct table* p_table = (struct table*)malloc(sizeof(struct table) + row*col*sizeof(int));if(!p_table){return NULL;}p_table->height = row;p_table->width  = col;int num_row = row;int num_col = col;//We must initialize the table !for(row = 0;row < num_row;row++){*((int*)(p_table->msg) + row*num_col + KNOW_OFFSET) = NOT_FOUND;if(row != ENTRY_POINT){*((int*)(p_table->msg) + row*num_col + DIST_OFFSET) = INFINITE;}else{*((int*)(p_table->msg) + row*num_col + DIST_OFFSET) = 0;}*((int*)(p_table->msg) + row*num_col + PATH_OFFSET) = 0;}return p_table;
}


/************************************************************
code file	: print_graph.c
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:This function will print out the connection of graph
which @p_graph point to.************************************************************/#include "BFS.h"int print_graph(struct graph* p_graph)
{if(!p_graph){return FAILED;}int from_v = 0;int to_v = 0;int num_vertex = p_graph->num_vertex;struct vertex* p_vertex = NULL;for(from_v = 0;from_v < num_vertex;from_v++){	p_vertex = &(p_graph->adjacent[from_v]);while(p_vertex){printf("\t%d",p_vertex->value);p_vertex = p_vertex->next;}printf("\n");}return SUCCESS;
}


/******************************************************************
code writer : EOF
code   date : 2014.09.13
e-mail : jasonleaster@gmail.com
Attention:Just a implementation of function queue_init. I would be
happy, if my code will help you to know what is queue.
we assuem that ...Input data ---> tail | | |queue| | |  header ---> Output dataIf something wrong with my code please touch me by e-mail.*******************************************************************/
#include "BFS.h"int queue_init(struct node** pp_queue_header,struct node** pp_queue_tail)
{(*pp_queue_header) = NULL;(*pp_queue_tail)   = NULL;return SUCCESS;	
}



/****************************************************************
code writer : EOF
code date: 2014.03.07
e-mail: jasonleaster@gmail.com
code purpose:Just a implementation of function queue_enter. I would be
happy, if my code will help you to know what is queue.
****************************************************************/
#include "BFS.h"int queue_enter(struct node** pp_queue_header ,struct node** pp_queue_tail,int number)
{struct node* p_new_node = NULL;struct node* p_temp_node = NULL;p_new_node = (struct node*)malloc(sizeof(struct node));if(p_new_node == NULL){printf("malloc error!\nqueue enter failed\n");return FAILED;}if(!(*pp_queue_tail))	{*pp_queue_tail   = p_new_node;*pp_queue_header = p_new_node;p_new_node->data = number;//Before 2014.11.22, I forgot to add this line and this is a //little bug, but now everything goes right after I adding this :)p_new_node->previous = NULL;p_new_node->next     = NULL;}else{p_temp_node = (*pp_queue_tail);p_new_node->data = number;p_new_node->next = p_temp_node;p_new_node->previous = NULL;p_temp_node->previous = p_new_node;(*pp_queue_tail) = p_new_node;}return SUCCESS;
}

/***********************************************************************
code writer : EOF
code date : 2014.09.13
e-mail: jasonleaster@gmail.com
code purpose:Just a implementation of function queue_out. I would be
happy, if my code will help you to know what is queue.If something wrong with my code, please touch me by e-mail.************************************************************************/
#include "BFS.h"int queue_out(struct node** pp_queue_header,struct node** pp_queue_tail)
{struct node* p_temp_node = NULL;int ret = 0;if( !(*pp_queue_header)){/***	There is no way to check the return value.** when we use "queue_out()". So, you needn't to do** that.*/printf("ATTENTION! There is nothing in the queue.\n");return EMPTY_QUEUE;}p_temp_node = (*pp_queue_header);(*pp_queue_header) = (*pp_queue_header)->previous;if(*pp_queue_header)//If there are not only one element left in the queue{(*pp_queue_header)->next = NULL;}else{*pp_queue_tail   = NULL;*pp_queue_header = NULL;}ret = p_temp_node->data;free(p_temp_node);p_temp_node = NULL;return ret;
}


/******************************************************************************
code writer : EOF
code date : 2014.03.07
e-mail: jasonleaster@gmail.com
code purpose:Just a implementation of function queue_print. I would be
happy, if my code will help you to know what is queue.If something wrong with my code, please touch me by e-mail.***********************************************************************************/#include "BFS.h"
void queue_print(struct node* p_queue_tail)
{struct node* p_temp_node = NULL;p_temp_node = p_queue_tail;printf("queue data at this time:\n");while(p_temp_node != NULL){printf("%d ",p_temp_node->data);p_temp_node = p_temp_node->next;}printf("\n");
}

/*********************************************************************
code writer : EOF
code date : 2014.03.07
e-mail: jasonleaster@gmail.com
code purpose:Just a implementation of function queue_enter. I would be
happy, if my code will help you to know what is queue.
*******************************************************************/
#include "BFS.h"int queue_destory(struct node* p_queue_tail)
{if(!p_queue_tail){return SUCCESS;}struct node* p_temp_node = NULL;p_temp_node = p_queue_tail->next;while(p_temp_node != NULL){p_queue_tail->next = p_temp_node->next;free(p_temp_node);p_temp_node = p_queue_tail->next;}	free(p_queue_tail);return SUCCESS;
}


/************************************************************
code file	: release_graph.c
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:It's easy and convenient for us to call this API once
and free all the graph.*************************************************************/
#include "BFS.h"void release_graph(struct graph* p_graph)
{if(!p_graph){return ;}int temp = 0;int num_vertex = p_graph->num_vertex;struct vertex* p_temp = NULL;for(temp = 0;temp < num_vertex;temp++){if(p_graph->adjacent[temp].next){p_temp = (p_graph->adjacent[temp].next->next);while(p_temp){free(p_graph->adjacent[temp].next);p_graph->adjacent[temp].next = p_temp;p_temp = p_temp->next;}free(p_graph->adjacent[temp].next);}}free(p_graph);
}


#include "BFS.h"void release_table(struct table* p_table)
{if(!p_table){return;}free(p_table);
}

#include "BFS.h"void table_print(struct table* p_table)
{if(!p_table){return;}int row_num = p_table->height;int col_num = p_table->width;int row = 0;int know = 0;int dist = 0;int path = 0;printf("\tknow\tdist\tpath\n");for(row = 0;row < row_num;row++){know = p_table->msg[row*col_num + KNOW_OFFSET];switch(know){case FOUND:{printf("\tFound");break;}case NOT_FOUND:{printf("\tNFond");break;}default:printf("error value of varible @know\n");return;}dist = p_table->msg[row*col_num + DIST_OFFSET];switch(dist){case INFINITE:{printf("\tINF");break;}default:printf("\t%d",dist);}path = p_table->msg[row*col_num + PATH_OFFSET];switch(path){case 0:{printf("\t0");break;}default:printf("\tv%d",path);}printf("\n");}printf("\n\n\n");
}

/************************************************************
code file	: unweighted_path.c
code writer	: EOF
code date	: 2014.11.23
e-mail		: jasonleaster@gmail.comcode description:This function will do the work of searching.
This job is based on a ADT--Queue. You could read "BFS.h"
and find that decleration of these functions which is used
for Queue.************************************************************/#include "BFS.h"void unweighted_path(struct table* p_table,struct graph* p_graph)
{if(!p_table || !p_graph){return;}struct node* p_queue_tail;struct node* p_queue_header;queue_init(&p_queue_header,&p_queue_tail);	queue_enter(&p_queue_header,&p_queue_tail,p_graph->adjacent[ENTRY_POINT].value);int vertex_index = 0;struct vertex* p_vertex = NULL;while(!!p_queue_header){vertex_index = queue_out(&p_queue_header,&p_queue_tail);printf("v%d dequeue\n",vertex_index);*((int*)(p_table->msg)\+ vertex_index*(p_table->width) + KNOW_OFFSET) = FOUND;p_vertex = (struct vertex*)p_graph->adjacent + vertex_index;p_vertex = p_vertex->next;for(;p_vertex;p_vertex = p_vertex->next){if(*((int*)(p_table->msg) \+ (p_vertex->value)*(p_table->width)+ DIST_OFFSET ) == INFINITE){*((int*)(p_table->msg) \+ (p_vertex->value)*(p_table->width)+ DIST_OFFSET ) = \*((int*)(p_table->msg)\+ (vertex_index)*(p_table->width)\+ DIST_OFFSET) + 1;*((int*)(p_table->msg) \+ (p_vertex->value)*(p_table->width)+ PATH_OFFSET ) = vertex_index;queue_enter(&p_queue_header,&p_queue_tail,p_vertex->value);}}table_print(p_table);}queue_destory(p_queue_tail);
}



测试主程序:
/****************************************************************
code file	: test_graph.c
code writer	: EOF
code date	: 2014.11.22
e-mail		: jasonleaster@gmail.comcode description:This test program is used for testing BFS.*****************************************************************/
#include "BFS.h"int main()
{struct graph* p_graph = NULL;FILE* fp = fopen("./text.txt","r+");if(!fp){printf("fopen() failed!\n");return 0;}int ret    = 0;int vertex = 0;int edge   = 0;int from_v = 0;int to_v   = 0;fscanf(fp,"%d",&vertex);fscanf(fp,"%d",&edge);p_graph = init_graph(vertex,edge);int temp = 0;for(temp;temp < edge;temp++){/***	I think it's necessary to check the returned value** of scanf() family.*/ret = fscanf(fp,"%d %d",&from_v,&to_v);if(ret != 2){break;}add_edge(p_graph,from_v,to_v);}struct table* p_table =  init_table(vertex,3);unweighted_path(p_table,p_graph);print_graph(p_graph);release_table(p_table);release_graph(p_graph);fclose(fp);return 0;
}


测试用文本文件text.txt:


测试结果:

图的邻接关系表示及实际图对照



由出队的顺序,各个元素出对后的table的情况




最后,所有的节点都会被检索到(0节点不考虑,这里我们初始数据中没有0节点,这是哑节点~)

我们可以知道,Found 0 0 的是入口节点,即节点3,而Found 1 v3,表示距离初始节点有1个edge距离,而该节点的上一个节点为v3, 同样的,Found 3 v4 表示,距离初始节点有3个edge距离,而该节点的上一个节点为v4.











这篇关于BFS—— Breadth First Search 广度优先算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035743

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s