广告
返回顶部
首页 > 资讯 > 精选 >镜像二叉树的示例分析
  • 892
分享到

镜像二叉树的示例分析

2023-06-04 09:06:14 892人浏览 八月长安
摘要

镜像二叉树的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。算法这个东西很难,纵使你了解了其中的逻辑,用代码写出来仍然不是一件容易的事,内部有太多的细节需

镜像二叉树的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

算法这个东西很难,纵使你了解了其中的逻辑,用代码写出来仍然不是一件容易的事,内部有太多的细节需要处理。为了便于大伙轻松理解算法逻辑,对于所有的题目,我会使用图文加动画的形式进行讲解,让读者可以轻松理解算法逻辑的同时,还可以留下深刻的影像不容易遗忘。

镜像二叉树的示例分析

好,下面我们开始今天的算法题:镜像二叉树,就是将一颗二叉树上的左右节点全部交换,就好比镜子里的二叉树,左右方向是反过来的。

二叉树节点表示

镜像二叉树的示例分析
class node<T> {
    T value;
    Node<T> left;
    Node<T> right;

    Node(T value) {
        this.value = value;
    }

    Node(T value, Node<T> left, Node<T> right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }
}


一个参数的构造器是叶子节点,三个参数的构造器是中间节点,看到这里读者应该知道这是 Java 语言,我使用了范型 

构造二叉树

镜像二叉树的示例分析
Node<Integer> node2 = new Node<>(2);
Node<Integer> node3 = new Node<>(3);
Node<Integer> node1 = new Node<>(1, node2, node3);

// 一次性构造
Node<Integer> node1 = new Node<>(1, new Node<>(2), new Node<>(3));

呈现二叉树结构

如果我们正确写出了镜像算法,那如何来直观验证镜像的结构是否正确呢?LeetCode 使用的是单元测试,它使用一系列的单元测试和压力测试脚本代码来验证用户编写的算法的正确性和性能。但是我们不要这样做,因为不直观。我们选择对二叉树的结构内容进行直观的呈现,如此就可以使用肉眼来进行快速验证。如何直观呈现呢?我们使用最简单的括号表示法,它并不是最直观的,但是它易于实现。

镜像二叉树的示例分析
class Node<T> {
  T value;
  Node<T> left;
  Node<T> right;

  public String toString() {
    // 叶节点
    if (left == right) {
        return String.fORMat("[%d]", value);
    }
    // 中间节点
    return String.format("(%d, %s, %s)", value, left, right);
  }
}

Node<Integer> node2 = new Node<>(2);
Node<Integer> node3 = new Node<>(3);
Node<Integer> node1 = new Node<>(1, node2, node3);

System.out.println(node1);
System.out.println(node2);
System.out.println(node3);
---------------------
[2]
[3]
(1, [2], [3])

递归镜像二叉树

镜像二叉树有两种算法,一种是递归,一种是迭代。递归的算法简单易于理解,我们先使用递归算法来求解。递归的思想就是深度遍历,遇到一个节点,先递归镜像它的左子树,再递归镜像它的右子树,然后再交换自己的左右子树。如果遇到的是叶子节点,就不必处理了。为了避免无限递归,一定要及时设置好递归的停止条件,在这里停止条件就是遇到了叶节点。

镜像二叉树的示例分析
public void mirrorFrom(Node<T> node) {
    // 叶子结点
    if (node.left == node.right) {
        return;
    }
    // 递归镜像左子树
    if (node.left != null)
        mirrorFrom(node.left);
    // 递归镜像右子树
    if (node.right != null)
        mirrorFrom(node.right);
    // 交换当前节点的左右子树
    Node<T> tmp = node.left;
    node.left = node.right;
    node.right = tmp;
}

迭代镜像二叉树

递归算法的优势在于逻辑简单,缺点在于每一次递归调用函数都会增加一个新的函数堆栈,如果树的深度太深,函数的堆栈内存就会持续走高,一不小心就会触发臭名昭著的异常 StackOverflowException。如果二叉树分布比较均匀,那么树就不会太深,但是遇到偏向的二叉树,比如所有的子节点都挂在了右节点上,二叉树就退化成了线性链表,链表的长度就是树的深度,那这颗树的深度就比较可怕了。

镜像二叉树的示例分析


所以下面我来介绍第二种算法 —— 迭代算法。迭代的基本思想就是将递归算法转换成循环算法,用一个 for 循环来交换所有节点的左右子树。我们需要再重新理解一下算法的目标,这个目标非常简单,就是遍历整颗二叉树,将遍历途中遇到的所有中间节点的左右指针交换一下。

那如何设计这个循环呢?一个很明显的方法是分层循环,第一次循环处理第 1 层二叉树节点,也就是唯一的根节点。下一个循环处理第 2 层二叉树节点,也就是根节点的两个儿子。如此一直处理到最底层,循环的终止条件就是后代节点没有了。所以我们需要使用一个容器来容纳下一次循环需要处理的后代节点。

镜像二叉树的示例分析
public MirrorBinaryTree<T> mirrorByLoop() {
    // 空树不必处理
    if (root == null) {
        return this;
    }
    // 当前循环需要处理的节点
    LinkedList<Node<T>> expandings = new LinkedList<>();
    expandings.add(root);
    // 没有后台节点就可以终止循环
    while (!expandings.isEmpty()) {
        // 下一次循环需要处理的节点
        // 也就是当前节点的所有儿子节点
        LinkedList<Node<T>> nextExpandings = new LinkedList<>();
        // 遍历处理当前层的所有节点
        for (Node<T> node : expandings) {
            // 将后代节点收集起来,留着下一次循环
            if (node.left != null) {
                nextExpandings.add(node.left);
            }
            if (node.right != null) {
                nextExpandings.add(node.right);
            }
            // 交换当前节点的左右指针
            Node<T> tmp = node.left;
            node.left = node.right;
            node.right = tmp;
        }
        // 将后代节点设置为下一轮循环的目标节点
        expandings = nextExpandings;
    }
    return this;
}

完整代码

下面的完整代码可以拷贝过去直接运行,如果读者还是不够明白欢迎在留言区及时提问。

package leetcode;

import java.util.LinkedList;

public class MirrorBinaryTree<T> {

    static class Node<T> {
        T value;
        Node<T> left;
        Node<T> right;

        Node(T value) {
            this.value = value;
        }

        Node(T value, Node<T> left, Node<T> right) {
            this(value);
            this.left = left;
            this.right = right;
        }

        public String toString() {
            if (left == right) {
                return String.format("[%d]", value);
            }
            return String.format("(%d, %s, %s)", value, left, right);
        }

    }

    private Node<T> root;

    public MirrorBinaryTree(Node<T> root) {
        this.root = root;
    }

    public MirrorBinaryTree<T> mirrorByLoop() {
        if (root == null) {
            return this;
        }
        LinkedList<Node<T>> expandings = new LinkedList<>();
        expandings.add(root);
        while (!expandings.isEmpty()) {
            LinkedList<Node<T>> nextExpandings = new LinkedList<>();
            for (Node<T> node : expandings) {
                if (node.left != null) {
                    nextExpandings.add(node.left);
                }
                if (node.right != null) {
                    nextExpandings.add(node.right);
                }
                Node<T> tmp = node.left;
                node.left = node.right;
                node.right = tmp;
            }
            expandings = nextExpandings;
        }
        return this;
    }

    public MirrorBinaryTree<T> mirrorByRecursive() {
        mirrorFrom(root);
        return this;
    }

    public void mirrorFrom(Node<T> node) {
        if (node.left == node.right) {
            return;
        }

        if (node.left != null)
            mirrorFrom(node.left);
        if (node.right != null)
            mirrorFrom(node.right);

        Node<T> tmp = node.left;
        node.left = node.right;
        node.right = tmp;
    }

    public String toString() {
        if (root == null) {
            return "()";
        }
        return root.toString();
    }

    public static void main(String[] args) {
        Node<Integer> root = new Node<>(
                1, 
                new Node<>(
                        2, 
                        new Node<>(4), 
                        new Node<>(
                                5, 
                                new Node<>(8),
                                null)),
                new Node<>(
                        3, 
                        new Node<>(
                                6, 
                                null, 
                                new Node<>(9)), 
                        new Node<>(7)));
        MirrorBinaryTree<Integer> tree = new MirrorBinaryTree<>(root);
        System.out.println(tree);
        tree.mirrorByRecursive();
        System.out.println(tree);
        tree.mirrorByLoop();
        System.out.println(tree);
    }

}
---------------
(1, (2, [4], (5, [8], null)), (3, (6, null, [9]), [7]))
(1, (3, [7], (6, [9], null)), (2, (5, null, [8]), [4]))
(1, (2, [4], (5, [8], null)), (3, (6, null, [9]), [7]))

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: 镜像二叉树的示例分析

本文链接: https://www.lsjlt.com/news/237079.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 镜像二叉树的示例分析
    镜像二叉树的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。算法这个东西很难,纵使你了解了其中的逻辑,用代码写出来仍然不是一件容易的事,内部有太多的细节需...
    99+
    2023-06-04
  • Java中二叉树与N叉树的示例分析
    这篇文章主要介绍了Java中二叉树与N叉树的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。题目一 解法class Solution {&...
    99+
    2023-06-29
  • TypeScript获取二叉树的镜像实例
    目录前言思路分析实现代码前言 给定一颗二叉树,如何获取它的镜像?本文将跟大家分享这个问题的解决方案,欢迎各位感兴趣的开发者阅读本文。 思路分析 当我们把一张写有文字的纸放在镜子前面,...
    99+
    2022-11-13
  • web开发中二叉树的示例分析
    这篇文章将为大家详细讲解有关web开发中二叉树的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。0.  前言到目前为止,我们已经讲述了顺序表、链表、栈、队...
    99+
    2022-10-19
  • java二叉树面试题的示例分析
    小编给大家分享一下java二叉树面试题的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!二叉树的深度题目:输入一颗二叉树的根节点,求该树的的深度。输入一颗二...
    99+
    2023-06-20
  • C语言中二叉树的示例分析
    这篇文章主要为大家展示了“C语言中二叉树的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中二叉树的示例分析”这篇文章吧。树概念及结构树是一种 非线性 的数据结构,它是由 n ( n...
    99+
    2023-06-29
  • C++树与二叉树实例分析
    这篇“C++树与二叉树实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++树与二叉树实例分析”文章吧。树树的定义Q:...
    99+
    2023-06-30
  • C语言平衡二叉树的示例分析
    这篇文章给大家分享的是有关C语言平衡二叉树的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一...
    99+
    2023-06-25
  • java面试题解LeetCode27二叉树的镜像实例
    目录正文解题思路方法一:递归法方法二:辅助栈(或队列)正文 LeetCode27. 二叉树的镜像 请完成一个函数,输入一个二叉树,该函数输出它的镜像。 例如输入: 4 /2 7 ...
    99+
    2023-01-05
    java面试LeetCode二叉树镜像 java面试LeetCode
  • JavaScritp中二叉树遍历算法的示例分析
    这篇文章主要为大家展示了“JavaScritp中二叉树遍历算法的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScritp中二叉树遍历算法的示例...
    99+
    2022-10-19
  • C++二叉搜索树实例分析
    本篇内容介绍了“C++二叉搜索树实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!独一无二的二叉搜索树Given an integer&...
    99+
    2023-06-19
  • Java平衡二叉树实例分析
    这篇文章主要讲解了“Java平衡二叉树实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java平衡二叉树实例分析”吧!AVL树的引入搜索二叉树有着极高的搜索效率,但是搜索二叉树会出现以...
    99+
    2023-06-30
  • Java二叉搜索树增、插、删、创的示例分析
    小编给大家分享一下Java二叉搜索树增、插、删、创的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!①概念二叉搜索树又称二叉排序树,它或者是一棵空树**,或者是具有以下性质的二叉树:若它的左子树不为空,则左子树上所有...
    99+
    2023-06-29
  • JavaScript数据结构与算法之二叉树插入节点、生成二叉树的示例分析
    小编给大家分享一下JavaScript数据结构与算法之二叉树插入节点、生成二叉树的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解...
    99+
    2022-10-19
  • C++使用LeetCode实现二叉搜索树的示例分析
    这篇文章将为大家详细讲解有关C++使用LeetCode实现二叉搜索树的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Given an integer n, generate all st...
    99+
    2023-06-20
  • java二叉树中数据插入算法的示例分析
    这篇文章主要介绍java二叉树中数据插入算法的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!例题:leetcode 第701题二叉树插入数据题目:给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉...
    99+
    2023-06-22
  • Docker镜像的示例分析
    这篇文章主要为大家展示了“Docker镜像的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Docker镜像的示例分析”这篇文章吧。一:思维导图二:镜像的生命周期三:镜像的组织结构四:镜像...
    99+
    2023-06-04
  • Java中二叉树与斐波那契函数的示例分析
    这篇文章主要介绍Java中二叉树与斐波那契函数的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!题目一解法class Solution {    pu...
    99+
    2023-06-29
  • C++二叉树层序遍历实例分析
    今天小编给大家分享一下C++二叉树层序遍历实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。二叉树层序遍历Example...
    99+
    2023-06-19
  • java二叉搜索树使用实例分析
    本篇内容主要讲解“java二叉搜索树使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java二叉搜索树使用实例分析”吧!概念二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作