持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
深度优先遍历可以不用递归吗?
我们在工作中遇到的一些数据问题,很多都是可以用递归来实现.
如果一个递归搞不定的话,就再来一个递归!
但是我们都知道递归是非常耗时的,一旦数据量庞大起来,递归次数多了,这个时间是非常恐怖的。
如何吧一些递归问题给非递归化,来达到某一定的效率。通常递归转化为非递归用到了栈和队列
深度优先遍历可以不用递归吗? 答案是肯定的:
- 可以不用递归
- 用栈,就可以实现
- 因为递归本身就是栈
- 递归在代码的底层也是用栈来实现的 用二叉树的先序遍历举例(先遍历当前节点,再遍历左节点,再遍历右节点):
- 对于当前的节点来说
- 步骤一: 弹栈,拿到栈顶的节点
- 步骤二: 把右节点压栈
- 步骤三: 压入左节点 (这样弹栈的时候会先拿到左节点遍历,符合深度优先遍历要求)。
- 步骤四: 如果节点不为空,重复步骤 1, 如果为空,结束遍历。
整体思路还是比较清晰的,使用栈来将要遍历的节点压栈,然后出栈后检查此节点是否还有未遍历的节点,有的话压栈,没有的话不断回溯(出栈)。
有了思路,不难写出如下用栈实现的二叉树的深度优先遍历代;
我们用144. 二叉树的前序遍历 (前序遍历是深度优先遍历的一种)进行举例:
var preorderTraversal = function (root) {
if (root == null) {
return [];
}
let stack = []
let res = []
stack.push(root)
// 先遍历当前节点
while (stack.length !== 0) {
// 弹栈,拿到栈顶的节点,如果节点不为空,重复步骤
let treeNode = stack.pop()
res.push(treeNode.val)
// 先压右节点
if (treeNode.right != null) {
stack.push(treeNode.right);
}
// 再压左节点
if (treeNode.left != null) {
stack.push(treeNode.left);
}
}
return res
};
执行结果
题外话
二叉树的 前序、后序、中序遍历都可以套这种模板进行遍历,一招鲜吃遍天!