• 【数据结构与算法】初识二叉树(中)


    ✨hello,进来的小伙伴们,你们好耶!✨

    🚀🚀系列专栏:【数据结构与算法】

    ⛴️⛴️本篇内容:二叉树的三种遍历方式以及二叉树的模拟实现。

    ⛵⛵作者简介:一名双非本科大三在读的Java编程小白,不行动起来,你永远只是旁观者!

    🛰️🛰️码云存放仓库gitee:https://gitee.com/king-zhou-of-java/preliminary-data-structure.git

    一、二叉树的遍历

    🚀🚀1、前中后序遍历

    所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容)

    遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

    NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。
    LNR:中序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树。
    LRN:后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点。

    e13b3d20e2724c1683f494da1f796fe0.png

     前序遍历结果:1 2 4 5 3 6

     中序遍历结果:4 2 5 1 6 3

     后序遍历结果:4 5 2 6 3 1

    ✈️✈️2、层序遍历

    层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层
    上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

    对于上图层序遍历结果为:1 2 3 4 5  6

    🚠🚠3、选择题练习

    🍊1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为(A)
    A: ABDHECFG  B: ABCDEFGH  C: HDBEAFCG  D: HDEBFGCA

    🍖🍖解答:由题干我们可以知道这是一个完全二叉树,又是层序遍历的结果已经给出,那么我们可以顺势画出该二叉树,层序遍历的第一个节点就是根节点,依次画出得:

     7d59a974c36b4bec81a6fb92e8fd2053.jpeg

     🍎2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则二叉树根结点为(A)
    A: E      B: F      C: G      D: H

    🍗🍗解答:先序遍历的第一个节点就是我们的根节点,由题意的A。

    🍅3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为(D)
    A: adbce    B: decab    C: debac    D: abcde

    🧀🧀解答:由题意,给出了中序和后续的节点,由后续最后一个节点就是根节点知道a就是根节点,中序第一个节点就是最左侧的节点,那么最左侧的节点就是b,那么看中序的结果是badce,那么根节点a的左孩子就只有一个b,dce都在a的右边,在根据后续遍历的结果dec得出c是右边节点的根节点,于是可以画出我们的二叉树。

    6ee4cd5acfb94bcab282ef0d94cca40b.jpeg

    🍏 4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同一层从左到右)的序列为(A)
    A: FEDCBA   B: CBAFED   C: DEFCBA   D: ABCDEF

    🍤🍤解答:我们先来回顾一下后序和中序的遍历方式;后序:左右根   中序:左根右  由题意得知后序与中序的遍历结果相同,那么我们发现舍去右孩子,二者的遍历方式都是左根,也就是说该二叉树是没有右孩子的一颗二叉树。画出效果图如下:

    82076a0bd1c64c2dbddc2fc2ac43b3b6.jpeg

     🍼🍼重要结论:只给出二叉树的前序和后序的结果,是无法推导出该课二叉树的模型的,也就是三种遍历方式,想要通过其中两种得到第三种的结果,则这两种方式中必须存在中序遍历!

    二、二叉树的基本操作

    接下来博主将通过idea来演示二叉树的基本操作。

    我们下面的基本操作都是基于这个二叉树来完成的!

    9d08eb470d9845aa8be8c95bc597f19a.jpeg

    1、首先我们新建一个包名为BinaryTree,在这个包下新建两个类Test 和 TestBinaryTree。

    9879481b2e184432b43e6ae347609267.png

    2、我们初始化实现一个内部类:

    1. public class TreeNode {
    2. char val;
    3. TreeNode left;
    4. TreeNode right;
    5. TreeNode() {
    6. }
    7. TreeNode(char val) {
    8. this.val = val;
    9. }
    10. TreeNode(char val, TreeNode left, TreeNode right) {
    11. this.val = val;
    12. this.left = left;
    13. this.right = right;
    14. }
    15. }
    16. public TreeNode createTree() {//创建二叉树
    17. TreeNode A = new TreeNode('A');
    18. TreeNode B = new TreeNode('B');
    19. TreeNode C = new TreeNode('C');
    20. TreeNode D = new TreeNode('D');
    21. TreeNode E = new TreeNode('E');
    22. TreeNode F = new TreeNode('F');
    23. TreeNode G = new TreeNode('G');
    24. TreeNode H = new TreeNode('H');
    25. A.left = B;
    26. A.right = C;
    27. B.left = D;
    28. B.right = E;
    29. C.left = F;
    30. C.right = G;
    31. E.right = H;
    32. return A;
    33. }

     3、三种遍历方式的实现

    1. public void preOrder(TreeNode root){//前序遍历
    2. if(root == null){
    3. return;
    4. }
    5. System.out.print(root.val+" ");
    6. preOrder(root.left);
    7. preOrder(root.right);
    8. }
    9. public void inOrder(TreeNode root){//中序遍历
    10. if(root == null){
    11. return;
    12. }
    13. preOrder(root.left);
    14. System.out.print(root.val+" ");
    15. inOrder(root.right);
    16. }
    17. public void postOrder(TreeNode root){//后序遍历
    18. if(root == null){
    19. return;
    20. }
    21. preOrder(root.left);
    22. inOrder(root.right);
    23. System.out.print(root.val+" ");
    24. }

    运行结果:

    da208c16bceb4f93a4bf61557a3b525a.png

    4、获取树中节点的个数(2种方法)

    1. // 获取树中节点的个数 两种方法
    2. public static int nodeSize = 0;
    3. public int size(TreeNode root) {
    4. if(root == null) {
    5. return 0;
    6. }
    7. nodeSize++;
    8. size(root.left);
    9. size(root.right);
    10. return nodeSize;
    11. }
    12. public int size2(TreeNode root) {
    13. if(root == null) {
    14. return 0;
    15. }
    16. int tmp = size2(root.left)+size2(root.right)+1;
    17. return tmp;
    18. }

    运行结果:

    0b416e75beaf433f9a0769b2276ee94f.png

    5、获取叶子节点的个数(两种方法)

    1. int getLeafNodeCount(TreeNode root) {
    2. if(root == null) {
    3. return 0;
    4. }
    5. if(root.left == null && root.right == null) {
    6. return 1;
    7. }
    8. int tmp = getLeafNodeCount(root.left) +
    9. getLeafNodeCount(root.right);
    10. return tmp;
    11. }
    12. public static int leafSize = 0;
    13. void getLeafNodeCount2(TreeNode root) {
    14. if(root == null) {
    15. return ;
    16. }
    17. if(root.left == null && root.right == null) {
    18. leafSize++;
    19. }
    20. getLeafNodeCount2(root.left);
    21. getLeafNodeCount2(root.right);
    22. }

    运行结果:

    ea6885fb46014158aeda07d398fa77e5.png

    6、判断第K层节点的个数

    1. int getKLevelNodeCount(TreeNode root,int k) {
    2. if(root == null || k <= 0) {
    3. return 0;
    4. }
    5. if(k == 1) {
    6. return 1;
    7. }
    8. int tmp = getKLevelNodeCount(root.left,k-1) +
    9. getKLevelNodeCount(root.right,k-1);
    10. return tmp;
    11. }

    运行结果:(这里我们求的是第3层的结果)

    cb691638394945359feb66e48de7eea3.png

    7、获取二叉树的高度

    1. // 时间复杂度:O(n)
    2. public int getHeight(TreeNode root) {
    3. if(root == null) {
    4. return 0;
    5. }
    6. int leftHeight = getHeight(root.left);
    7. int rightHeight = getHeight(root.right);
    8. return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
    9. }
    10. // 时间复杂度:O(n)
    11. public int getHeight2(TreeNode root) {
    12. if(root == null) {
    13. return 0;
    14. }
    15. return getHeight2(root.left) > getHeight2(root.right)
    16. ? getHeight2(root.left)+1 : getHeight2(root.right)+1;
    17. }

    运行结果:

    52a134043b89438fa958d93eccac7f52.png

    8、检测值为val的元素是否存在

    1. public TreeNode find(TreeNode root, char val) {
    2. if(root == null) {
    3. return null;
    4. }
    5. if(root.val == val) {
    6. return root;
    7. }
    8. TreeNode ret1 = find(root.left,val);
    9. if(ret1 != null) {
    10. return ret1;
    11. }
    12. TreeNode ret2 = find(root.right,val);
    13. if(ret2 != null) {
    14. return ret2;
    15. }
    16. return null;
    17. }
    18. //时间复杂度:O(min(M,N)) P:M Q:N
    19. public boolean isSameTree(TreeNode p, TreeNode q) {
    20. if(p == null && q != null || p != null && q == null ) {
    21. return false;
    22. }
    23. if(p == null && q == null) {
    24. return true;
    25. }
    26. if(p.val != q.val) {
    27. return false;
    28. }
    29. return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    30. }

    运行结果:(这里我们检测字符H是否在节点中)

    133a840a71294b1f810878be1adef06f.png

     🥧🥧OK,那么二叉树的中篇就讲到这里,下篇博主将会整合二叉树的面试OJ题,期待你的阅读,一键三连!🤟🤟

  • 相关阅读:
    开发工程师必备————【Day13】数据库约束条件
    Pig的搭建和配置
    Github创建个人博客
    Vue.js+Node.js全栈开发教程:Vue.js方法详解
    广域确定性网络技术概述
    【PAT(甲级)】1066 Root of AVL Tree
    Android性能优化,可以从那些方面解决?方案一览
    Python基于机器视觉的图像风格迁移
    【OpenVINO™】使用OpenVINO™ C# API 部署 YOLO-World实现实时开放词汇对象检测
    插件未购买或已到期,请重新绑定帐号后重试,如操作无效,请将服务器出口IP改为:8XX.XXX.XX.XX
  • 原文地址:https://blog.csdn.net/m0_62426532/article/details/127109753