ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

二叉树的基本知识

2022-06-13 01:00:43  阅读:157  来源: 互联网

标签:right TreeNode 基本知识 遍历 二叉树 null root 节点



title: 二叉树的基本知识
date: 2022-06-12 15:37:23
tags:

  • 二叉树
  • 算法
  • 待补充

二叉树的四种遍历方式

不要较真,其实也可以分为两种:广度优先(层级)和深度优先(前序、中序、后序)

基本概念不再赘述。复杂度:设二叉树中元素数目为n。这四种遍历算法的空间复杂性均为O (n),时间复杂性为O(n)。

二叉树数据结构

class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode() {}
        TreeNode(int val) { this.val = val; }
        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }
      1
     / \
    2   5
   / \     
  3   4   

前序遍历

遍历顺序:根节点-> 左节点-> 右节点

代码实现:

/**
     * 前序遍历  根 -> 左 -> 右
     */
    public void preOrder(TreeNode tree){
        if (tree == null){
            return;
        }
        System.out.print(tree.val);
        preOrder(tree.left);
        preOrder(tree.right);
    }

非递归方式

//java 中使用 Deque, Stack已经弃用。
    //Deque 的使用用法:push、pop。
    public void perOrderIter(TreeNode root){
        if (root == null){
            return;
        }
        Deque<TreeNode> stack = new ArrayDeque<>();
        StringBuilder result = new StringBuilder();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode treeNode = stack.pop();
            result.append(treeNode.val);
            if (treeNode.right != null){
                stack.push(treeNode.right);
            }
            if (treeNode.left != null){
                stack.push(treeNode.left);
            }
        }
        System.out.println(result.toString());
    }

中序遍历

遍历顺序:左节点-> 根节点-> 右节点

代码实现

/**
 * 中序遍历  左 -> 根 -> 右
 * 结果:32415
 */
public void midOrder(TreeNode tree){
    if (tree == null){
        return;
    }
    midOrder(tree.left);
    System.out.print(tree.val);
    midOrder(tree.right);
}
/**
     * 迭代式中序遍历  左 -> 根 -> 右
     * 这个比较难,重点关注一下。
     */
    public void minOrderIter(TreeNode root){
        if (root == null){
            return;
        }
        Deque<TreeNode> stack = new ArrayDeque<>();
        StringBuilder result = new StringBuilder();
        while(root != null || !stack.isEmpty()){

            //此处的目的是放入将根节点放入,然后将根节点的左节点压在根节点上面。
            while (root != null){
                stack.push(root);
                root = root.left;
            }
            //调出栈
            root = stack.pop();
            result.append(root.val);
            root = root.right;
        }
        System.out.println(result.toString());
    }

后序遍历

遍历顺序:左节点-> 右节点-> 根节点

/**
     * 后序遍历  左 -> 右 -> 根
     * 结果:34251
     */
    public void postOrder(TreeNode tree){
        if (tree == null){
            return;
        }
        postOrder(tree.left);
        postOrder(tree.right);
        System.out.print(tree.val);
    }
/**
     * 迭代式后序遍历
     * 后序遍历更复杂!!!!
     * 先遍历左节点 -> 右节点 -> 根节点
     *      1
     *      / \
     *     2   5
     *    / \
     *   3   4
     *      / \
     *     7   8
     */
    public void postOrderIter(TreeNode root){
        if (root == null){
            return;
        }
        Deque<TreeNode> stack = new ArrayDeque<>();
        StringBuilder result = new StringBuilder();
        TreeNode pre = null; //记录前置节点
        while(root != null || !stack.isEmpty()){
            //把所有的左子树节点都放入栈中
            while(root != null){
                stack.push(root);
                root = root.left;
            }

            //找到当前节点
            root = stack.pop();
            //如果当前节点的右节点为空
            //这里为什么会有对pre的判断,是为了避免重复处理。
            //拿例子:当8已经处理完了之后,应该处理4节点,当时发现4也是有右子树的,但是8已经处理过了,通过pre达标,那么8也不用处理。
            if (root.right == null || pre == root.right){
                result.append(root.val);
                //设置前置节点
                pre = root;
                //置为空的目的是处理栈中堆积的父节点。
                root = null;
            } else{
                //右节点非空,说明当前节点这个时候不能够处理,就把当前节点再放回去。
                stack.push(root);
                //把当前节点的右节点作为root进行处理。
                root = root.right;
            }
        }
        System.out.println(result.toString());
    }

层级遍历

/**
 * 层级遍历
 * 递归的方式
 * 递归需要存储每个的层级 对应的数据都有什么,借助额外的数据结构
 */
public List<StringBuilder> result = new ArrayList<>();

public void levelOrder(TreeNode root, int level) {
    if (root == null) {
        return;
    }
    //当数组大小等于层级时,初始化该层级需要的存储空间
    if (result.size() == level) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(root.val);
        result.add(level, stringBuilder);
    } else {
        result.get(level).append(root.val);
    }
    levelOrder(root.left, level + 1);
    levelOrder(root.right, level + 1);
}
/**
 * 迭代式层级遍历
 * 借助额外的数据结构:队列,特性:先进先出
 * queue 的基本用法:add(offer),remove(poll)
 */
public void levelOrderIter(TreeNode root) {
    if (root == null) {
        return;
    }
    StringBuilder result = new StringBuilder();
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while(!queue.isEmpty()){
        TreeNode current = queue.poll();
        result.append(current.val);
        if (current.left != null){
            queue.add(current.left);
        }
        if (current.right != null){
            queue.add(current.right);
        }
    }
    System.out.println(result.toString());
}

额外:

/**
 * 获取二叉树的最大深度
 */
public int getMaxDepth(TreeNode root){
    if (root == null){
        return 0;
    }
    return Math.max(getMaxDepth(root.left)+1,getMaxDepth(root.right)+1);
}

文章作者: 冯廷鑫
文章链接: http://fengtingxin.github.io/2022/06/12/二叉树的基本知识/

标签:right,TreeNode,基本知识,遍历,二叉树,null,root,节点
来源: https://www.cnblogs.com/fengtingxin/p/16369406.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有