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


一.什么是二叉查找树?

二叉查找树(Binary Search Tree, BST)是二叉树的一种。

简单来说,二叉查找树的特有性质是:对于树中的每个节点N,它的左子树中所有的元素值小于N中的值,所有右子树中的所有的元素值大于N中的值。

如图所示。

二.二叉查找树的作用

二叉排序树在数组和链表结构之间,对数据存储的一种折中方案。及能保证一定的插入删除效率,又保证了数据查找的效率。

通常情况下,对于查找操作操作,保证操作在O(logN)时间。这就是完成了哈希表不便完成的工作,动态性。但是二叉树有可能出现worst-case——最坏的情况,即如果输入序列已经排序,则时间复杂度为O(N)。

三.实现二叉查找树

  1. BinaryNode类:为内部静态类(嵌套类),用于描述节点信息。节点中的元素对象,必须要实现Comparable接口,因为元素必须能比较出大小,即要通过compareTo()方法进行值的大小比较。
  2. makeEmpty():使树置空,直接将根节点置空即可。
  3. isEmpty():判断树是否为空,判断根节点是否为空即可。
  4. contains(T t):查看t元素是否在树中。
  5. findMin():查找最小值。沿着根遍历只查左节点,直到某个节点的左节点为空,则该节点的值为最小值。方法有两种,递归和非递归法。
  6. findMax():查找最大值。思路痛findMin()。
  7. insert(T t):将元素t插入到树中。
  8. remove(T t):将t元素删除。这里重点说一下删除操作。
    a)如果被删除的节点是一个树叶(即没有子节点的节点),则它可以立即被删除。
    b)如果被删除是节点有一个左节点或者右节点,则可以让该节点的父节点直接指向该节点的子节点。如图所示,删除节点50。

    c)麻烦的是删除同时有两个子节点的节点。一般的方式是:用被删除的节点的右子树中最小的节点的值来代替被删除节点的值,并且删除那个最小的节点。因为右子树中最小的节点不可能有做儿子,所以第二次remove只可能是a)或者b)中的情况,所以要容易的多。如图所示,删除节点200。

    PS:有关remove()的方法,我改进了《数据结构与算法分析(第3 版) 工业出版社》中的方法。对于c)所说的情况,只进行了一次遍历查找最小值并删除(树中是遍历两次)。思路在注解中有写。

四.实现代码

BinarySearchTree.java

/*** Created with IDEA* Author: MaYuzhe* Date: 2018/6/17* Time: 15:11* <p>* BinarySearchTree 二叉查找树*/
public class BinarySearchTree<T extends Comparable<? super T>> {private static class BinaryNode<T> {BinaryNode(T t) {this(t, null, null);}BinaryNode(T t, BinaryNode<T> left, BinaryNode<T> right) {this.element = t;this.left = left;this.right = right;}T element;BinaryNode<T> left;BinaryNode<T> right;}private BinaryNode<T> root;public BinarySearchTree() {this.root = null;}/*** 将树清空*/public void makeEmpty() {this.root = null;}/*** 判断是否为空** @return 为空则返回true,否则返回false*/public boolean isEmpty() {return this.root == null;}public boolean contais(T t) {return contains(t, root);}public T findMin() {if (isEmpty()) {return null;}return findMin(root).element;}public T findMax() {if (isEmpty()) {return null;}return findMax(root).element;}public void insert(T t) {root = insert(t, root);}public void remove(T t) {root = remove(t, root);}public void printTree() {if (isEmpty()) {System.out.println("空树/Empty tree");} else {printTree(root);}System.out.println();}/*** 中序遍历方式打印树** @param node*/private void printTree(BinaryNode<T> node) {if (node != null) {printTree(node.left);System.out.println(node.element);printTree(node.right);}}/*** 判断被判断的元素在节点哪侧,递归判断。** @param t    被判断的元素* @param node 当前节点* @return 如果有相等的值则返回true。否则返回false*/private boolean contains(T t, BinaryNode<T> node) {if (node == null) {return false;}int compareResult = t.compareTo(node.element);if (compareResult < 0) {return contains(t, node.left);} else if (compareResult > 0) {return contains(t, node.right);} else {return true;}}/*** 寻找最小节点(递归)** @param node* @return*/private BinaryNode<T> findMin(BinaryNode<T> node) {if (node == null) {return null;} else if (node.left == null) {return node;}return findMin(node.left);}/*** 寻找最大节点(递归)** @param node* @return*/private BinaryNode<T> findMax(BinaryNode<T> node) {if (node == null) {return null;} else if (node.right == null) {return node;}return findMax(node.right);}//    /**
//     * 寻找最小节点(非递归)
//     * @param node
//     * @return
//     */
//    private BinaryNode<T> findMin(BinaryNode<T> node) {
//        if(node != null) {
//            while (node.left != null) {
//                node = node.left;
//            }
//        }
//        return node;
//    }//    /**
//     * 寻找最大节点(非递归)
//     * @param node
//     * @return
//     */
//    private BinaryNode<T> findMax(BinaryNode<T> node) {
//        if (node != null) {
//            while (node.right != null) {
//                node = node.right;
//            }
//        }
//        return node;
//    }/*** 插入操作** @param t* @param node* @return*/private BinaryNode<T> insert(T t, BinaryNode<T> node) {if (node == null) {return new BinaryNode<>(t, null, null);}int compareResult = t.compareTo(node.element);if (compareResult < 0) {node.left = insert(t, node.left);} else if (compareResult > 0) {node.right = insert(t, node.right);}return node;}/*** 删除节点** @param t* @param node* @return*/private BinaryNode<T> remove(T t, BinaryNode<T> node) {if (t == null) {return null;}int compareResult = t.compareTo(node.element);if (compareResult < 0) {node.left = remove(t, node.left);} else if (compareResult > 0) {node.right = remove(t, node.right);} else if (node.left != null && node.right != null) {
//            node.element = findMin(node.right).element;
//            node.right = remove(node.element, node.right);// 用removeRightMin方法替代上面两个操作,将两次遍历合并成一次遍历完成,提高效率node.right = removeRightMin(node, node.right);} else {node = node.left != null ? node.left : node.right;}return node;}/*** 删除右侧做小节点** @param node* @param rNode* @return*/private BinaryNode<T> removeRightMin(BinaryNode<T> node, BinaryNode<T> rNode) {if (rNode.left != null) {rNode.left = removeRightMin(node, rNode.left);} else {node.element = rNode.element;rNode = rNode.right;}return rNode;}
}

测试类
BinarySearchTreeTest.java

/*** Created with IDEA* Author: MaYuzhe* Date: 2018/6/17* Time: 15:42** BinarySearchTreeTest 二叉查找树测试类*/
public class BinarySearchTreeTest {public static void main(String[] args) {BinarySearchTree<Integer> binarySearchTree = new BinarySearchTree<>();// 测试insert,并用中序遍历打印树binarySearchTree.insert(10);binarySearchTree.insert(5);binarySearchTree.insert(1);binarySearchTree.insert(3);binarySearchTree.insert(8);binarySearchTree.insert(6);binarySearchTree.insert(9);binarySearchTree.insert(7);binarySearchTree.insert(17);binarySearchTree.insert(16);binarySearchTree.insert(18);binarySearchTree.printTree();// 测试removebinarySearchTree.remove(5);binarySearchTree.printTree();// 测试isEmpty方法System.out.println("树是否为空:" + binarySearchTree.isEmpty());// 测试containsSystem.out.println("树是否包含16:" + binarySearchTree.contais(16));System.out.println("树是否包含100:" + binarySearchTree.contais(100));// 测试findMin、findMaxSystem.out.println("树的最小数据为:" + binarySearchTree.findMin());System.out.println("树的最大数据为:" + binarySearchTree.findMax());// 测试makeEmptybinarySearchTree.makeEmpty();System.out.println("树是否为空:" + binarySearchTree.isEmpty());}
}

输出

1
3
5
6
7
8
9
10
16
17
181
3
6
7
8
9
10
16
17
18树是否为空:false
树是否包含16:true
树是否包含100:false
树的最小数据为:1
树的最大数据为:18
树是否为空:true

所有功能均正常。

以上就是有关二叉树的介绍及其部分功能的Java实现。


有关[数据结构与算法]的学习内容已经上传到github,喜欢的朋友可以支持一下。
data-structures-and-algorithm-study-notes-java


站在前人的肩膀上前行,感谢以下博客及文献的支持。

  • 二叉树的好处(应用)
  • 《数据结果与算法分析(第3版) 机械工业出版社》

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

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

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

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

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

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

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

  4. JAVA数据结构与算法【简单介绍】

    前几天去面一个大厂,面试官特别好,面试官说到,我们的学习不能本末倒置,数据结构和算法是程序的基础,如果数据结构你没有学好,你真正意义上不算会写代码.你的代码是各处粘贴,杂乱无章的. 由于现在大多用JA ...

  5. 金九银十面试即将到来!字节内部数据结构与算法笔记,限时上线,Java程序员们准备好了吗?

    前言 不得不说,现在几乎所有的大厂,比如Google.字节.BAT,面试的时候都喜欢考算法.让人现场写代码,那你有没有真正地想过,为什么这些大公司都喜欢考算法呢? 经常有人说,程序员35岁之后很容易陷 ...

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

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

  7. 《数据结构与算法之二叉搜索树(Java实现)》

    说在前头:本人为大二在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,能力有限,文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正.若 ...

  8. 数据结构与算法之栈与队列:java实现

    闻理似悟,遇境则迷!!! 栈与队列来说也算是一种特殊的线性表,栈的特点是后进先出,队列的特点是先进先出. 栈 栈的特点是后进先出,栈的操作只有出栈和入栈(也叫压栈),除此之外,还包含栈顶与栈底的指向以 ...

  9. 【数据结构与算法】左式堆的Java实现

    引言 二叉堆是对优先队列的一种高效实现,左式堆是针对二叉堆合并操作困难的缺点,而提出的另外一种优先队列实现方式. 线性结构合并困难是显而易见的,而二叉堆那样高效的支持合并操作而且只使用一个数组更是难得 ...

最新文章

  1. jquery-autoComplete 插件使用
  2. python工作-Python工作五年月薪23K,记录一下我的学习经历建议
  3. 能量分析攻击day02
  4. 电脑开机3秒就重启循环_移动办公神器!电脑包秒变支架、鼠标垫,3合1设计超方便!...
  5. SpringBoot中对thymeleaf的时间进行格式化显示
  6. 现代化Java代码的七个NetBeans提示
  7. LeetCode 967. 连续差相同的数字(BFS/DFS)
  8. 1、Docker部署及基础理论
  9. 706. 设计哈希映射
  10. Shell脚本学习-阶段十二-在CentOS 7上给一个网卡分配多个IP地址
  11. Tracepro中up vector和normal vector的定义1
  12. 【wps】wps怎样删除中间的一页?
  13. Beginning Lua with World of Warcraft Add-ons第三章翻译总结及一些工具
  14. Qt实现全局键盘事件监听器-Windows
  15. 此PL2303驱动程序不支持Windows11及后续版本,请安装正确驱动程序
  16. 麒麟座mini学习笔记之云端查看数据流
  17. 如何在 Linux 系统中配置 firewalld 防火墙策略
  18. 保姆级AS400 CL介绍与应用(硬核)
  19. JAVA根据经纬度计算两点距离
  20. NXP - LPC1769与LPC1768的区别

热门文章

  1. 【youcans 的 OpenCV 例程200篇】128. 形态算法之骨架 (skimage)
  2. cocos creator尝试使用tween的几种新实现方案
  3. 雷军:《我十年的程序员生涯》系列之二(我赚的第一桶金)
  4. ARM SIMD 指令集:NEON 简介
  5. com.jcraft.jsch.JSchException: Auth fail
  6. LeetCode刷题-11
  7. 【渗透技巧】资产探测与信息收集
  8. 升级android安全补丁,谷歌发布 2019 年 12 月的 Android 安全补丁
  9. #淘宝#复制分享宝贝内容,打开淘宝APP,自动弹出宝贝提示信息
  10. 网页素材大宝库:15套精美的用户头像图标素材