基础概念  

  二叉树(binary tree)是一棵树,其中每个结点都不能有多于两个儿子。

  二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

    (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;

    (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;

    (3)左、右子树也分别为二叉排序树;

二叉树的遍历

  二叉树的遍历是指从根节点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。二叉树的遍历方式有很多,主要有前序遍历,中序遍历,后序遍历。

前序遍历

  前序遍历的规则是:若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树

中序遍历

  中序遍历的规则是:若树为空,则空操作返回;否则从根节点开始(注意并不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,最后中序遍历右子树。可以看到,如果是二叉排序树,中序遍历的结果就是个有序序列。

后序遍历

  后序遍历的规则是:若树为空,则空操作返回;然后先遍历左子树,再遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。

 

删除结点

  对于二叉排序树的其他操作,比如插入,遍历等,比较容易理解;而删除操作相对复杂些。对于要删除的结点,有以下三种情况:

    1.叶子结点;

    2.仅有左子树或右子树的结点;

    3.左右子树都有结点;

  对于1(要删除结点为叶子结点)直接删除,即直接解除父节点的引用即可,对于第2种情况(要删除的结点仅有一个儿子),只需用子结点替换掉父节点即可;而对于要删除的结点有两个儿子的情况,比较常用处理逻辑为,在其子树中找寻一个结点来替换,而这个结点我们成为中序后继结点。

  可以看到,我们找到的这个用来替换的结点,可以是删除结点的右子树的最小结点(6),也可以是其左子树的最大结点(4),这样可以保证替换后树的整体结构不用发生变化。为什么称为中序后继结点呢?我们来看下这棵树的中序遍历结果 1-2-3-4-5-6-7-8-9。可以很清晰的看到,其实要找的这个结点,可以是结点5的前驱或者后继。

代码实现

package treeDemo;/*** Created by chengxiao on 2017/02/12.*/
public class BinaryTree {//根节点private Node root;/*** 树的结点*/private static class Node{//数据域private long data;//左子结点private Node leftChild;//右子结点private Node rightChild;Node(long data){this.data = data;}}/*** 插入结点* @param data*/public void insert(long data){Node newNode = new Node(data);Node currNode = root;Node parentNode;//如果是空树if(root == null){root = newNode;return;}while(true){parentNode = currNode;//向右搜寻if(data > currNode.data){currNode = currNode.rightChild;if(currNode == null){parentNode.rightChild = newNode;return;}}else{//向左搜寻currNode = currNode.leftChild;if(currNode == null){parentNode.leftChild = newNode;return;}}}}/*** 前序遍历* @param currNode*/public void preOrder(Node currNode){if(currNode == null){return;}System.out.print(currNode.data+" ");preOrder(currNode.leftChild);preOrder(currNode.rightChild);}/*** 中序遍历* @param currNode*/public void inOrder(Node currNode){if(currNode == null){return;}inOrder(currNode.leftChild);System.out.print(currNode.data+" ");inOrder(currNode.rightChild);}/*** 后序遍历* @param currNode*/public void postOrder(Node currNode){if(currNode == null){return;}postOrder(currNode.leftChild);postOrder(currNode.rightChild);System.out.print(currNode.data+" ");}/*** 查找结点* @param data* @return*/public Node find(long data){Node currNode = root;while(currNode!=null){if(data>currNode.data){currNode = currNode.rightChild;}else if(data<currNode.data){currNode = currNode.leftChild;}else{return currNode;}}return null;}/*** 删除结点 分为3种情况* 1.叶子结点* 2.该节点有一个子节点* 3.该节点有二个子节点* @param data*/public boolean delete(long data) throws Exception {Node curr = root;//保持一个父节点的引用Node parent = curr;//删除结点是左子结点还是右子结点,boolean isLeft = true;while(curr != null && curr.data!=data){parent = curr;if(data > curr.data){curr = curr.rightChild;isLeft = false;}else{curr = curr.leftChild;isLeft = true;}}if(curr==null){throw new Exception("要删除的结点不存在");}//第一种情况,要删除的结点为叶子结点if(curr.leftChild == null && curr.rightChild == null){if(curr == root){root = null;return true;}if(isLeft){parent.leftChild = null;}else{parent.rightChild = null;}}else if(curr.leftChild == null){//第二种情况,要删除的结点有一个子节点且是右子结点if(curr == root){root = curr.rightChild;return true;}if(isLeft){parent.leftChild = curr.rightChild;}else{parent.rightChild = curr.rightChild;}}else if(curr.rightChild == null){//第二种情况,要删除的结点有一个子节点且是左子结点if(curr == root){root = curr.leftChild;return true;}if(isLeft){parent.leftChild = curr.leftChild;}else{parent.rightChild = curr.leftChild;}}else{//第三种情况,也是最复杂的一种情况,要删除的结点有两个子节点,需要找寻中序后继结点Node succeeder = getSucceeder(curr);if(curr == root){root = succeeder;return  true;}if(isLeft){parent.leftChild = succeeder;}else{parent.rightChild = succeeder;}//当后继结点为删除结点的右子结点succeeder.leftChild = curr.leftChild;}return true;}public Node getSucceeder(Node delNode){Node succeeder = delNode;Node parent = delNode;Node currNode = delNode.rightChild;//寻找后继结点while(currNode != null){parent = succeeder;succeeder = currNode;currNode = currNode.leftChild;}//如果后继结点不是要删除结点的右子结点if(succeeder != delNode.rightChild){parent.leftChild = succeeder.rightChild;//将后继结点的左右子结点分别指向要删除结点的左右子节点succeeder.leftChild = delNode.leftChild;succeeder.rightChild = delNode.rightChild;}return succeeder;}public static void main(String []args) throws Exception {BinaryTree binaryTree = new BinaryTree();//插入操作binaryTree.insert(5);binaryTree.insert(2);binaryTree.insert(8);binaryTree.insert(1);binaryTree.insert(3);binaryTree.insert(6);binaryTree.insert(10);//前序遍历System.out.println("前序遍历:");binaryTree.preOrder(binaryTree.root);System.out.println();//中序遍历System.out.println("中序遍历:");binaryTree.inOrder(binaryTree.root);System.out.println();//后序遍历System.out.println("后序遍历:");binaryTree.postOrder(binaryTree.root);System.out.println();//查找结点Node node = binaryTree.find(10);System.out.println("找到结点,其值为:"+node.data);//删除结点binaryTree.delete(8);System.out.print("删除结点8,中序遍历:");binaryTree.preOrder(binaryTree.root);}
}二叉树的基本操作

View Code

转载于:https://www.cnblogs.com/godyh/p/10977221.html

数据结构之二叉树--转载相关推荐

  1. 数据结构之二叉树(遍历、建立、深度)

    数据结构之二叉树(遍历.建立.深度) 1.二叉树的深度遍历 二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树的所有结点,使得每个结点被访问一次且仅被访问一次. 对于二叉树的深度遍历,有前序遍历 ...

  2. 【数据结构】二叉树及其相关操作

    二叉树的定义 二叉树是一个由结点构成的有限集合,这个集合或者为空,或者由一个根节点及两棵互不相交的分别称作这个根节点的左子树和右子树的二叉树组成. 二叉树并非一般的树形结构的特殊形式,它们是两种不同的 ...

  3. python数据结构 树_python数据结构之二叉树的建立实例

    先建立二叉树节点,有一个data数据域,left,right 两个指针域 复制代码 代码如下: # -*- coding: utf - 8 - *- class TreeNode(object): d ...

  4. 【关于封装的那些事】 缺失封装 【关于封装的那些事】 泄露的封装 【关于封装的那些事】 不充分的封装 【图解数据结构】二叉查找树 【图解数据结构】 二叉树遍历...

    [关于封装的那些事] 缺失封装 目录 - 缺失封装 为什么不能缺失封装? 缺失封装潜在的原因 未意识到关注点会不断变化 混合关注点 幼稚的设计决策 示例分析一 示例分析二 总结 缺失封装 没有将实现变 ...

  5. python处理mysql数据结构_python环境下使用mysql数据及数据结构和二叉树算法(图)...

    python环境下使用mysql数据及数据结构和二叉树算法(图): 1 python环境下使用mysql 2使用的是 pymysql库 3 开始-->创建connection-->获取cu ...

  6. 数据结构之二叉树:折纸问题——11

    数据结构之二叉树:Python代码解决折纸问题 折纸问题 要求:请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开.此时折痕是凹下去的,即折痕突起的方向指向纸条的背面.如果从纸 ...

  7. 数据结构树二叉树计算节点_查找二叉树中叶节点的数量 数据结构

    数据结构树二叉树计算节点 Algorithm: 算法: One of the popular traversal techniques to solve this kind of problems i ...

  8. 【数据结构】二叉树的python实现

    [数据结构]二叉树的python实现 本博文描述的二叉树是任意二叉树,可以使完全二叉树,也可以是非完全二叉树. 首先声明一个二叉树节点的初始化类TNode,每一个节点都有三个组成部分,节点的元素值,节 ...

  9. 大一新生必看,自学必看,里昂详解数据结构之二叉树

    数据结构之二叉树 有幸掌握浅薄知识,不吝分享,保持独立思考,自主学习,共同进步.另求关注,点赞,评论,感谢!(tips:主页有数据结构全部知识点,以及知识点讲解,建立完善的数据结构知识体) 核心算法思 ...

  10. 初阶数据结构 初识二叉树

    初阶数据结构 初识二叉树 一. 树 1. 基本概念 2. 常用术语 3. 代码表示 4. 实际运用 二. 二叉树 1. 基本概念 2. 特殊的二叉树 3. .二叉树的顺序结构及实现 (1)顺序结构 ( ...

最新文章

  1. Java的API及Object类、String类、字符串缓存区
  2. 52条实用经验,SQL优化不再难!
  3. vj节点_创意编码—如何在JavaScript中创建VJ引擎
  4. 计算机科学与技术范文,计算机科学与技术专业(范文).doc
  5. 了解PS、学习使用html语义化标签和CSS术语
  6. vmware虚拟机使用docker使用代理国外镜像
  7. rssi参数获取_如何获取WlanGetNetworkBssList函数返回值的Rssi值
  8. 爬虫项目实操四、用Scrapy爬取招聘网站的招聘信息
  9. 往超级表格导入Excel,让数据处理不再繁杂!
  10. Flutter CircularProgressIndicator圆形进度指示器
  11. feature map理解
  12. android壁纸软件代码,android高清壁纸APP完整源码HD Wallpaper(服务端+客户端)
  13. c语言企业自动化管理系统,基于C语言制作的人事管理系统-自动化毕业论文.doc...
  14. 浪潮服务器怎么重做raid 、设置pxe 启动
  15. 轻松的玩转Docker的15个小技巧
  16. 互联网快讯:雷军宣布小米正式对标苹果;极米多款投影产品获用户肯定;矽行半导体签约落地苏州高新区
  17. 用 selenium 统计博客总字数
  18. server 服务器文档,aserver 服务器
  19. EasyPlayer-RTSP-Android安卓播放器播放RTSP延迟优化策略,极低延时!
  20. 树状选择框测试用例_分类树测试用例设计工具:CTE XL

热门文章

  1. mysql报错:ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
  2. ASCII码,hex编码,String字符串相互转化及原理
  3. 容器中Bean的生命周期
  4. [渝粤教育] 江西外语外贸职业学院 商务英语口语与实训 参考 资料
  5. 将自己电脑的SSH key添加到GitHub上
  6. ubuntu16.04中ROS-Kinetic报错: not find a package configuration file provided by “gazebo_ros_control“
  7. Latex初学者指南
  8. c# winform 窗体间的传值
  9. Java学习笔记-枚举类
  10. [POJ2406]字符串的幂