当前位置:网站首页>二叉树的遍历:递归法/ 迭代法/ 统一迭代法(强QAQ)
二叉树的遍历:递归法/ 迭代法/ 统一迭代法(强QAQ)
2022-08-02 14:10:00 【鱼子酱:P】
最近刷题刷到二叉树...算法面试的常客,数据结构基石...
见到许多厉害的解法,膜拜啊~
特此记录一下2022/3/24
力扣对应题目:144,145,94
一:递归法
一看就会,一写就废!~简单解法
前序遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preorder(root, result);
return result;
}
public void preorder(TreeNode root, List<Integer> result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
}
中序遍历:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
inorder(root, res);
return res;
}
void inorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val); // 注意这一句
inorder(root.right, list);
}
}
后序遍历:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
postorder(root, res);
return res;
}
void postorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val); // 注意这一句
}
}
二:迭代法
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。so 可以用栈!
前序遍历:
// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return result;
}
}
中序遍历:
lass Solution {
public List<Integer> inorderTraversal(TreeNode root) {
//中序遍历:左中右 入栈顺序:左右
List<Integer> result = new ArrayList<>();
if (root == null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);//头结点入栈
cur = cur.left;//一直遍历放左节点,到最左的叶子结点,然后到else取出最左的结点,然后放右结点。左边-中间-右边
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}
后续遍历:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
//左右中 入栈顺序:中左右 出栈顺序:中右左 翻转:左右中
List<Integer> res = new ArrayList<>();
if(root == null){
return res;
}
Stack<TreeNode> stack1 = new Stack<>();
stack1.push(root);//头结点入栈
while(!stack1.isEmpty()){
TreeNode node = stack1.pop();
res.add(node.val);
if(node.left != null){
stack1.push(node.left);
}
if(node.right != null){
stack1.push(node.right);
}
}
Collections.reverse(res);
return res;
}
}
三:统一迭代法
迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。
其实针对三种遍历方式,使用迭代法是可以写出统一风格的代码!
重头戏来了,接下来介绍一下统一写法。
用栈的话,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
前序遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
//前序:中左右 入栈顺序:右左中
List<Integer> res = new ArrayList<>();//LinkedList也可以
Stack<TreeNode> st = new Stack<>();
if(root != null) st.push(root);
while(!st.empty()){
TreeNode node = st.peek();
if(node != null){
st.pop();//把该节点弹出,避免重复操作
if(node.right != null) st.push(node.right);
if(node.left != null) st.push(node.left);
st.push(node);
st.push(null);//中间结点访问过,但还没有处理,加入空节点标记
}else{
st.pop();//弹出空节点
node = st.pop();//取出被标记的结点
res.add(node.val);//加入res中
}
}
return res;
}
}
中序遍历:
后续遍历:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
//后序:左右中 入栈顺序:中右左
List<Integer> res = new LinkedList<>();
Stack<TreeNode> st = new Stack<>();
if(root != null ) st.push(root);
while(!st.empty()){
TreeNode node = st.peek();
if(node != null){
st.pop();//弹出该节点,避免重复
st.push(node);
st.push(null);//中方结点访问过,没处理,标记
if(node.right != null) st.push(node.right);
if(node.left != null) st.push(node.left);
}else{
st.pop();//把null结点弹出
node = st.pop();
res.add(node.val);
}
}
return res;
}
}
边栏推荐
- 7. How to add the Click to RecyclerView and LongClick events
- Win11系统找不到dll文件怎么修复
- 利用plot_surface命令绘制复杂曲面入门详解
- Win10系统设置application identity自动提示拒绝访问怎么办
- Publish module to NPM should be how to operate?Solutions to problems and mistake
- CS4398音频解码替代芯片DP4398完全兼容DAC解码
- ECP2459耐压60V降压BUCK电路用于WIFI模块供电方案原理图
- 用U盘怎么重装Win7系统?如何使用u盘重装系统win7?
- Compilation error D8021: Invalid numeric argument '/Wextra' cl command line error d8021 invalid numeric argument '/Wextra'
- KiCad Common Shortcuts
猜你喜欢
Win10无法连接打印机怎么办?不能使用打印机的解决方法
In-depth understanding of Golang's Map
Mysql lock
倍增和稀疏表
Win11 keeps popping up User Account Control how to fix it
win10无法直接用照片查看器打开图片怎么办
How to reinstall Win7 system with U disk?How to reinstall win7 using u disk?
[STM32 Learning 1] Basic knowledge and concepts are clear
4.发布帖子,评论帖子
推开机电的大门《电路》(三):说说不一样的电阻与电导
随机推荐
BLE蓝牙5.2-PHY6222系统级芯片(SoC)智能手表/手环
CI24R1小模块2.4G收发模块无线通信低成本兼容si24r1/XN297超低功耗
专硕与学硕
ECP2459耐压60V降压BUCK电路用于WIFI模块供电方案原理图
使用 腾讯云搭建一个个人博客
深入理解Golang之Map
动态规划理论篇
DP1332E刷卡芯片支持NFC内置mcu智能楼宇/终端poss机/智能门锁
5. Use RecyclerView to elegantly achieve waterfall effect
Article pygame drag the implementation of the method
FP6296锂电池升压 5V9V12V内置 MOS 大功率方案原理图
mysql的索引结构为什么选用B+树?
系统线性、时不变、因果判断
STM32LL library use - SPI communication
word方框怎么打勾?
利用plot_surface命令绘制复杂曲面入门详解
MATLAB绘图命令fimplicit绘制隐函数图形入门详解
Installation and configuration of Spark and related ecological components - quick recall
Codeforces Round #605 (Div. 3)
Yolov5 official code reading - prior to transmission