深度优先(DFS)、广度优先(BFS)、一致代价(UCS)搜索算法的实现(附代码)

Introduction
一、 深度优先搜索算法
从一个顶点v出发,首先将v标记为已遍历的顶点,然后选择一个邻接于v的尚未遍历的顶点u,如果u不存在,本次搜素终止。如果u存在,那么从u又开始一次DFS。如此循环直到不存在这样的顶点。
假设我们建立如下树
在这里插入图片描述
搜索过程如下:
在这里插入图片描述
首先编码,令S=1、a=2、b=3、c=4、d=5、e=6、f=7、g=8、h=9、r=10、p=11、q=12
重复点不再搜索,所以12个点最多24步搜索完毕
代码主要部分为

  1. 建立结构体,包含序号、状态、发现时刻、完成时刻、上下节点
  2. 字符与数字的互相转换函数
  3. DFS函数:根据判断下一个节点是否被发现过来搜索,若搜索过将会被标记,若没有节点将返回上一节点,并寻找新的节点
    在这里插入图片描述
  4. 并对节点路径显示
    在这里插入图片描述
    DFS实现代码
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <climits> 
using namespace std;
struct Node{//节点结构体
 	int Num;//节点序号,与节点一一对应
 	int State;//三种状态,0表示未被发现,1表示正在处理,2表示处理完成
 	int Find;//发现节点的时刻 
 	int Solve;//完成对节点处理的时刻 
 	vector<Node*> next;//存储所有的邻接节点 
 	Node* pre;
 	Node(int x):State(0),Num(x),Find(0),Solve(0),pre(NULL){
	 }
 }; 
void insert(Node* L,Node* n)
{
	L->next.push_back(n);
}
void display(Node* L)//显示该节点的所有邻接节点 
{
	int n=L->next.size();
	
	for(int i=0;i<n;i++)
	cout<<(L->next)[i]->Num<<"	";
}

void display2(int num)
{switch(num){
case 1:
	cout<<"s"<<endl;break;
case 2:
	cout<<"a"<<endl;break;
case 3:
	cout<<"b"<<endl;break;
case 4:
	cout<<"c"<<endl;break;
case 5:
	cout<<"d"<<endl;break;
case 6:
	cout<<"e"<<endl;break;
case 7:
	cout<<"f"<<endl;break;
case 8:
	cout<<"g"<<endl;break;
case 9:
	cout<<"h"<<endl;break;
case 10:
	cout<<"r"<<endl;break;
case 11:
	cout<<"p"<<endl;break;
case 12:
	cout<<"q"<<endl;break;
default:cout<<endl;
}
}

int time=0;//变量time是一个全局变量,用来计算时间

void dfs_v(Node* a[],int n,Node* u)
{
	time++;//时间加1
	u->Find=time;
	u->State=1;
	int n1=u->next.size();
	for(int i=0;i<n1;i++)//根据n1寻找下一个节点
	{
		Node* v=(u->next)[i];//判断下一个节点是否被处理过,若未被处理则继续
		if(v->State==0)
		{
			v->pre=u;//并存储上一节点
			dfs_v(a,n,v);//继续往下搜索
		}
	}
	u->State=2;
	time++;
	u->Solve=time;
 
 
}
void dfs(Node* a[],int n) //dfs搜索函数
{
	for(int i=0;i<n;i++)
	{
		Node* u=a[i];
		if(u->State==0)
		dfs_v(a,n,u);
	}
}
 
 
int main()
{
	Node* a[12];
	int b[12][12]={{5,6,11},{2},{2},{2},{3,4,6},{9,10},{4,8},{8},{11,12},{7},{12},{12}};

	cout<<"By drs"<<endl;
    for(int i=0;i<12;i++)
    {
   	 a[i]=new Node(i+1);
    }
    for(int j=0;j<12;j++)
    {
	 for(int i=0;i<12;i++)
   	 if(b[j][i])
   	 a[j]->next.push_back(a[b[j][i]-1]);
	 cout<<"节点"<<j+1<<"的下个节点为:	";
   	 display(a[j]);
	 cout<<endl;
    }
   //以上是构建一个有向图 
    dfs(a,12);
	cout<<endl;
	cout<<"搜索时序图......"<<endl;
//	搜索时序图
	cout<<"节点号"<<"	"<<"发现时刻"<<"	"<<"结束时间"<<endl;
    for(int m=0;m<12;m++){
		cout<<a[m]->Num<<"	"<<a[m]->Find<<"		"<<a[m]->Solve<<endl;
   
		}
   cout<<"搜索节点顺序:"<<endl;
   int n=1;
   while(n<25){
	      for(int m=0;m<12;m++){
			  if((n==(a[m]->Find))||(n==(a[m]->Solve))){
				  cout<<a[m]->Num<<"	";
				  display2(a[m]->Num);
				  break;
			  }   
		  }
		  n++;
   }
}





二、 广度优先搜索算法
按层次来遍历的,先是根节点,然后是第二层子节点,依次是第三层子节点,将节点分别放入队列中,每次从队列中探出首元素,遍历后的点放入closed表中,还未遍历的店放入open表中,当open表为空时,则整个数遍历完全。
假设我们建立如下树
在这里插入图片描述
搜索过程如下:
在这里插入图片描述
代码主要部分为

  1. 建立结构体,包含序号、状态、发现时刻、上下节点
  2. 字符与数字的互相转换函数
  3. BFS函数:首先按照层等级排列,一个层的顺序依次开始,然后根据本层节点搜索下一层节点,并判断下一层节点是否被搜索,若搜索过将跳过,并不能搜索。
  4. 并对节点路径显示、
    在这里插入图片描述
    BFS实现代码
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <climits> 
using namespace std;
struct Node{//节点结构体
 	int Num;//节点序号,与节点一一对应
 	int State;//三种状态,0表示未被发现,1表示正在处理,2表示处理完成
 	int Find;//发现节点的时刻 
 	vector<Node*> next;//存储所有的邻接节点 
 	Node* pre;
 	Node(int x):State(0),Num(x),Find(0),pre(NULL){
	 }
 }; 
void insert(Node* L,Node* n)
{
	L->next.push_back(n);
}
void display(Node* L)//显示该节点的所有邻接节点 
{
	int n=L->next.size();
	
	for(int i=0;i<n;i++)
	cout<<(L->next)[i]->Num<<"	";
}

void display2(int num)
{switch(num){
case 1:
	cout<<"s"<<endl;break;
case 2:
	cout<<"a"<<endl;break;
case 3:
	cout<<"b"<<endl;break;
case 4:
	cout<<"c"<<endl;break;
case 5:
	cout<<"d"<<endl;break;
case 6:
	cout<<"e"<<endl;break;
case 7:
	cout<<"f"<<endl;break;
case 8:
	cout<<"g"<<endl;break;
case 9:
	cout<<"h"<<endl;break;
case 10:
	cout<<"r"<<endl;break;
case 11:
	cout<<"p"<<endl;break;
case 12:
	cout<<"q"<<endl;break;
default:cout<<endl;
}
}

int time=0;//变量time是一个全局变量,用来计算时间戳

int bfs_v(Node* u[],int m)
{
	Node* c[12];
	int ww=0;
	for(int p=0;p<m;p++){
		u[p]->State=2;
		time++;
		u[p]->Find=time;
		for(int q=0;q<(u[p]->next.size());q++){//对当前层的某一个节点的下一层节点处理
			if((u[p]->next)[q]->State==0) {//判断是否搜索过
				c[ww]=(u[p]->next)[q];//添加到下一层
				ww++;//下一层数量加
				(u[p]->next)[q]->State=1;//状态为正在处理
			}
		}
		

	}

	if(ww==0)  return 0;
	bfs_v(c,ww);
}
 
void main()
{
	Node* a[12];
	Node* DD[12];
	int b[12][12]={{5,6,11},{2},{2},{2},{3,4,6},{9,10},{4,8},{8},{11,12},{7},{12},{12}};
	cout<<"By drs"<<endl;
    for(int i=0;i<12;i++)
    {
   	 a[i]=new Node(i+1);
    }
    for(int j=0;j<12;j++)
    {
	 for(int i=0;i<12;i++)
   	 if(b[j][i])
   	 a[j]->next.push_back(a[b[j][i]-1]);
	 cout<<"节点"<<j+1<<"的下个节点为:	";
   	 display(a[j]);
	 cout<<endl;
    }
   //以上是构建一个有向图 

	a[0]->State=2;
	DD[0]=a[0];
	bfs_v(DD,1);
	
	cout<<endl;
	cout<<"搜索时序图......"<<endl;
	//搜索时序图
	cout<<"节点号"<<"	"<<"发现时刻"<<"	"<<endl;

	    for(int m=0;m<12;m++){
		cout<<a[m]->Num<<"	"<<a[m]->Find<<"		"<<a[m]->State<<endl;
  		}

   cout<<"搜索节点顺序:"<<endl;
   int n=1;
   while(n<13){
	      for(int m=0;m<12;m++){
			  if((n==(a[m]->Find))){
				  cout<<a[m]->Num<<"	";
				  display2(a[m]->Num);
				  break;
			  }   
		  }
		  n++;
   }
   
}





三、 一致代价搜索算法
在BFS的基础上,一致代价搜索不在扩展深度最浅的节点,而是通过比较路径消耗,并选择当前代价最小的节点进行扩展,因此可以保证无论每一步代价是否一致,都能够找到最优解。
假设我们建立如下树
在这里插入图片描述
搜索过程如下:
在这里插入图片描述
代码(基于BFS完成)主要部分为

  1. 建立结构体,包含序号、状态、发现时刻、上下节点
  2. 字符与数字的互相转换函数
  3. UCS函数:首先按照层等级排列,一个层的顺序依次开始,然后根据本层节点搜索下一层节点,若在当前层的某一个节点的下一层发现目标节点,则开始寻求路径,根据前面保存的上下层关系返回到s层(出发点),关键部分代码如下。
    在这里插入图片描述
    在这里插入图片描述
  4. 并对节点路径显示、
    在这里插入图片描述
    UCS实现代码
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <climits> 
using namespace std;

struct Node{//节点结构体
 	int Num;//节点结构体,与节点一一对应
 	int State;//三种状态,0表示未被发现,1表示正在处理,2表示处理完成
 	int Find;//发现节点的时刻 
 	vector<Node*> next;//存储其对应的下一个节点 
 	Node* pre;//储存前一个节点,需要赋值完成
 	Node(int x):State(0),Num(x),Find(0),pre(NULL){//初始化
	 }
 }; 
void display2(int num)//序号与字母转换显示
{switch(num){
case 1:
	cout<<"s";break;
case 2:
	cout<<"a";break;
case 3:
	cout<<"b";break;
case 4:
	cout<<"c";break;
case 5:
	cout<<"d";break;
case 6:
	cout<<"e";break;
case 7:
	cout<<"f";break;
case 8:
	cout<<"g";break;
case 9:
	cout<<"h";break;
case 10:
	cout<<"r";break;
case 11:
	cout<<"p";break;
case 12:
	cout<<"q";break;
default:cout<<endl;
}
}
void insert(Node* L,Node* n)
{
	L->next.push_back(n);
}
void display(Node* L)//显示该节点的所有邻接节点 
{
	int n=L->next.size();
	
	for(int i=0;i<n;i++){
	display2((L->next)[i]->Num);
	cout<<"	";
	}
}


int Judge(char a){
switch(a){
case 's': return 1;
case 'a': return 2;
case 'b': return 3;
case 'c': return 4;
case 'd': return 5;
case 'e': return 6;
case 'f': return 7;
case 'g': return 8;
case 'h': return 9;
case 'r': return 10;
case 'p': return 11;
case 'q': return 12;
default:cout<<endl;
}

}


int time=0;//变量time是一个全局变量,用来计算时间



int ucs(Node* u[],int m,int aim)//ucs搜索最短路径,基于广度搜索完成
{
	Node* c[12];//定义节点数组,存放下一级节点数据
	Node* mm;//存放上一个节点变量
	int ww=0;//存放下一级节点个数
	int follow[12];//存放最短路径序号并排列
	time++;
	for(int p=0;p<m;p++){//当前节点级搜素并已读
		u[p]->State=2;
		u[p]->Find=time;
		for(int q=0;q<(u[p]->next.size());q++){//当前节点级的每一个节点的下一个节点,并排除已经被上一级和同级的下一级发现过得节点
		
			if((u[p]->next)[q]->State==0) (u[p]->next)[q]->pre=u[p];//若是未被搜索过得节点,才可以用来确定上一级节点,并储存上一级节点数据

			if((u[p]->next)[q]->Num==aim) {//序号为8即s,为要寻找的点
					mm=(u[p]->next)[q];//如果是则开始找寻前级节点
					follow[time]=mm->Num;
				for(int qq=0;qq<time;qq++){//根据时间顺序找前级节点个数以及序号
					mm=mm->pre;
					follow[time-qq-1]=mm->Num;//存储在数组中
				//	cout<<mm->Num<<"	";
				//	display2(mm->Num);
				}

				for(int qc=0;qc<time+1;qc++){//显示寻找顺序
					display2(follow[qc]);
					cout<<"	"<<follow[qc];
					cout<<endl;
				}
//				cout<<u[p]->Num<<endl;
//				display2(u[p]->Num);
//				cout<<(u[p]->pre)->Num<<endl;
			//	cout<< (((u[p]->next)[q])->pre).Num<<endl;
			cout<<"take: "<<time<<" steps"<<endl;
			return 0;

			}
			if((u[p]->next)[q]->State==0) {//若是未处理点,则保存到数组c,并变为正在处理状态
				c[ww]=(u[p]->next)[q];
				ww++;
				(u[p]->next)[q]->State=1;
			}
		}
		

	}
	ucs(c,ww,aim);
}


 
void main()
{
	Node* a[12];
	Node* DD[12];
	char abc;
	int b[12][12]={{5,6,11},{2},{2},{2},{3,4,6},{9,10},{4,8},{8},{11,12},{7},{12},{12}};
	cout<<"By drs"<<endl;
    for(int i=0;i<12;i++)
    {
   	 a[i]=new Node(i+1);
    }
    for(int j=0;j<12;j++)
    {
	 for(int i=0;i<12;i++)
   	 if(b[j][i])
   	 a[j]->next.push_back(a[b[j][i]-1]);
	 cout<<"节点";display2(j+1);cout<<"的下个节点为:	";
   	 display(a[j]);
	 cout<<endl;
    }
	   //以上是构建一个有向图过程

	a[0]->State=2;
	DD[0]=a[0];
	cout<<endl;

//	ucs(DD,1,8);
//	cout<<"以上为s到g的最短路径"<<endl;
	cout<<"请输入您想从s到达的点(小写字母s,a,b,c.....)";
	cin>>abc;
//	cout<<Judge(abc)<<endl;
	if(Judge(abc)!=1)ucs(DD,1,Judge(abc));
	else cout<<"需要0步"<<endl;
}





  • 30
    点赞
  • 132
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python可以通过使用队列来实现广度优先搜索BFS)、深度优先搜索DFS),以及使用优先队列来实现统一代价搜索UCS)。 BFS广度优先搜索): 广度优先搜索是一种层次遍历的搜索算法,通过使用队列来实现。算法从根节点开始,将其加入到队列中,并将其标记为已访问。然后,从队列中取出第一个节点,并将其未访问的相邻节点加入到队列中,依此类推,直到队列为空。下面是一个Python示例代码: ```python def bfs(graph, start): visited = set() queue = [start] while queue: node = queue.pop(0) if node not in visited: print(node) visited.add(node) neighbours = graph[node] for neighbour in neighbours: queue.append(neighbour) # 调用方法 graph = { 'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F'], 'D': [], 'E': ['F'], 'F': [] } bfs(graph, 'A') ``` DFS深度优先搜索): 深度优先搜索是一种通过递归实现搜索算法,算法通过深入到最底层的节点,然后回溯到上一级节点继续搜索。下面是一个Python示例代码: ```python def dfs(graph, start, visited=None): if visited is None: visited = set() visited.add(start) print(start) for next_node in graph[start]: if next_node not in visited: dfs(graph, next_node, visited) # 调用方法 graph = { 'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F'], 'D': [], 'E': ['F'], 'F': [] } dfs(graph, 'A') ``` UCS(统一代价搜索): 统一代价搜索是一种以路径的实际代价作为搜索优先级的算法,通过使用优先队列来实现。在搜索过程中,每个节点都被赋予一个代价,并且优先队列根据这些代价来选择节点。下面是一个Python示例代码: ```python import heapq def ucs(graph, start): visited = set() queue = [(0, start)] while queue: (cost, node) = heapq.heappop(queue) if node not in visited: print(node) visited.add(node) neighbours = graph[node] for neighbour, neighbour_cost in neighbours: if neighbour not in visited: heapq.heappush(queue, (cost + neighbour_cost, neighbour)) # 调用方法 graph = { 'A': [('B', 2), ('C', 1)], 'B': [('D', 3), ('E', 2)], 'C': [('F', 4)], 'D': [], 'E': [('F', 1)], 'F': [] } ucs(graph, 'A') ``` 以上就是Python实现BFSDFSUCS的简单示例。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值