数据结构青铜到王者第九话---二叉树(2)

发布于:2025-08-29 ⋅ 阅读:(12) ⋅ 点赞:(0)

续接上一话

目录

一、二叉树(续)

1、二叉树的基本操作

1.1前置说明

1.2二叉树的遍历

1.2.1前中后序遍历

1.2.2层序遍历

1.3二叉树的基本操作


一、二叉树(续)

1、二叉树的基本操作

1.1前置说明

        在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习。等 二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。

 public class BinaryTree{
     public static class BTNode{
         BTNode left;
         BTNode right;
         int value;
        
         BTNode(int value){
            this.value = value;
         }
    } 
    
     private BTNode root;
 
 public void createBinaryTree(){
     BTNode node1 = new BTNode(1);
     BTNode node2 = new BTNode(2);
     BTNode node3 = new BTNode(3);
     BTNode node4 = new BTNode(4);
     BTNode node5 = new BTNode(5);
     BTNode node6 = new BTNode(6);
     root = node1;
     node1.left = node2;
     node2.left = node3;
     node1.right = node4;
     node4.left = node5;
     node5.right = node6;
     }
 }

注意:上述代码并不是创建二叉树的方式,真正创建二叉树方式后序详解重点讲解。

        在看二叉树基本操作前,我们回顾下二叉树的概念,二叉树是:

                (1)空树

                (2)非空:根节点,根节点的左子树、根节点的右子树组成的。

        从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。

1.2二叉树的遍历

1.2.1前中后序遍历

        学习二叉树结构,最简单的方式就是遍历。所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、节点内容加 1)。 遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

        在遍历二叉树时,如果没有进行某种约定,每个人都按照自己的方式遍历,得出的结果就比较混乱,如果按 照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的。如果N代表根节点,L代表根节点的 左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式:

(1)NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。(从根节点开始,先左后右,遇到一个结点就出一个数据)

    // 前序遍历
    public void preOrder(TreeNode root) {
        if(root == null) return;
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

(2)LNR:中序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树。(从根节点开始,先左后右,某一个节点的左子树都走完时出该节点数据)

    // 中序遍历
    public void inOrder(TreeNode root) {
        if(root == null) return;
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

(3)LRN:后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点。(从根节点开始,先左后右,某一个节点的右子树都走完时出该节点数据)

    // 后序遍历
    public void postOrder(TreeNode root) {
        if(root == null) return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

下面主要分析前序递归遍历,中序与后序图解类似

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

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

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

总结:

        先序遍历:遇到一个出一个

                特点:第一个打印根节点

        中序遍历:左侧孩子结点返回时打印(左侧都走完)

                特点:根节点左侧为左子树,右侧为右子树

        后序遍历:右侧孩子结点返回时打印(右侧都走完)

                特点:最后一个打印根节点

1.2.2层序遍历

        层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在 层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层 上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

1.2.3练习

(1)自己去多找几个二叉树的图片,分别写出对应的前中后序遍历

(2)选择

答案:

1.3二叉树的基本操作

    // 获取树中节点的个数
    public void size(TreeNode root) {
        if(root == null) {
            return ;
        }
        nodeSize++;
        size(root.left);
        size(root.right);
    } 
 
    // 获取叶子节点的个数
    public void getLeafNodeCount(TreeNode root) {
        if(root == null) {
            return;
        }
 
        if(root.left == null && root.right == null) {
            leafSize++;
        }
 
        getLeafNodeCount(root.left);
        getLeafNodeCount(root.right);
    }

    // 获取第K层节点的个数
    public int getKLevelNodeCount(TreeNode root,int k) {
        if(root == null) {
            return 0;
        }
        if(k == 1) {
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right,k-1);
    }
 
    // 获取二叉树的高度
    public int getHeight(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);
 
        return leftHeight >rightHeight
                ? leftHeight+1 : rightHeight+1;
    }
 
    // 检测值为value的元素是否存在
    public TreeNode findVal(TreeNode root,char val) {
        if(root == null) {
            return null;
        }
        if(root.val == val) {
            return root;
        }
        TreeNode leftT = findVal(root.left,val);
        if(leftT != null) {
            return leftT;
        }
        TreeNode rightT = findVal(root.right,val);
        if(rightT != null) {
            return rightT;
        }
        return null;
    }

    //判断一棵树是不是完全二叉树
    public boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean foundNull = false; // 标记是否已经遇到null节点
        
        while (!queue.isEmpty()) {
            TreeNode current = queue.poll();
            
            if (current == null) {
                foundNull = true; // 遇到null节点,标记为true
            } else {
                // 如果已经遇到过null节点,但当前节点不为null,则不是完全二叉树
                if (foundNull) {
                    return false;
                }
                // 将左右子节点加入队列(即使为null也要加入)
                queue.offer(current.left);
                queue.offer(current.right);
            }
        }
        return true;
    }

        由于内容较多,会分为多篇讲解,预知后续内容,请看后续博客!!!


网站公告

今日签到

点亮在社区的每一天
去签到