当前位置: 首页 > news >正文

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

续接上一话

目录

一、二叉树(续)

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;}

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

http://www.dtcms.com/a/355844.html

相关文章:

  • 多语言与零样本语音识别新突破:基于发音特征分类的方法
  • 通过ETL工具,同步SQLserver数据至starrocks数据库
  • Autosar之DCM模块
  • 构建AI智能体:十六、构建本地化AI应用:基于ModelScope与向量数据库的文本向量化
  • Day14 Gorm框架学习(1)
  • 安装与环境搭建:准备你的 Electron 开发环境
  • leetcode 525 连续数组
  • 可改善能源利用水平、削减碳排放总量,并为可再生能源规模化发展提供有力支撑的智慧能源开源了
  • 计算机组成原理3-3-5:定点数的乘法运算——补码阵列乘法器
  • init.usb.configfs.rc的USB动态配置
  • 算法学习笔记:双指针_滑动窗口专题
  • STM32CubeMX 6.15.0 + CLion
  • 3.渗透-.IP地址-详解
  • AI批量抠图工具,无需付费,永久使用
  • 报错记录 Error: CUDNN_STATUS_BAD_PARAM; Reason: finalize_internal()
  • 仓颉编程语言青少年基础教程:输入输出
  • Vue 自定义筛选组件:3 种全选反选场景的优雅实现
  • Groovy闭包语法详解
  • 【MySQL数据库入门课程】开课啦!
  • 一个是“内容生成器”,一个是“知识管理器”:VibeVoice 与 NoteBookLM 优劣对决?
  • 《零基础入门AI:YOLO目标检测模型详解(从基础概念到YOLOv1核心原理)》
  • Vue模版:Ant-design模态框弹窗
  • vue3的setup
  • 基于离散小波变换(DWT)的数字水印Matlab
  • @Indexed注解的作用
  • 整理3点结构点与点之间的距离
  • Paimon——官网阅读:非主键表
  • 基于pytorch的垃圾分类识别项目实战
  • Qt|QElapsedTimer 的使用详解
  • H5小游戏-超级马里奥