二叉树(Java)

目录

  • 一、概念
  • 二、 两种特殊的二叉树
  • 三、 二叉树的性质
  • 四、二叉树的存储
  • 五、二叉树的基本操作
    • 1、二叉树的遍历
      • (1)前中后序遍历
      • (2)层序遍历
    • 2、基本操作
  • 六、总结

一、概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。

在这里插入图片描述

二、 两种特殊的二叉树

  1. 满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
  2. 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
    在这里插入图片描述

三、 二叉树的性质

  1. 若规定 根节点的层数为 1 ,则一棵 非空二叉树的第 i 层上最多有 2^(i-1) (i>0) 个结点;
  2. 若规定只有 根节点的二叉树的深度为 1 ,则 深度为 K 的二叉树的最大结点数是2^k - 1
    (k>=0);
  3. 对任何一棵二叉树 , 如果其 叶结点个数为 n0, 度为 2 的非叶结点个数为 n2, 则有 n0 = n2 + 1;
    假设二叉树有N个节点,一棵二叉树,有n0(度为0的节点),n1(度为1的节点),n2(度为2)有N=n0+n1+n2;
    一个有N个节点的二叉树,共有N-1条边;
    度为0的节点产生0条边,度为1的节点有n1个 产生n1条边,度为2的节点有n2个 产生2n2条边,N-1=n1+2n2;
    联立得n0=n2+1;
    对于任意一个二叉树,叶子节点的个数比度为2的节点多一个。
  4. 具有 n 个结点的完全二叉树的深度 k 为log₂(n+1) 上取整;
    2^k-1=n->k=log₂(n+1)
  5. 对于具有 n 个结点的完全二叉树 ,如果按照 从上至下从左至右的顺序对所有节点从 0 开始编号 ,则对于 序号为 i 的结点有 :
    若 i>0 , 双亲序号: (i-1)/2 ; i=0 , i 为根节点编号 ,无双亲节点
    若 2i+1<n ,左孩子序号: 2i+1 ,否则无左孩子;
    若 2i+2<n ,右孩子序号: 2i+2 ,否则无右孩子。

四、二叉树的存储

二叉树的存储结构分为:顺序存储和类似于链表的链式存储。

二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式,具体如下:

// 孩子表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
} 
// 孩子双亲表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树Node parent; // 当前节点的根节点
}

五、二叉树的基本操作

1、二叉树的遍历

(1)前中后序遍历

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

// 前序遍历
void preOrder(Node root);
// 中序遍历
void inOrder(Node root);
// 后序遍历
void postOrder(Node root);

前序遍历
先输出当前节点(初始的时候是root节点)
如果左子节点不为空,则递归继续前序遍历
如果右子节点不为空,则递归继续前序遍历

中序遍历
如果当前节点的左子节点不为空,则递归中序遍历
输出当前节点
如果当前的右子节点不为空,则递归中序遍历

后序遍历
如果当前节点的左子节点不为空,则递归后序遍历
如果当前节点的右子节点不为空,则递归后序遍历
输出当前节点

// 前序遍历  
void preOrder(Node root) {  if (root == null) {  return;  }  // 访问根节点  System.out.print(root.data + " ");  // 递归遍历左子树  preOrder(root.left);  // 递归遍历右子树  preOrder(root.right);  
}  // 中序遍历  
void inOrder(Node root) {  if (root == null) {  return;  }  // 递归遍历左子树  inOrder(root.left);  // 访问根节点  System.out.print(root.data + " ");  // 递归遍历右子树  inOrder(root.right);  
}  // 后序遍历  
void postOrder(Node root) {  if (root == null) {  return;  }  // 递归遍历左子树  postOrder(root.left);  // 递归遍历右子树  postOrder(root.right);  // 访问根节点  System.out.print(root.data + " ");  
}  

(2)层序遍历

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

public void levelOrder(TreeNode root){Queue<TreeNode> queue = new LinkedList<>();if(root != null){queue.offer(root);}while (!queue.isEmpty()){TreeNode top = queue.poll();System.out.print(top.val+" ");if(top.left != null){queue.offer(top.left);}if(top.right != null){queue.offer(top.right);}} 
}

2、基本操作

(1)获取二叉树结点个数:

public int size(Node root){if(root==null)return 0;return size(root.left)+size(root.right)+1;
}

(2)获取叶子结点个数:

// 获取叶子节点的个数
public int getLeafNodeCount(Node root){if(root==null){return 0;}if(root.left==null&&root.right==null){return 1;}return getLeafNodeCount(root.left)+getLeafNodeCount(root.right);
}

(3) 获取第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);
}

(4) 获取二叉树高度:

public  int getHeight(TreeNode root){if(root == null){return 0;}int leftH = getHeight(root.left);int rightH = getHeight(root.right);return (leftH > rightH ? leftH :rightH) + 1;
}

(5)检测是否存在value值:

public TreeNode find(TreeNode root,int val){if(root == null) return null;if(root.val == val){return root;}TreeNode leftL = find(root.left,val);if(leftL != null){return leftL;}TreeNode leftLR = find(root.right,val);if(leftLR != null){return leftLR;}return null;
}

(6)是否为完全二叉树:

public boolean isCompleteTree(TreeNode root){Queue<Node> queue = new LinkedList<>();if(root != null){queue.offer(root);}while (!queue.isEmpty()){Node cur = queue.poll();if(cur != null){queue.offer(cur.left);queue.offer(cur.right);}else{break;}}while (!queue.isEmpty()){Node cur = queue.poll();if(cur != null){return false;}}return true;
}

六、总结

通过对二叉树的深入学习,我们可以理解其性质、存储方式以及基本操作,从而在实际问题中灵活运用二叉树来解决各种问题。在实际应用中,我们还需要根据具体问题选择合适的二叉树类型(如满二叉树、完全二叉树、平衡二叉树等)以及相应的存储方式(顺序存储或链式存储)。此外,二叉树的遍历是二叉树操作的基础,需要熟练掌握前序、中序、后序和层序遍历的方法。通过不断练习和实践,我们可以更好地应用二叉树来解决实际问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/502508.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

xsslabs第六关

看一下源码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;charsetutf-8"> <script> window.alert function() { confirm("完成的不错&#xff01;…

驱动高级--mknod

一、起源 仅devfs&#xff0c;导致开发不方便以及一些功能难以支持&#xff1a; 热插拔 不支持一些针对所有设备的统一操作&#xff08;如电源管理&#xff09; 不能自动mknod 用户查看不了设备信息 设备信息硬编码&#xff0c;导致驱动代码通用性差&#xff0c;即没有分离…

JavaScript DOM操作笔记记录回忆总结

一、什么是DOM&#xff1f; 1、通过 HTML DOM&#xff0c;可访问 JavaScript HTML 文档的所有元素。 2、当网页被加载时&#xff0c;浏览器会创建页面的文档对象模型&#xff08;Document Object Model&#xff09; 二、操作DOM 1、在操作DOM之前&#xff0c;我们需要先获取到…

vue自定义实现icon选择器

<template> <div> <span class"iconStyle" click"selectIcon"> <i :class"value" /> </span> <div class"iconTitle">选择图标</div> <el-dialog title"" :visible.sync"…

bvh文件,人体骨骼重定向

关于两个bvh文件&#xff0c;人体骨骼重定向&#xff0c;小白记录 1、打开 Motionbuilder &#xff0c;选择 打开特定路径下的bvh文件。 绑定骨骼&#xff08;在绑定骨骼过程中&#xff0c;如果骨骼角度&#xff0c;大小之类的不方便&#xff0c;可以shift键加鼠标拖拽界面&…

vulhub中Aapache Tomcat AJP 文件包含漏洞复现(CVE-2020-1938)

查看tomcat默认页面&#xff0c;此时通过AJP协议的8009端口亦可访问Tomcat。 利用如下工具均可测试漏洞&#xff1a; https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi 工具需要用到python2&#xff0c; 如果需要进一步利用需要向服务器的/webapps/ROOT目录下上传…

Entry First Day 入职恩孚第一天

入职第一天&#xff0c;电脑还没配置好就去了工厂。 熟悉了一下设备&#xff0c;切了几个小玩意&#xff0c; hello world 一下。 了解了串行端口的Nodejs的库 https://github.com/serialport/node-serialport&#xff0c;以后要用这个东西和硬件通讯&#xff0c;安装&#…

6. Z 字形变换

将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你的输出需要从左往右…

【零基础SRC】成为漏洞赏金猎人的第一课:加入玲珑安全漏洞挖掘班。

我们是谁 你是否对漏洞挖掘充满好奇&#xff1f;零基础或有基础但想更进一步&#xff1f;想赚取可观的漏洞赏金让自己有更大的自由度&#xff1f; 那么&#xff0c;不妨了解下我们《玲珑安全团队》。 玲珑安全团队&#xff0c;拥有多名实力讲师&#xff0c;均就职于互联网头…

SpringBoot整合OAuth2 实现单点登录 SSO

单点登录&#xff1a; SSO服务端和SSO客户端直接是通过授权以后发放Token的形式来访问受保护的资源相对于浏览器来说&#xff0c;业务系统是服务端&#xff0c;相对于SSO服务端来说&#xff0c;业务系统是客户端浏览器和业务系统之间通过会话正常访问不是每次浏览器请求都要去S…

2023中国PostgreSQL数据库生态大会:洞察前沿趋势,探索无限可能(附核心PPT资料下载)

随着数字化浪潮的推进&#xff0c;数据库技术已成为支撑各行各业数字化转型的核心力量。2023中国PostgreSQL数据库生态大会的召开&#xff0c;无疑为业界提供了一个深入交流、共同探索PostgreSQL数据库技术未来发展趋势的平台。本文将带您走进这场盛会&#xff0c;解析大会的亮…

springboot配置多数据源以及事务问题

一、背景以及为什么需要学习 在高并发的项目中,单数据库已无法承载大数据量的访问,因此需要使用多个数据库进行对数据的读写分离,此外就是在微服化的今天,我们在项目中可能采用各种不同存储,因此也需要连接不同的数据库,居于这样的背景,这里简单分享实现的思路以及实现…