JAVA数据结构之二叉树
用树作为存储数据的结构兼具像数组一样查询速度快和像链表一样具有很快的插入和删除数据项的优点
我们用圆点表示节点,连接圆的直线表示边如下图所示就表示了一颗树,接下来我们讨论的二叉树即每个节点最多只有两个子节点的树称作是二叉树。除了二叉树还有多路树,比如2-3-4树和外部存储就属于多路树

二叉搜索树:一个节点的左子节点关键字小于这个节点,右子节点关键字大于或等于这个父节点,

在java中我们要设计一个树可以只用下面的代码
class Node{ //树节点类 class Person{ //封装树节点的数据 class Tree{ //相当于树的根节点
Person person; int iData; private Node root;
Node leftChild; double dData; //包含一些操作树的方法
Node rightChild; } }
}
二叉树查找元素
下图展示了在搜索二叉树中查找关键值为57的节点的查找流程图

由上图我们可以写出上面的们Tree类中的查找的方法
- public Node find ( int key ){
- Node current = root;
- while(current.iData != key){
- if(key < current.iData){
- current = current.leftChild;
- }else{
- current = current.rightChild;
- }
- if(current == null){ //说明此时没有找到对应的节点
- return null;
- }
- }
- return current; //循环执行结束跳出循环,说明找到此关键字节点,返回节点
- }
这里我们可以总结出在树中查找节点的效率,首先取决于关键字所在树的层数,像我们图中给出的树最多5层,即查找最多进行5次比较,节点数最多为31准确来说所需要的时间复杂度为O(log2N)
二叉树插入节点
接下来讨论在树中插入一个节点:插入的方法和查找很像,只不过插入在最后一步遇到null不是立即返回null,而需要在返回之前插入节点
- public void insert( int id,double dd){
- Node newNode = new Node; //创建新的节点
- newNode.iData = id;
- newNode.dData = dd;
- if(root == null){
- root = newNode;
- }else{
- Node current = root;
- Node parent; //引入parent是为了记录新节点插入的位置,不然当找到插入的地方会去其插入的父节点的位置
- while(true){
- parent = current;
- if(id< current.iData){
- current = current.leftChild;
- if(current == null){ //说明此时没有找到对应的节点,将新节点连入左子节点
- parrent.leftChild = newNode;
- return;
- }
- }else{
- current = current.rightChild;
- if(current == null){ //说明此时没有找到对应的节点,将新节点连入右子节点
- parrent.rightChild= newNode;
- return;
- }
- }
- }
- }
- }
遍历二叉树
接下来我们介绍遍历一个二叉树:我们常用的遍历树的方法有三种:前序,中序,后序。二叉树中常用的遍历方式是中序遍历,这里我们遍历的方法只需要做三件事情,1.调用自身来遍历节点的左子树,2.访问这个节点,3.调用自身来遍历节点的右子树,下面是java代码
- public void inOrder(Node localRoot){ //使用递归的方式来遍历一颗树
- if(localRoot != null){
- inOrder(localRoot.leftChild); //遍历左子树
- System.out.print(localRoot.iData+" "); //访问自身数据
- inOrder(localRoot.rightChild); //遍历右子树
- }
- }


前序遍历步骤 :1.访问这个节点,2.调用自身来遍历节点的左子树,3.调用自身来遍历节点的右子树
后序遍历步骤 :1.调用自身来遍历节点的左子树,2.调用自身来遍历节点的右子树,3.访问这个节点
查找二叉搜索树中的最大最小值:最小值一直往树的最左边往下查找即可得到最小值,相反向右可得到最大值。
- public Node minimum(){ //查找二叉搜索树中的最小值
- Node current,last;
- current = root;
- while(current != null){
- last = current;
- current = current.leftChild; //将这里换成Right即可查询的到最大值
- }
- return last;
- }
删除二叉树中的节点
接下来介绍二叉树如何删除一个节点,要删除二叉树的节点我们需要考虑到三种删除的状态:
1.该节点是叶节点,是叶节点的情况删除很简单,只需要将父节点对应的子节点改为null即可,如图
2.节点有一个子节点,删除该节点,只需要将需要删除的节点的唯一一个子节点连接到需要删除的节点的父节点之上,如图
3.有两个子节点,若有两个子节点,则需要找到该删除节点的中序后继节点来替换当前删除的节点(找后继节点的算法简单来说就是先向该节点右边找到子节点,然后一直往左边找到最小值即可得到该节点的后继节点)



接下来写出完整的删除节点的java代码
- public boolean delete(int key){
- Node current = root;
- Node parent = root;
- boolean isLeftChild = true;
- while(current.iData != key){
- parent = current;
- if(key < current.iData){
- isLeftChild = true;
- current = current.leftChild;
- }else{
- isLeftChild = false;
- current = current.rightChild;
- }
- if(current == null){
- return; //没有找到需要删除的数据项,直接返回
- }
- }
- //1.如果删除的节点是叶子结点,直接删除
- if(current.leftChild == null && current.rightChild == null){
- if(current == root){
- root = null;
- }else if(isLeftChild){
- parent.leftChild = null;
- }else{
- parent.rightChild = null;
- }
- }else if(current.rightChild == null){ //删除的节点只有左子节点
- if(current == root){
- root = current.leftChild;
- }else if(isLeftChild){
- parent.leftChild = current.leftChild;
- }else{
- parent.rightChild = current.leftChild ;
- }
- }else if(current.leftChild == null){ //删除的节点只有右子节点
- if(current == root){
- root = current.leftChild;
- }else if(isLeftChild){
- parent.leftChild = current.rightChild ;
- }else{
- parent.rightChild = current.rightChild ;
- }
- }else{
- Node successor = getSuccessor(current); //查找得到删除节点的后继
- if(current == root){
- root = successor;
- }else if(isLeftChild){
- parent.leftChild = successor;
- }else{
- parent.rightChild = successor;
- }
- successor.leftChild = current.leftChild; //最后一步设置删除替换后的左子节点
- }
- }
- //查找后继节点的算法
- private Node getSuccessor(Node delNode){
- Node successorParent = delNode;
- Node successor = delNode;
- Node current = delNode.rightChild;
- While(current!=null){
- successorParent = successor;
- successor = current;
- current = current.leftChild;
- }
- if(successor != delNode.rightChild){
- successorParent.leftChild = successor.rightChild;//将后继节点的父节点的左子节点值设置为后继的右子节点
- successor.rightChild = delNode.rightChild;//将后继节点的右子节点设置成当前删除节点的右子节点(处理后)
- }
- return successor;
- }
二叉树的效率
二叉树的效率:二叉树的效率取决于二叉树的层数(层数即为操作时最多的比较次数),下表给出了一个二叉满树的节点数和层数的关系,我们可以设第一列节点数为N层数为L,那么
N = 2L-1 <=> L = (log2N+1)
这里我们能换算成大O表示的时间复杂度为O(logN)。同样层数的不满的树的用时是要小于满树的时间的,树对于常用的数据存储操作有很高的效率,遍历不如其他的操作快。

JAVA数据结构之二叉树的更多相关文章
- java数据结构之二叉树的实现
java二叉树的简单实现,可以简单实现深度为n的二叉树的建立,二叉树的前序遍历,中序遍历,后序遍历输出. /** *数据结构之树的实现 *2016/4/29 * **/ package cn.Link ...
- Java数据结构之二叉树的基本介绍与递归遍历
二叉树的基本概念: 正如我们所了解的,树是有很多中形态,但是我们规定,形如每个节点最多只能有两个子节点的一种形如称为二叉树.我们将二叉树中该节点的两个子节点分别称作为:左孩子节点和右孩子节点.该节点称 ...
- java数据结构之二叉树遍历的非递归实现
算法概述递归算法简洁明了.可读性好,但与非递归算法相比要消耗更多的时间和存储空间.为提高效率,我们可采用一种非递归的二叉树遍历算法.非递归的实现要借助栈来实现,因为堆栈的先进后出的结构和递归很相似.对 ...
- java数据结构之二叉树的定义和递归实现
定义最多有两棵子树的有序树,称为二叉树.二叉树是一种特殊的树.递归定义:二叉树是n(n>=0)个有限结点构成的集合.N=0称为空二叉树:n>0的二叉树由一个根结点和两互不相交的,分别称为左 ...
- Java数据结构之树和二叉树(2)
从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...
- Java数据结构之树和二叉树
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- Java数据结构和算法 - 二叉树
前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...
- Java数据结构和算法(六)--二叉树
什么是树? 上面图例就是一个树,用圆代表节点,连接圆的直线代表边.树的顶端总有一个节点,通过它连接第二层的节点,然后第二层连向更下一层的节点,以此递推 ,所以树的顶端小,底部大.和现实中的树是相反的, ...
- 【java 数据结构】还不会二叉树?一篇搞定二叉树
二叉树是我们常见的数据结构之一,在学习二叉树之前我们需要知道什么是树,什么是二叉树,本篇主要讲述了二叉树,以及二叉树的遍历. 你能get到的知识点? 1.树的介绍 2.二叉树的介绍 3.二叉树遍历的四 ...
随机推荐
- 0 ‘+new Array(017)’ 输出? js+相当于Number()类型转换
网站搬迁,给你带来的不便敬请谅解! http://www.suanliutudousi.com/2017/10/20/new-array017-%E8%BE%93%E5%87%BA%EF%BC%9F- ...
- python学习10—迭代器、三元表达式与生成器
python学习10—迭代器.三元表达式与生成器 1. 迭代器协议 定义:对象必须提供一个next方法,执行该方法或者返回迭代中的下一项,或者返回一个StopIteration异常,以终止迭代(只能往 ...
- Codeforces Round #527 F - Tree with Maximum Cost /// 树形DP
题目大意: 给定一棵树 每个点都有点权 每条边的长度都为1 树上一点到另一点的距离为最短路经过的边的长度总和 树上一点到另一点的花费为距离乘另一点的点权 选定一点出发 使得其他点到该点的花费总和是最大 ...
- Avito Cool Challenge 2018 B - Farewell Party
题目大意: 有n个人 接下来一行n个数a[i] 表示第i个人描述其他人有a[i]个的帽子跟他不一样 帽子编号为1~n 如果所有的描述都是正确的 输出possible 再输出一行b[i] 表示第i个人的 ...
- Solr6.6环境安装及core的创建(win7环境)
1.下载solr6.6 并解压 地址: http://www.apache.org/dyn/closer.lua/lucene/solr/6.6.0 2.安装JDK1.8 地址: http://www ...
- 操作bin目录下的文件
string dir = AppDomain.CurrentDomain.BaseDirectory + "Video"; if (!System.IO.Directory.Exi ...
- [转] js对键盘输入事件绑定到特定按钮。
<script type="text/javascript" language="javascript"> document.onkeyup = f ...
- Centos7 PXE Server Install Script
#安装前配置好centos和epel yum源 #网卡ip和localip一致 localip="192.168.88.200" eth_name='eth0' dnsmasq_i ...
- MySQL高可用配置(主从复制)
主从复制包含两个步骤: 在 master 主服务器(组)上的设置,以及在 slave 从属服务器(组)上的设置. 环境: MASTER: 192.168.155.101SLAVE: 192.168.1 ...
- struts2验证器
1. Struts2 的验证(note6,struts2-8) 1). 验证分为两种: > 声明式验证* >> 对哪个 Action 或 Model 的那个字段进行验证 >&g ...