二叉查找树

  • 二叉树的一个重要应用就是他在查询中的使用,假设书中每个节点存储一项数据。在我们的案例中,任意复杂的项在java中都容易处理,但为了简单还是假设都是整数。还假设他们都是不重复的整数,使二叉树称为二叉查找树的性质是:

    • 对于树中每个节点X,左子树中所有项小于X中的项
    • 而右子树中的所有元素都大于X中的项目
  • 依据以上规则,意味着改树中所有元素都可以用某种一致的方式排序。

  • 如上图中图一中的树是二叉查找树,但是图二中的树不是,图二中树在其项是3 的节点的右子树 上 有一个节点项是1 ,1< 3,右子节点中数据有小于该节点数据的项目,违反的二叉树的两个规则之一。

二叉查找树的实现

  • 二叉查找树要求所有项都能够排序,那么必定在树中任意两个节点之间都可以进行比较,所以我们必须对树节点实现Comparable接口。节点定义如下,和上篇中定义有一点不同:
/*** 二叉树节点对象定义** @author liaojiamin* @Date:Created in 15:24 2020/12/11*/
public class BinaryNode implements Comparable {private Object element;private BinaryNode left;private BinaryNode right;private int count;public BinaryNode(Object element, BinaryNode left, BinaryNode right) {this.element = element;this.left = left;this.right = right;this.count = 1;}public Object getElement() {return element;}public void setElement(Object element) {this.element = element;}public BinaryNode getLeft() {return left;}public void setLeft(BinaryNode left) {this.left = left;}public BinaryNode getRight() {return right;}public void setRight(BinaryNode right) {this.right = right;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}@Overridepublic int compareTo(Object o) {if(o == null){return 1;}int flag = this.element.toString().compareTo(o.toString());if(flag == 0){return 0;}else if (flag > 0){return 1;}else {return -1;}}
}
  • 二叉查找树对应相关方法实现:
/*** 二叉查找树实现** @author liaojiamin* @Date:Created in 15:42 2020/12/15*/
public class BinarySearchTree {public void makeEmpty(BinaryNode root) {root = null;}public boolean isEmpty(BinaryNode root) {return root == null;}/*** 节点元素是否存在** @author: liaojiamin* @date: 15:48 2020/12/15*/private boolean contains(Object x, BinaryNode t) {if (x == null) {return false;}if (t == null) {return false;}int flag = t.compareTo(x);if (flag > 0) {return contains(x, t.getLeft());} else if (flag < 0) {return contains(x, t.getRight());} else {return true;}}/*** 查找最小元素节点** @author: liaojiamin* @date: 15:48 2020/12/15*/private BinaryNode findMin(BinaryNode t) {if (t == null) {return null;}if (t.getLeft() != null) {return findMin(t.getLeft());}return t;}/*** 查找最大元素节点** @author: liaojiamin* @date: 15:48 2020/12/15*/private BinaryNode findMax(BinaryNode t) {if (t == null) {return null;}if (t.getRight() != null) {return findMax(t.getRight());}return t;}/*** 插入节点** @author: liaojiamin* @date: 15:48 2020/12/15*/private BinaryNode insert(Object x, BinaryNode t) {if (x == null) {return t;}if (t == null || t.getElement() == null) {t = new BinaryNode(x, null, null);return t;}int flag = t.compareTo(x);if (flag > 0) {t.setLeft(insert(x, t.getLeft()));} else if (flag < 0) {t.setRight(insert(x, t.getRight()));} else {t.setCount(t.getCount() + 1);}return t;}/*** 删除节点** @author: liaojiamin* @date: 15:48 2020/12/15*/private BinaryNode remove(Object x, BinaryNode t) {if (x == null) {return t;}int flag = t.compareTo(x);if (flag > 0) {return remove(x, t.getLeft());} else if (flag < 0) {return remove(x, t.getRight());} else if (t.getLeft() != null && t.getRight() != null) {//找到对应节点,将节点右子树下面最小的值替换当前值BinaryNode min = findMin(t.getRight());t.setElement(min.getElement());//递归删除右子树下最小值remove(min.getElement(), t.getRight());} else {//找到对应节点,但是当前节点只有一个子节点// 递归思想:只考虑最简单情况,当只有当前节点与其左子节点,删除当前节点返回当节点左子节点,右节点同理t = t.getLeft() != null ? t.getLeft() : t.getRight();}return t;}/*** 按顺序打印节点信息:左中右** @author: liaojiamin* @date: 15:48 2020/12/15*/public void printTree(BinaryNode t) {if (t == null || t.getElement() == null) {return;}printTree(t.getLeft());for (int i = 0; i < t.getCount(); i++) {System.out.print(t.getElement() + " ");}printTree(t.getRight());}public static void main(String[] args) {BinaryNode node = new BinaryNode(null, null, null);BinarySearchTree searchTree = new BinarySearchTree();Random random = new Random();for (int i = 0; i < 20; i++) {node = searchTree.insert(random.nextInt(1000), node);}System.out.println(searchTree.findMax(node).getElement());System.out.println(searchTree.findMin(node).getElement());searchTree.printTree(node);if(!searchTree.contains(13, node)){node = searchTree.insert(13, node);}System.out.println(searchTree.contains(13, node));node = searchTree.remove(13, node);System.out.println(searchTree.contains(13, node));}
}
方法解析:
containes方法
  • 如果在树T中包含有项目X的节点,你们这个需要返回True,否则放回false。我们用两个递归调用来实现这个方法,其实也可以用while循环来替代递归调用。但是这里用递归也是合理的,因为算法表达式的简单性是以降低速度为代价的,而这里所使用的栈空间的量也不过是O(logN)而已
findMin,findMax方法
  • 同样递归,依据二叉查找树的规则左子树永远小于本节点,所以一直向左节点递归 可以得到最小值,同样,一直向右节点递归可以得到最大值
insert方法
  • 插入操作概念是简单的。为了将X插入到树T中,可以用contains方法那样沿着树查找。如果找到X,则更新数量。否则将X插入到变量的路径上的最后一个点上。如下图显示,为了插入4, 我们遍历改树就好像在运行contains。在具有关键字的1节点处我们需要向右边行进,但是右边不存在子树,因此4不在这棵树上,从而这个位置就是我们要插入的位置,将4节点的引用交给 1 节点的right
  • 重复插入可以在节点距离中保留一个附加字段频率来处理,就想我们定义的count

remove方法
  • 在集合相关API中医院,最困难的是remove删除操作。因为我们发现要删除的对应节点,需要考虑多种情况

    • 如果节点是叶子节点,那么可以立刻删除,
    • 如果节点有一个儿子节点,则该节点卡伊在其父节点调整自己的链,从而绕过改节点后逻辑上被删除
    • 最复杂情况,处理具有两个儿子节点,一般的删除策略是用其右子树的最小数据代替该节点的数据,并递归的删除那个最小的数据(相当于将右子树最小数据和需要删除数据做替换),因为右子树的最小节点不可能有左节点,所以第二次remove要容易。
    • 下面分别图示一个子节点和两个子节点的情况
  • 一个节点情况

  • 两个子节点情况,删除5 节点,将右子树中最小节点6 和 5 替换,再删除 右子树最小节点6:

平均时间复杂度分析

  • 二叉树我们期望的平均时间复杂度是O(logN)时间,但是一颗二叉查找树在不断的insert和remove的过程中,由于上面我们所采用的的删除策略有助于使得左子树的深度比右子树更深,因为我们总是用右子树中最小的节点去替换需要删除的节点。这种方案的准确性是已经在业界证明可行,就避免不了最终不平衡的可能。
  • 我们在删除过程中可以通过随机选取右子树的最小元素 和 左子树的最大元素来代替删除元素的策略来消除这种不平衡问题,但是这种做法还没有人能证明可行性。
  • 好像不能完全解决平衡问题,出发我们增加一个平衡(balance)的附加条件:任何节点深度不得过深那就是AVL树。

上一篇:数据结构与算法–重建二叉树
下一篇:数据结构与算法–AVL树原理及实现

数据结构与算法--二叉查找树实现原理相关推荐

  1. 数据结构与算法--二叉查找树转顺序排列双向链表

    二叉查找树转顺序排列双向链表 题目:输入一颗二叉查找树,将二叉查找树转成一个排序的双向链表,要求不能创建任何新节点,只调整树节点中指针的指向.例如下图所示: 本次二叉查找树节点定义使用之前文章 数据结 ...

  2. 数据结构与算法--B树原理及实现

    B树 前几篇文中讨论的数据结构我们都是假设所有的数据都存储在计算机的主存中.可说总要那么海量的数据需要通过个中数据结构去存储,我们不可能有这么多内存区存放这些数据.那么意味着我们需要将他们放磁盘.所以 ...

  3. 怎样将树的中序遍历的数输入到一个数组中_数据结构与算法-二叉查找树平衡(DSW)...

    上一节探讨了二叉查找树的基本操作,二叉查找树的查找效率在理想状态下是O(lgn),使用该树进行查找总是比链表快得多.但是,该论点并不总是正确,因为查找效率和二叉树的形状息息相关.就像这样: 图1-1给 ...

  4. 数据结构与算法--二叉树实现原理

    二叉树 二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的子节点 二叉树的一个性质是一颗平均二叉树的深度要比节点个数N小得多(重点),对二叉树的分析得出其平均深度为O(N\sqr ...

  5. [数据结构与算法]-二叉查找树(BLT)介绍及其实现(Java)

    本文欢迎转载,转载前请联系作者,经允许后方可转载.转载后请注明出处,谢谢! http://blog.csdn.net/colton_null 作者:喝酒不骑马 Colton_Null from CSD ...

  6. 数据结构与算法——堆的原理和实现

    目录 一.堆的原理 二.堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一.堆 ...

  7. python 快速排序 详解_数据结构与算法:快速排序(原理讲解+python实现)

    快速排序 快速排序是一种基于分治法(Divide and Conquer)的排序算法 它之所以称为快速排序是因为它的平均时间复杂度为O(nlogn),最坏情况下是O(n2) 但是这样的情况不常见 一般 ...

  8. 数据结构与算法-二叉查找树(java描述)

    一.概述 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树. 1.1.定义 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: ...

  9. 一步搞定你疑惑的数据结构与算法系列,原理+实战讲解

    蚂蚁金服一面: 下午杭州的电话,问有没有空,果断有空,虽然感觉略显紧张,有点懵逼. 面试的题目: HashMap和Hashtable的区别 实现一个保证迭代顺序的HashMap 说一说排序算法,稳定性 ...

最新文章

  1. 20145223 《信息安全系统设计基础》课程总结
  2. 【铜】第174-9篇 一对一视频录制(九)一对多学生端删除白板及nginx下配CI
  3. 新东方财报背后:增收不增利之下,“下沉”“上线”能有坦途?
  4. 天兔安装手册-第一篇文章
  5. 金融业务数字化,用户体验和安全防护双重挑战,你该怎么办?
  6. 出租车管理系统java_基于jsp的出租车管理系统-JavaEE实现出租车管理系统 - java项目源码...
  7. 一个模型使召回阶段又准确又多样
  8. OGG_GoldenGate日常维护(案例)
  9. 软件包的安装(源码安装)
  10. 第2章—装配Bean—自动化装配Bean
  11. Android Studio 编译失败 Could not read entry ':app:processDebugManifest' from cache taskArtifacts.bin
  12. c语言二级考试题库及答案,c语言二级考试题库
  13. 如何成为优秀的技术主管-管理篇
  14. EasyAR WebAR开发
  15. 语音端点matlab,语音端点检测及其在Matlab中的实现
  16. 西门子opc服务器注册,西门子OPC服务器怎么做
  17. 内容过于真实,可能会引起不适-----程序员去面试的梗!面试官:“哦了,明天来上班吧”
  18. JAVA运行内存的设置
  19. WebView网页视频统一全屏播放及横竖屏切换
  20. glue logic-胶合逻辑

热门文章

  1. IOS学习笔记七之KVC和Key路径
  2. C++之inline函数使用总结
  3. linux c之((void *) - 1)是啥意思
  4. Android之OKHttp使用总结
  5. 栈和队列之用2个栈实现一个队列
  6. hse不起振 stm8_STM8S207使用外部24M晶振不起振的解决办法
  7. unity webgl读写txt文件_VB 读写txt文件
  8. 中国25个最“吓人”地名,看完都被吓笑了!
  9. 程序员没有女朋友的原因,我终于找到了!
  10. 程序员年入50万,我们该如何努力达到这个目标?