数据结构之二叉树的实现
文章目录
- 一、树的简单了解
- 二、树的结构概念
- 三、二叉树
- 四、代码实现二叉树
- 1.实现前准备
- 2.实现二叉树的遍历
- 3.实现获取树中结点的数量
- 4.获取叶子结点的个数
- 5.获取第K层元素的个数
- 6.获取二叉树的高度
- 7.检测value值是否在该树中
- 五、总结
一、树的简单了解
1.概念:
树是一种非线性数据结构,它是由 n (n>0) 个结点组成的一个具有层次结构的关系的集合。
形似一个倒置的树,根朝上,叶子朝下。
2.树的特点:
(1)树有一个特殊的节点,为根节点,根节点没有前驱结点。
(2)树是由递归方式定义的。
(3)树形结构中,子树之间不能有交集,否则不能称为树形结构。
二、树的结构概念
结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A 的节点的度为 2。
树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为 2 。
叶子结点或终端结点:度为0的结点称为叶结点; 如上图:D,H,F,G 为叶结点。
双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的
父结点, 如上图:A 为 B,C 的父节点。
孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点, 如上图:B,C 为 A 的孩子结点。
根结点:一棵树中,没有双亲结点的结点,如上图:A
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。
树的高度或深度:树中结点的最大层次,如上图:树的高度为4。
树的以下概念只需了解:
非终端结点或分支结点:度不为0的结点; 如上图:A,B,C,E 为分支结点
兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:E,F 互为兄弟结点
结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
三、二叉树
1.二叉树的概念:二叉树可以为空,或是由一个根节点加上一个左子树和一个右子树组成。
注:
(1)二叉树不存在度大于2的节点。
(2)二叉树的结点元素是有顺序的,次序不能改变。
2.两种特殊的二叉树
(1)满二叉树:每层结点数都达到最大值,这棵树就是满二叉树。
(2)完全二叉树:对于深度为K的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从 0 至 n-1 的结点一 一对应时称之为完全二叉树。
四、代码实现二叉树
1.实现前准备
为了后续方法的实现更加方便,我们首先需要简单实现一下树的节点,并且简单创建一个树。
代码如下:
//树的每一个结点都是一个独立的部分,因此可以以内部类的形式实现。static class TreeNode{public char val;public TreeNode left; //存储左孩子引用public TreeNode right; //存储有孩子引用public TreeNode(char val) {this.val = val;}}
如图,我们利用上面创建的结点空间实现以下的二叉树。
代码如下:
//手动创建一个二叉树,便于测试public TreeNode createTree(){TreeNode A = new TreeNode('A');TreeNode B = new TreeNode('B');TreeNode C = new TreeNode('C');TreeNode D = new TreeNode('D');TreeNode E = new TreeNode('E');TreeNode F = new TreeNode('F');TreeNode G = new TreeNode('G');TreeNode H = new TreeNode('H');A.left = B;A.right = C;B.left = D;B.right = E;C.left = F;C.right = G;E.right = H;return A; //返回树的根节点}
之后,我们要了解有关二叉树,需要实现的一些方法,如下:
1.实现二叉树的遍历(前、中、后序)。
2.实现获取树中结点的个数。
3.实现获取叶子结点的个数。
4.获取第 k 层元素个数。
5.获取二叉树的高度。
6.检测值为 val 的结点是否存在。
2.实现二叉树的遍历
简单解释:
我们知道二叉树的遍历有三种,分别为,前,中,后序。
前序:根 --> 左–> 右。
中序:左 --> 根 --> 右。
后序:左 --> 右 --> 根。
注:有关树的方法实现最主要的就是递归方法的使用!
代码实现:
//前序遍历 根-->左-->右void preOrder(TreeNode root){if(root == null){return;}System.out.print(root.val+" ");preOrder(root.left);preOrder(root.right);}//中序遍历 左-->根-->右void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}//后序遍历 左-->右-->根void postOrde(TreeNode root){if(root == null){return;}postOrde(root.left);postOrde(root.right);System.out.print(root.val+" ");}
详细解释:
这里,为了便于解释,我将上面的树进行了删减,以下图为例解释一下前序遍历的代码逻辑(其余两种遍历类似)。
结果为:ABDEC
3.实现获取树中结点的数量
简单解释:
获取树中的元素个数,最直接的方法就是定义一个计数器,通过遍历树中的元素实现累加。
代码实现:
// 获取树中节点的个数public static int nodeSize = 0;public int size(TreeNode root){if(root == null){return 0;}//每次递归遍历时首先实现计数增加nodeSize++;size(root.left);size(root.right);return nodeSize;}
详细解释:
这里使用递归的方法,只要 root != null 优先实现对左树的遍历计数,然后在此基础上实现对右树元素进行遍历计数。最终返回个数和。
4.获取叶子结点的个数
简单解释:
叶子结点,就是指树中没有孩子结点的元素,也就是说,这样的节点左右均为 null 因此这也就成为了实现该方法的突破口。
代码如下:
public int getLeafNodeCount2(TreeNode root){if(root == null){return 0;}if(root.left == null && root.right == null){return 1;}int tmp = getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);return tmp;}
详细解释:
同样这里使用了递归的方法,在递归前,先放出递归返回的条件,然后,进入递归,从整体看,将树分为左右两大部分,在进行细分,先让递归记录左边,在记录右边相加和,最终获得叶子结点的数量。
5.获取第K层元素的个数
简单解释:
如图所示:假设获取第 3 层元素数量。
对于 A 层,是第三层。对于 B,C 层,是第二层。对于 D,E,F,G 是第一层。
以此为判断条件,不难理解,可以在每次递归时让层数减少,当为 1 时就记录个数,最后返回即可。
代码实现:
// 获取第K层节点的个数public int getKLevelNodeCount(TreeNode root,int k){//这里需要注意当要查找的层数超过数高度的情况if(root == null || k <= 0){return 0;}if(k == 1){return 1;}int tmp = getKLevelNodeCount(root.left,k-1) + getKLevelNodeCount(root.right,k-1);return tmp;}
详细解释:
因为只需要找某一层的结点个数,因此,只要到该层节点时返回 1 ,如果继续 k-1 ,k = 0 就会返回 0 。同样的,这里递归需要将整棵树看做左右两大部分,在细分到下面的左右子树,最后加和返回该层的数量。
6.获取二叉树的高度
简单解释:
要获取高度,同样的需要对二叉树进行深入遍历,因为二叉树只有左右两部分,树的高度无非就是左右部分进行比较,这里将树看做左右两大部分,分别深入,最终进行比较即可。
代码实现:
// 获取二叉树的高度public int getHeight(TreeNode root){if(root == null){return 0;}int leftHigh = getHeight(root.left);int rightHigh = getHeight(root.right);return leftHigh > rightHigh ? leftHigh+1 : rightHigh+1;}
详细解释:
同样,以 root 所指向为 null 为条件,将树分为左右两大部分,先对左树进行遍历,通过三目运算的判断,最终会返回出最长,高度最高的呢一串结点。
7.检测value值是否在该树中
简单解释:
同样,这个方法的实现也很简单,就是遍历整棵树,寻找对应的值后返回 root 即可。
代码实现:
// 检测值为value的元素是否存在public TreeNode find(TreeNode root, int val){if(root == null){return null;}if(root.val == val){return root;}TreeNode ret1 = find(root.left,val);if(ret1 != null){return ret1;}TreeNode ret2 = find(root.left,val);if(ret2 != null){return ret2;}return null;}
详细解释:
与前面的方法相同,从整体上,将一棵树一分为二,首先,定义返回条件,这里需要定义两个结点来接受返回出来的目标值。只要最终返回的值符合条件,就将该地址传递出去即可,如果均不成立,呢没有找到目标值。
五、总结
简单总结:
在有关树的问题中,用的最多的就是递归的思想,这就需要我们用整体和部分的眼光来看问题,往往在深究深层是如何运行的时候常常会将问题复杂化,所以,子问题的思考方法在这里尤为重要!
数据结构之二叉树的实现相关推荐
- 【数据结构】二叉树及其相关操作
二叉树的定义 二叉树是一个由结点构成的有限集合,这个集合或者为空,或者由一个根节点及两棵互不相交的分别称作这个根节点的左子树和右子树的二叉树组成. 二叉树并非一般的树形结构的特殊形式,它们是两种不同的 ...
- 数据结构之二叉树(遍历、建立、深度)
数据结构之二叉树(遍历.建立.深度) 1.二叉树的深度遍历 二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树的所有结点,使得每个结点被访问一次且仅被访问一次. 对于二叉树的深度遍历,有前序遍历 ...
- python数据结构 树_python数据结构之二叉树的建立实例
先建立二叉树节点,有一个data数据域,left,right 两个指针域 复制代码 代码如下: # -*- coding: utf - 8 - *- class TreeNode(object): d ...
- 【关于封装的那些事】 缺失封装 【关于封装的那些事】 泄露的封装 【关于封装的那些事】 不充分的封装 【图解数据结构】二叉查找树 【图解数据结构】 二叉树遍历...
[关于封装的那些事] 缺失封装 目录 - 缺失封装 为什么不能缺失封装? 缺失封装潜在的原因 未意识到关注点会不断变化 混合关注点 幼稚的设计决策 示例分析一 示例分析二 总结 缺失封装 没有将实现变 ...
- python处理mysql数据结构_python环境下使用mysql数据及数据结构和二叉树算法(图)...
python环境下使用mysql数据及数据结构和二叉树算法(图): 1 python环境下使用mysql 2使用的是 pymysql库 3 开始-->创建connection-->获取cu ...
- 数据结构之二叉树:折纸问题——11
数据结构之二叉树:Python代码解决折纸问题 折纸问题 要求:请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开.此时折痕是凹下去的,即折痕突起的方向指向纸条的背面.如果从纸 ...
- 数据结构树二叉树计算节点_查找二叉树中叶节点的数量 数据结构
数据结构树二叉树计算节点 Algorithm: 算法: One of the popular traversal techniques to solve this kind of problems i ...
- 【数据结构】二叉树的python实现
[数据结构]二叉树的python实现 本博文描述的二叉树是任意二叉树,可以使完全二叉树,也可以是非完全二叉树. 首先声明一个二叉树节点的初始化类TNode,每一个节点都有三个组成部分,节点的元素值,节 ...
- 大一新生必看,自学必看,里昂详解数据结构之二叉树
数据结构之二叉树 有幸掌握浅薄知识,不吝分享,保持独立思考,自主学习,共同进步.另求关注,点赞,评论,感谢!(tips:主页有数据结构全部知识点,以及知识点讲解,建立完善的数据结构知识体) 核心算法思 ...
- 初阶数据结构 初识二叉树
初阶数据结构 初识二叉树 一. 树 1. 基本概念 2. 常用术语 3. 代码表示 4. 实际运用 二. 二叉树 1. 基本概念 2. 特殊的二叉树 3. .二叉树的顺序结构及实现 (1)顺序结构 ( ...
最新文章
- Android短信发送流程之普通短信发送(原)
- idea 无法打开项目_Premiere出现quot;项目看来已经损坏,无法打开”的解决方法...
- python定义一个人类_Python类的定义、继承及类对象使用方法简明教程
- JPA一对多循环引用的解决
- [CareerCup] 4.1 Balanced Binary Tree 平衡二叉树
- [转贴]Silverlight Socket 实现收发信息
- 深度剖析 Linux 的 3 种“拷贝”命令
- CoreAnimation-CAKeyframeAnimation
- C#坦克大战流程设计与源代码(1):基本对象类规划
- win10系统迁移后系统重装_Windows10系统迁移后无法更新
- [Luogu P3975] [TJOI2015]弦论
- 引用 和指针 ,简单, 一怔见血
- HDFS开启HA后,Hbase的REGIONSERVERS启动错误(Operation category READ is not supported in state standby)
- Android 修改系统默认输入法
- 数组方法中会更改原数组,不会更改原数组(详细)
- Splay(splay模板)
- 服务器主板插显卡进不了系统,我的主板插上显卡后按电源,开不了机怎么办?...
- 大数据之离线数仓项目搭建(一)
- 【经典蓝牙】蓝牙AVRCP协议分析
- java并发编程实战wwj--------------------第二阶段------------Balking------------------29-30