一、二叉查找树定义

二叉树每个节点都不能有多于两个的儿子。二叉查找树是特殊的二叉树,对于树中的每个节点X,它的左子树中的所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。

二叉查找树节点的定义:

  1. private static class BinaryNode<T> {
  2. T element; // 节点的值
  3. BinaryNode<T> left; // 左子节点
  4. BinaryNode<T> right; // 右子节点
  5. public BinaryNode(T element) {
  6. this(element, null, null);
  7. }
  8. public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
  9. this.element = element;
  10. this.left = left;
  11. this.right = right;
  12. }
  13. }

二、树的遍历

树的三种遍历方式:前序遍历、中序遍历、后序遍历。这里的前中后是相对于根节点而言的:

  • 前序遍历:根节点->左子树->右子树
  • 中序遍历:左子树->根节点->右子树
  • 后序遍历:左子树->右子树->根节点

对于下面这样一棵树,不同的遍历方式结果如下:

前序遍历:ABDGHCEIF

  1. private void preOrder(BinaryNode<T> root) {
  2. if (root == null) {
  3. return;
  4. }
  5. System.out.printf("%d ", root.element);
  6. preOrder(root.left);
  7. preOrder(root.right);
  8. }

中序遍历:GDHBAEICF

  1. private void inOrder(BinaryNode<T> root) {
  2. if (root == null) {
  3. return;
  4. }
  5. inOrder(root.left);
  6. System.out.printf("%d ", root.element);
  7. inOrder(root.right);
  8. }

后序遍历:GHDBIEFCA

  1. private void postOrder(BinaryNode<T> root) {
  2. if (root == null) {
  3. return;
  4. }
  5. postOrder(root.left);
  6. postOrder(root.right);
  7. System.out.printf("%d ", root.element);
  8. }

三、二叉查找树的基本操作

3.1 contains方法

  1. /**
  2. * 判断树t中是否存在含有项x的节点
  3. *
  4. * @param x 值
  5. * @param t 以t为根节点的一棵树
  6. * @return
  7. */
  8. private boolean contains(T x, BinaryNode<T> t) {
  9. if (t == null) {
  10. return false;
  11. }
  12. int compareResult = x.compareTo(t.element);
  13. if (compareResult < 0) {
  14. return contains(x, t.left);
  15. } else if (compareResult > 0) {
  16. return contains(x, t.right);
  17. } else {
  18. return true;
  19. }
  20. }
  21. public boolean contains(T x) {
  22. return contains(x, root);
  23. }

3.2 find方法

  1. /**
  2. * 查找树t中值为x的节点
  3. * @param x
  4. * @param t
  5. * @return
  6. */
  7. private BinaryNode<T> find(T x, BinaryNode<T> t) {
  8. if (t == null) {
  9. return t;
  10. }
  11. int compareResult = x.compareTo(t.element);
  12. if (compareResult < 0) {
  13. return find(x, t.left);
  14. } else if (compareResult > 0) {
  15. return find(x, t.right);
  16. } else {
  17. return t;
  18. }
  19. }
  20. public BinaryNode<T> find(T x) {
  21. return find(x, root);
  22. }

3.3 最大值与最小值

查找树中最大值的节点

  1. private BinaryNode<T> findMax(BinaryNode<T> t) {
  2. if (t == null) {
  3. return null;
  4. }
  5. while (t.right != null) {
  6. t = t.right;
  7. }
  8. return t;
  9. }
  10. public BinaryNode<T> findMax() {
  11. return findMax(root);
  12. }

查找树中最小值的节点

  1. private BinaryNode<T> findMin(BinaryNode<T> t) {
  2. if (t == null) {
  3. return null;
  4. }
  5. while (t.left != null) {
  6. t = t.left;
  7. }
  8. return t;
  9. }
  10. public BinaryNode<T> findMin() {
  11. return findMin(root);
  12. }

3.4 insert方法

  1. private BinaryNode<T> insert(T x, BinaryNode<T> t) {
  2. if (t == null) {
  3. return new BinaryNode<>(x, null, null);
  4. }
  5. int compareResult = x.compareTo(t.element);
  6. if (compareResult < 0) {
  7. t.left = insert(x, t.left);
  8. } else if (compareResult > 0) {
  9. t.right = insert(x, t.right);
  10. } else {
  11. // 出现重复值,忽略不处理
  12. }
  13. return t;
  14. }
  15. public void insert(T x) {
  16. root = insert(x, root);
  17. }

3.5 remove方法

  • 如果需要删除的节点是叶节点,那么可以直接删除;
  • 如果节点有一个儿子,则让儿子节点取代该节点即可;
  • 如果节点有两个儿子,通常用其右子树的最小的数据代替该节点的数据并递归地删除那个节点。

    因为右子树的最小节点不可能有左儿子
  1. public void remove(T x) {
  2. root = remove(x, root);
  3. }
  4. private BinaryNode<T> remove(T x, BinaryNode<T> t) {
  5. if (t == null) {
  6. return t;
  7. }
  8. int compareResult = x.compareTo(t.element);
  9. if (compareResult < 0) {
  10. t.left = remove(x, t.left);
  11. } else if (compareResult > 0) {
  12. t.right = remove(x, t.right);
  13. } else if (t.left != null && t.right != null) {
  14. // 用右子树的最小的数据代替该节点的数据并递归地删除这个节点
  15. t.element = findMin(t.right).element;
  16. t.right = remove(t.element, t.right);
  17. } else {
  18. // 只有一个儿子,直接用儿子代替该节点
  19. t = (t.left != null) ? t.left : t.right;
  20. }
  21. return t;
  22. }

Java数据结构与算法(4):二叉查找树的更多相关文章

  1. Java数据结构和算法(七)B+ 树

    Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...

  2. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

  3. java数据结构和算法06(红黑树)

    这一篇我们来看看红黑树,首先说一下我啃红黑树的一点想法,刚开始的时候比较蒙,what?这到底是什么鬼啊?还有这种操作?有好久的时间我都缓不过来,直到我玩了两把王者之后回头一看,好像有点儿意思,所以有的 ...

  4. Java数据结构和算法

    首先,本人自学java,但是只学习了java的基础知识,所以想接下来学习一下数据结构和算法,但是找了很多教材,大部分写的好的都是用c语言实现的,虽然知道数据结构和算法,跟什么语言实现的没有关系,但是我 ...

  5. 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现

      本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型   栈是 ...

  6. Java数据结构和算法(六)——前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

  7. Java数据结构和算法(十四)——堆

    在Java数据结构和算法(五)——队列中我们介绍了优先级队列,优先级队列是一种抽象数据类型(ADT),它提供了删除最大(或最小)关键字值的数据项的方法,插入数据项的方法,优先级队列可以用有序数组来实现 ...

  8. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

  9. java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...

随机推荐

  1. 把对像生成json并存储到文件

    1.创建实体对像json import com.alibaba.fastjson.annotation.JSONField; import java.util.Date; public class S ...

  2. 指定pom文件jdk版本

    <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> ...

  3. ajax的contentType和dataType

    1.contentType,明确告诉服务器我的请求的编码类型是json(严格来说是application/json),不设置的话,有默认值application/x-www-form-urlencod ...

  4. 【7.24校内交流赛】T1&T2

    T1: 一个脑洞很大的题,将输入的所有数异或起来输出就好了: (话说我为什么这么喜欢用异或啊) #include<bits/stdc++.h> using namespace std; i ...

  5. 【模板】最长上升子序列(LIS)及其优化 & 洛谷 AT2827 LIS

    最长上升子序列 传送门 题意 对于给定的一个n个数的序列,找到它的一个最长的子序列,并且保证这个子序列是由低到高排序的. 例如,1 6 2 5 4 6 8的最长上升子序列为1 2 4 6 8. 基本思 ...

  6. [LeetCode] 108. 将有序数组转换为二叉搜索树

    题目链接 : https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/ 题目描述: 将一个按照升序排列的 ...

  7. windows 下mysql5.7设置密码

    学习Springboot时用到mysql数据库,以前用的mysql5.6版本 基本百度一个教程即可,听说5.7有新改动,突然想试试于是找到解压版mysql5.7照常安装, 以前用的mysql5.6版本 ...

  8. spring cloud zuul过滤器修改requestURI 忽略大小写

    通过zuul网关处理requestURI可以做很多事情,如对uri的解密,转发,大小写转化等. 这里对URI做一个简单的大小写的转化. 写一个filter实现ZuulFilter: package c ...

  9. django2.0变动数据库设置外键报错

    1.报错TypeError: __init__() missing 1 required positional argument: 'on_delete' django2.0以后创建数据库外键的时候必 ...

  10. 使用NPOI读取Excel数据并写入SQLite

    首先,我们来建一个数据库,我们就叫Hello.db(不一定是db后缀,你可以sqlite,sqlite3,db3)都可以作为识别,然后往里面建一个空的表格,如下图所示 然后建一个Excel表格,往表格 ...