IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 树的前中后序深度优先算法(迭代法+递归法)-日记篇 -> 正文阅读

[数据结构与算法]树的前中后序深度优先算法(迭代法+递归法)-日记篇

说明:问题来源于

leetcode的前序遍历

leetcode的中序遍历

leetcode的后序遍历

一、深度优先遍历递归法:

1、前序遍历

对于树

public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode() {
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

树的节点不为空时必须保证其val是有值的情况下,深度优先算法的前序遍历:

public class Solution {
    List<Integer> list = new LinkedList<>();

    public List<Integer> preorderTraversal(TreeNode root) {
        selectGoal(root);
        return list;
    }
    public void selectGoal(TreeNode root){
        if (root == null) return;
        list.add(root.val);
        selectGoal(root.left);
        selectGoal(root.right);
    }

}

如果说树节点的val没有定义,那么便在以上稍作修改:

class TreeNode {
    public Integer val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(Integer val) {
        this.val = val;
    }

    public TreeNode() {
    }

    public TreeNode(Integer val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
public class Solution {
    List<Integer> list = new LinkedList<>();

    public List<Integer> preorderTraversal(TreeNode root) {
        selectGoal(root);
        return list;
    }
    public void selectGoal(TreeNode root){
        if (root == null) return;
        if (root.val != null) list.add(root.val);
        selectGoal(root.left);
        selectGoal(root.right);
    }

}

2、对于后序遍历:

public class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
        selectGoal(root);
        return list;
    }
    public void selectGoal(TreeNode root){
        if (root == null) return;
        selectGoal(root.left);
        selectGoal(root.right);
        list.add(root.val);
    }
}

3、对于中序排序:

public class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        selectGoal(root);
        return list;
    }
    private void selectGoal(TreeNode root){
        if (root == null) return;
        selectGoal(root.left);
        list.add(root.val);
        selectGoal(root.right);
    }
}

二、迭代法:

1、前序遍历:

public class Solution {
    private List<Integer> list = new LinkedList<>();

    public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode treeNode = stack.pop();
            list.add(treeNode.val);
            if (treeNode.right != null) stack.push(treeNode.right);
            if (treeNode.left != null) stack.push(treeNode.left);
        }
        return list;
    }
}

2、中序遍历

public class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode peek = stack.peek();
            if (peek.left == null){
                TreeNode pop = stack.pop();
                list.add(pop.val);
                if (pop.right != null){
                    stack.push(pop.right);
                }
            }else {
                TreeNode pop = peek;
                if (peek.right != null) {
                    pop = stack.pop();
                    stack.push(peek.right);
                    stack.push(pop);
                }
                stack.push(pop.left);
                pop.left = null;
                pop.right = null;
            }
        }
        return list;
    }
}

思路:先将root节点放进stack里,通过while循环对树节点进行处理(有一种破坏其“莲藕”的“丝”,毁其“叶”的感觉,对应着下面的②中对于左右孩子砍掉的意思)

然后来一次while循环对stack容器进行非空判断对root的左节点进行判断

  • ①如果stack里的出口元素peek(通过pop或者peek获取的树节点)的左树节点为空,那么说明这一层上链表应该放peek.val,再放右树节点的数据。因此需要将peek元素从stack里pop出来。并且对右树节点进行判断,如果该右树节点非空,那么就push到stack。

  • ②如果出口元素的左树节点不为空,那么我们需要将peek和peek.left以及peek.right在stack的位置进行排序,肯定是先放peek.right(如果不为空的话),再放peek(要将左树节点和右树节点)砍掉,最后放peek.left。方便链表添加的顺序是“前中后”。

3、后序遍历

class Solution {
    List<Integer> list = new LinkedList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
        if (root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode peek = stack.peek();
            if (peek.left == null){//左子树为null时
                if (peek.right == null) {//左子树为null时,且右子树也等于null
                    list.add(peek.val);
                    stack.pop();
                }else {//左子树为null时,且右子树也bu等于null
                    TreeNode right = peek.right;
                    peek.right = null;
                    stack.push(right);
                }
            }else {//左子树bu为null
                if (peek.right != null) {//左子树bu为null,且右子树也bu等于null
                    stack.push(peek.right);
                }
                stack.push(peek.left);
                peek.right = null;
                peek.left = null;
            }
        }
        return list;
    }
}

思路和中序遍历的基本一样

整体思想将单个树的节点进行左右树节点判断,因为对于一颗树,假如是peek那么我们想放到链表里的顺序是peek.left的数据,再到peek.right最后到peek.val,这个是后序遍历,那么我们放到栈里的顺序肯定是peek.val,再到peek.right最后才是peek.left。因此肯定进入循环后是先对peek.left进行判断,并且当peek的左右树节点均为null时才可以add到链表里面进行保存。

心得:

以上是xin麒思考并且做出来了,三种迭代法的是通过栈来处理root(中序和后续方法会导致root的结构会被拆解),放到栈里面,细细看里面的顺序的要求会导致链表保存的结果是怎么样的。看到代码行数有些是可以优化的(也就是改的简洁些),不过不优化可以保留自己思考过的踩过的细节。

当然对于迭代法网上也很多各种类型题的模板,如果是面试的话可能就多数都是找模板就可以了,不适合看上面的。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:25:10  更:2022-10-31 12:28:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:39:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码