深度优先搜索与广度优先搜索

基本概念:

对于某一组数据的搜索,除非这个数据结构支持特定的查找操作(例如unordered_map的查找根据哈希公式找到对应位置,时间复杂度是O(1)),否则就要采用遍历的方式进行搜索(例如链表的搜索就是遍历的方式)。

对一组数据的搜索需要:
(1)每个结点都要访问一次;
(2)每个结点仅仅访问一次;
(3)对于结点访问顺序的不同,分为:

深度优先遍历(DFS = Depth First Search);
广度优先遍历(BFS = Breadth First Search);

除二者之外当然还有其他的搜索优先顺序,例如:优先级优先搜索,或自定义的搜索优先方式。

按优先级搜索的方式更适用于许多现实中的算法,这样的算法一般被称为启发式搜索,属于深度学习的领域。例如百度的搜索、抖音的推荐算法等,都是按照优先级优先的搜索结果。

深度优先搜索的写法:

用递归或者用栈。
先下探到最深层次的结点,再递归回到上一层,再找上一层是否有其他子结点。

深度优先搜索算法是一种用于遍历或搜索 树或图 的算法。

一个深度优先搜索二叉树的代码模板:(根左右)

//stack迭代方式:(回溯)
vector<int> result;
void binaryTreeDfs(Node* root) {
    if(root == nullptr) return;
    stack<Node*> s;
    s.push(root);
    while(!s.empty()) {
		Node* cur = s.top();
		s.pop();
		result.push_back(cur->val);
		if(cur->right != nullptr) s.push(cur->right); //先保存回溯点right子结点
		if(cur->left != nullptr) s.push(cur->left);
	}
	return;
}

所谓回溯,即在遍历之时,就给自己留好退路(回溯点),当这条路走到尽头,可直接跳转到回溯点。

从二叉树的栈迭代方式的实现,就可以深刻体会到这一点:

if(cur->right != nullptr) stack.push(cur->right); //right就是回溯点
if(cur->left != nullptr) stack.push(cur->left);
//先把自己的退路right子结点(回溯点)压入栈中,等把left左分支都遍历完之后,就可以从right子结点方向重新开始

使用递归法实现的先序深度优先搜索:

//先序:根左右
vector<int> result;
void binaryTreeDfs(Node* root) {
	travelTree(root);
	return;
}
void travelTree(Node* root) {
	if(node == nullptr) return;
	result.push_back(node->val);
	travelTree(root->left);
	travelTree(root->right);
}

广度优先搜索的写法:

使用迭代+队列。

在现实中,例如滴水波、冲击波,都是按层 一层一层的遍历。

至于为什么要用这样的方式去实现深度优先搜索和广度优先搜索,这些都是前人经过大量的实验、论证后得出的公认的原理,现阶段只需要记住怎么用就可以了。

一个广度优先搜索二叉树的代码模板:

//BFS:广度优先搜索:
class Solution {
public:
	vector<int> levelOrder(TreeNode* root) {
		if(root == nullptr) return result;
		queue<TreeNode*> q;
		q.push(root);
		while(!q.empty()) {
			TreeNode* tmp = q.front();
			q.pop();
			result.push_back(tmp->val);
			if(tmp->left != nullptr) q.push(tmp->left);
			if(tmp->right != nullptr) q.push(tmp->right);
		}
		return result;
	}
private:
	vector<int> result;
};

为什么使用队列可以实现广度优先搜索:
root结点单独处理一次,先入队列,随后每到一层,就逐次将它的下一层入队,这样就实现了一层一层的入队出队。

通过比较理解深度优先遍历与广度优先遍历的异同:

  1. 深度优先遍历常用的数据结构是 ,广度优先遍历常用的数据结构是 队列
  2. 深度优先遍历的思想是从上到下,把一个分支遍历完毕,再返回到上一层,对上一层的右子树继续深搜,直到整棵树都遍历完,因此符合栈的后进先出的特点;
    广度优先搜索是从左到右,因此符合队列的特点;
  3. 对于二叉树的深度优先搜索,有三种方法:前、中、后、序;
  4. 深度优先搜索与广度优先搜索的特点:
    (1)DFS:
    不全部保留结点,占用空间少;
    有回溯操作(即入栈、出栈),运行速度慢;(时间换空间)
    (2)BFS:
    保留全部结点,占用空间大;
    无回溯操作,运行速度快。(空间换时间)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值