Java数据结构与算法(八)-二叉树
一、为什么要使用树
- 有序数组插入、删除数据慢。
- 链表查找数据慢
- 树可以解决这两个问题
二、相关术语
- 树的结点:包含一个数据元素及若干指向子树的分支;
- 孩子结点:结点的子树的根称为该结点的孩子;
- 双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
- 兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
- 祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中* 任一结点都称为该结点的子孙
- 结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
- 树的深度:树中最大的结点层
- 结点的度:结点子树的个数
- 树的度: 树中最大的结点度。
- 叶子结点:也叫终端结点,是度为 0 的结点;
- 分枝结点:度不为0的结点;
- 有序树:子树有序的树,如:家族树;
- 无序树:不考虑子树的顺序;
三、基本操作
- 插入结点
- 从根结点开始查找一个相应的结点,这个结点成为新插入结点的父节点,当父节点找到后,通过判断新结点的值比父节点的值的大小来决定是连接到左子结点还是右子结点
- 查找结点
- 从根结点开始查找,如果查找的结点值比当前的结点的值小,则继续查找其左子树,否则查找其右子树。
- 遍历二叉树
- 遍历树是根据一个特定的顺序访问树的没一个节点,根据顺序的不通氛围前序、中序、后序三中遍历。
- 前序
- 访问跟节点
- 前序遍历左子树
3.遍历右子树
- 中序
- 遍历左子树
- 访问跟节点
3.遍历右子树
- 后序
- 遍历左子树
- 遍历右子树
3.访问跟节点
- 删除二叉树节点
- 删除是最复杂的,在删除之前首先要查找要删的节点。找到节点后,这个要删除的节点可能会有三中情况需要考虑。
- 该节点是叶子节点,没有子节点
- 要删除叶子节点,只需要改变该节点的父节点的引用值,将指向该节点的引用设置为null就可以了。
- 该节点有一个子节点
- 改变父节点的引用,将其直接指向要删除节点的子节点。
- 该节点右两个子节点
- 要删除右两个子节点的节点,就需要使用他的中序后继来替代该节点。
代码实现
package com.fantj.dataStruct.tree;/*** 二叉树结点* Created by Fant.J.* 2017/12/22 16:09*/
public class Node {//数据项public long data;//左子结点public Node leftChild;//右子结点public Node rightChild;//构造方法public Node(long data){this.data = data;}
}
package com.fantj.dataStruct.tree;/*** 二叉树* Created by Fant.J.* 2017/12/22 16:11*/
public class Tree {//根结点public Node root;/** 插入结点 */public void insert(long value){//封装结点Node newNode = new Node(value);//引用当前结点Node current = root;//引用父节点Node parent;//如果root为null,也就是第一次插入的时候if (root == null){root = newNode;return;}else {while (true){//父节点指向当前结点parent = current;//如果当前指向的结点数据比插入的要大,则向左走if (current.data > value){current = current.leftChild;if (current == null){parent.leftChild = newNode;return;}}else {//生成一个右子节点,并且赋值为 newNodecurrent = current.rightChild;if (current == null){parent.rightChild = newNode;return;}}}}}/* 查找节点 **/public Node find(long value){//引用当前节点,从根节点开始Node current = root;//循环,只要查找值不等于当前节点值while (current.data != value){//进行比较,比较查找值和当前节点的大小if (current.data > value){current = current.leftChild;}else {current = current.rightChild;}//如果是空,则退出if (current == null){return null;}}return current;}/* 前序遍历 **/public void frontOrder(Node localNode){if (localNode != null){//访问根节点System.out.print(localNode.data+",");//前序遍历左子树frontOrder(localNode.leftChild);//前序遍历右子树frontOrder(localNode.rightChild);}}/* 中序遍历 **/public void inOrder(Node localNode){if (localNode != null){//中序遍历左子树inOrder(localNode.leftChild);//访问根节点System.out.print(localNode.data+",");//中序遍历右子树inOrder(localNode.rightChild);}}/* 后序遍历 **/public void afterOrder(Node localNode){if (localNode != null){//后序遍历左子树afterOrder(localNode.leftChild);//后序遍历右子树afterOrder(localNode.rightChild);//访问根节点System.out.print(localNode.data+",");}}/* 删除结点 **/
}
这里我把删除节点的操作单独拿出来*(因为比较复杂)
/* 删除结点 **/public boolean delete(long value){//引用当前节点,从根节点开始Node current = root;//引用当前节点的父节点Node parent = root;//是否右左子节点boolean isLeftChild = true;while (current.data != value){parent = current;//进行比较,比较value和当前节点if (current.data > value){current = current.leftChild;isLeftChild = true;}else {current = current.rightChild;isLeftChild = false;}//如果查找不到if (current ==null){return false;}}//删除叶子节点,也就是该节点没有子节点if (current.leftChild == null && current.rightChild == null){if (current == root){root = null;}//如果是左子节点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 (root == current){root = current.rightChild;}if (isLeftChild){parent.leftChild = current.rightChild;}else {parent.rightChild = current.rightChild;}}else {//获取中序后继节点Node succeed = getSucceed(current);if (current == root){root = succeed;}else if (isLeftChild){parent.leftChild = succeed;}succeed.leftChild = current.leftChild;}return true;}/* 找到后继(succeed)节点 , 后继是按照中序先找右子树,然后找左节点**/public Node getSucceed(Node delNode){Node succeed = delNode;Node succeedParent = delNode;Node current = delNode.rightChild;while (current != null){succeedParent = succeed;succeed = current;current = current.leftChild;}if (succeed != delNode.rightChild){succeedParent.leftChild = succeed.rightChild;succeed.rightChild = delNode.rightChild;}return succeed;}
Java数据结构与算法(八)-二叉树相关推荐
- Java数据结构与算法:二叉树
原文链接:http://www.cnblogs.com/skywang12345/p/3576452.html 1. 二叉查找树简介 二叉查找树(Binary Search Tree),又被称为二叉搜 ...
- Java数据结构和算法:二叉树
二叉树的实现 数组查询快,增删慢:链表增删快,查询慢:二叉树查询和增删都有很好的性能 package com.itheiam62;/*** @描述 中序遍历是有序的二叉树(不重复)* */ publi ...
- 二叉树 BinaryTree (先序、中序、后序遍历 节点查找、插入、删除 完整类) Java数据结构与算法
二叉树 BinaryTree (先序.中序.后序遍历 节点查找.插入.删除 完整类) Java数据结构与算法 源代码: view plain /** * * @author sunnyykn */ i ...
- 数据结构 - Java -韩顺平 图解Java数据结构和算法
数据结构 Lesson 1 数据结构的知识总结 1. 几个经典的算法面试题 2. 线性结构与非线性结构 2.1 稀疏数组 sparsearray 2.2 队列 2.2.1 顺序队列: 2.2.2 环形 ...
- Java数据结构与算法——树(基本概念,很重要)
声明:码字不易,转载请注明出处,欢迎文章下方讨论交流. 有网友私信我,期待我的下一篇数据结构.非常荣幸文章被认可,也非常感谢你们的监督. 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督 ...
- 常考数据结构与算法:输出二叉树的右视图
题目描述 请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图 上图树的右视图为:{1,4,3,7} 做此题之前可以先做下面3道题: 1. 常考数据结构与算法:求二叉树的层序遍历 2.常 ...
- Java数据结构和算法(一)——简介
本系列博客我们将学习数据结构和算法,为什么要学习数据结构和算法,这里我举个简单的例子. 编程好比是一辆汽车,而数据结构和算法是汽车内部的变速箱.一个开车的人不懂变速箱的原理也是能开车的,同理一个不懂数 ...
- java数据结构与算法之顺序表与链表深入分析
转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结 ...
- Java数据结构与算法(二)
Java数据结构与算法(二) 第六章 递归 1 递归应用场景 2 递归的概念 3 递归调用机制 4 递归能解决什么样的问题 5 递归需要遵守的重要规则 6 递归-迷宫问题 6.1 迷宫问题 6.2 代 ...
最新文章
- 【Ubuntu】ubuntu webqq桌面版pywebqq
- ubuntu 进入 recovery mode
- 前端资源构建-Grunt环境搭建
- 刚刚,阿里发布AI谣言粉碎机,识别准确率达81%
- 第9课_2_dbsoft安装
- 计算机地址栏搜索不了网,我的电脑地址栏不见了怎么办 地址栏不见了如何解决...
- Java垃圾回收(1)
- C++中常引用的注意事项以及常引用和非常引用之间的转换
- 乒乓球单循环赛_乒乓球淘汰赛制和单循环赛制的比赛方法是什么?
- 零基础程序员如何自学编程?用这6种方法就够了!
- VeraCrypt磁盘加密软件
- 利用基准电压效正Vcc做参考电压的ADC采样计算方法
- 算法工程师的职业发展前景思考和总结
- 告诉你一个真实的Google
- net bios支持服务器,禁用NetBIOS巧妙解决网络不通故障
- 支付宝转账又出新方法:悬浮条自动识别输入,避免失误尴尬
- F5 GTM DNS 知识点和实验 3 -加速dns解析
- windows显示WiFi密码
- 三井化学将增加TAFMER™高性能弹性体产能
- 【C语言】C语言的简介
热门文章
- 【GStreamer】在x264enc中设置profile级别
- mybatis foreach map_Spring Boot(五):春眠不觉晓,Mybatis知多少
- integer比较_傻傻分不清?Integer、new Integer() 和 int 的面试题
- oracle创建用户名授权,oracle创建用户及授权创建表
- 【Linux】Linux简单操作之文件管理
- 编写spring应用
- Android架构篇-3 网络接口封装
- this和that的区别和原理
- 微信小程序多张图片和表单一起上传,验证表单及进度条的实现完整代码
- iOS infoplist 权限设置