二叉查找树的实现

1. 原理

  二叉查找树,又称为二叉排序树、二叉搜索树。对于树中每一个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。二叉查找树的平均深度为O(log N),搜索元素的时间复杂度也是O(log N)。是两种库集合类TreeSet、TreeMap实现的基础。

2. public API

void makeEmpty( )      --> 置空
boolean isEmpty( )     --> 判空
AnyType findMin( )     --> 寻找最小值
AnyType findMax( )     --> 寻找最大值
boolean contains( x ) --> 是否存在元素x
void insert( x )       --> 插入元素x
void remove( x )       --> 删除元素x
void printTree( )     --> 遍历二叉树

3. 核心思想图解:递归

!寻找最小值

此处用递归实现:

!寻找最大值

此处用非递归实现,也可以用递归实现:

!是否存在元素x

从root开始往下找,找到含有项X的节点,则此操作返回true,没有找到则返回false。

!插入元素x

从root开始往下找到合适的插入位置,然后插入。

!删除元素x

从root开始往下找到元素x,找到则删除,并且处理好后续工作。

4. BinarySearchTree代码实现

类中,大量使用方法来调用递归方法的技巧,很好地体现了面向对象的封装性。
 /**
* @author: wenhx
* @date: Created in 2019/10/8 19:41 (之前)
* @description: 二叉查找树的实现
*/
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {

/**
* 树的根节点
*/
private BinaryNode<AnyType> root;

/**
* 定义树的节点(内部类)
*/
private static class BinaryNode<AnyType> {

AnyType element; // 元素值
BinaryNode<AnyType> left; // 左孩子
BinaryNode<AnyType> right; // 右孩子

// 节点的构造器:初始化一个树的节点
BinaryNode(AnyType theElement) {
this(theElement, null, null);
}

BinaryNode(AnyType theElement, BinaryNode<AnyType> lt, BinaryNode<AnyType> rt) {
element = theElement;
left = lt;
right = rt;
}
}

/**
* 二叉排序树的构造器:初始化根节点
*/
public BinarySearchTree() {
root = null;
}

/**
* 置空
*/
public void makeEmpty() {
root = null;
}

/**
* 判空
*/
public boolean isEmpty() {
return root == null;
}

/**
* 寻找最小值
*/
public AnyType findMin() {
if (isEmpty()) {
throw new RuntimeException();
}
return findMin(root).element;
}

/**
* 寻找最大值
*/
public AnyType findMax() {
if (isEmpty()) {
throw new RuntimeException();
}
return findMax(root).element;
}


/**
* 是否存在元素x
*/
public boolean contains(AnyType x) {
return contains(x, root);
}

/**
* 插入元素x
*/
public void insert(AnyType x) {
root = insert(x, root);
}

/**
* 删除元素x
*/
public void remove(AnyType x) {
root = remove(x, root);
}

/**
* 遍历此二叉树
*/
public void printTree() {
if (isEmpty()) {
System.out.println("Empty tree");
} else {
printTree(root);
}
}

/**
* 寻找最小值(内部方法):此处用递归实现
*/
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) {
if (t == null) {
return null;
} else if (t.left == null) {
return t;
}
return findMin(t.left);
}

/**
* 寻找最大值(内部方法):此处用非递归实现
*/
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t) {
if (t != null) {
while (t.right != null) {
t = t.right;
}
}
return t;
}

/**
* 是否存在元素x(内部方法)
*/
private boolean contains(AnyType x, BinaryNode<AnyType> t) {
/**
* 跳出递归的条件
*/
if (t == null) {
return false;
}

/**
* 如果x小于节点值,则递归到左孩子;
* 如果x大于节点值,则递归到右孩子;
* 如果x等于节点值,则找到。
*/
int compareResult = x.compareTo(t.element);

if (compareResult < 0) {
return contains(x, t.left);
} else if (compareResult > 0) {
return contains(x, t.right);
} else {
return true;
}

}

/**
* 插入元素x(内部方法)
*/
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t) {
/**
* 跳出递归的条件
*/
if (t == null) {
return new BinaryNode<>(x, null, null);
}

/**
* 如果x小于节点值,则递归到左孩子;
* 如果x大于节点值,则递归到右孩子;
* 如果x等于节点值,则说明已有元素x,无需操作。
*/
int compareResult = x.compareTo(t.element);

if (compareResult < 0) {
t.left = insert(x, t.left);
} else if (compareResult > 0) {
t.right = insert(x, t.right);
} else {
}
return t;

}

/**
* 删除元素x(内部方法)
*/
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t) {
/**
* 跳出递归的条件
*/
if (t == null) {
return t; // Item not found; do nothing
}

/**
* 如果x小于节点值,则递归到左孩子;
* 如果x大于节点值,则递归到右孩子;
* 如果x等于节点值,则要删除此节点。
*/
int compareResult = x.compareTo(t.element);

if (compareResult < 0) {
t.left = remove(x, t.left);
} else if (compareResult > 0) {
t.right = remove(x, t.right);
} else if (t.left != null && t.right != null) {
// 要删除的节点有两个孩子(可选用右孩子最小元素/左孩子最大元素上调)
t.element = findMin(t.right).element;
t.right = remove(t.element, t.right);
} else {
// 要删除的节点有一个孩子或者没有孩子
t = (t.left != null) ? t.left : t.right;
}
return t;
}

/**
* 遍历此二叉树(内部方法)
*/
private void printTree(BinaryNode<AnyType> t) {
// 中序遍历-->即递增顺序
if (t != null) {
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
}

/**
* 求树的深度(内部方法)
*/
private int height(BinaryNode<AnyType> t) {
if (t == null) {
return -1;
} else {
return 1 + Math.max(height(t.left), height(t.right));
}
}

/**
* 主方法用来测试
*/
public static void main(String[] args) {
BinarySearchTree<Integer> t = new BinarySearchTree<>();
t.insert(6);
t.insert(3);
t.insert(9);
t.insert(2);
t.insert(5);
t.insert(8);
t.insert(10);
t.printTree();
t.insert(4);
}
}

okay,今天就到这啦,一定要掌握这种数据结构哈,真的很重要!!!

用Java实现二叉查找树的更多相关文章

  1. 数据结构:JAVA实现二叉查找树

    数据结构:JAVA实现二叉查找树 写在前面 二叉查找树(搜索树)是一种能将链表插入的灵活性与有序数组查找的高效性结合在一起的一种数据结构. 观察二叉查找树,我们发现任何一个节点大于左子节点且小于其右子 ...

  2. Java实现二叉查找树

    摘要:一个二叉查找树的Java实现.可以学习二叉树处理的递归及非递归技巧. 难度:初级. 为了克服对树结构编程的恐惧感,决心自己实现一遍二叉查找树,以便掌握关于树结构编程的一些技巧和方法.以下是基本思 ...

  3. JAVA数据结构--二叉查找树

    二叉查找树定义 二叉查找树(英语:Binary Search Tree),也称二叉搜索树.有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tr ...

  4. 使用java实现二叉查找树的插入,修改和删除方法

    目前使用的是根据key的hashcode来进行排序,并且没有考虑hash碰撞的问题 package com.zhou.tree; import java.util.Comparator; import ...

  5. 二叉查找树(三)之 Java的实现

    概要 在前面分别介绍了"二叉查找树的相关理论知识,然后给出了二叉查找树的C和C++实现版本".这一章写一写二叉查找树的Java实现版本. 目录 1. 二叉树查找树2. 二叉查找树的 ...

  6. 红黑树(五)之 Java的实现

    概要 前面分别介绍红黑树的理论知识.红黑树的C语言和C++的实现.本章介绍红黑树的Java实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章.还是那句老话,红黑树的C/C+ ...

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

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

  8. Java数据结构和算法(二)树的基本操作

    Java数据结构和算法(二)树的基本操作 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 一.树的遍历 二叉树遍历分为:前序遍 ...

  9. 红黑树 Java实现

    概要 前面分别介绍红黑树的理论知识.红黑树的C语言和C++的实现.本章介绍红黑树的Java实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章.还是那句老话,红黑树的C/C+ ...

随机推荐

  1. nginx 反向代理之 proxy_pass

    格式很简单: proxy_pass URL; 其中URL包含:传输协议(http://, https://等).主机名(域名或者IP:PORT).uri. 示例如下: proxy_pass http: ...

  2. kaldi使用thchs30数据进行训练并执行识别操作

    操作系统 : Ubutu18.04_x64 gcc版本 :7.4.0 数据准备及训练 数据地址: http://www.openslr.org/18/ 在 egs/thchs30/s5 建立 thch ...

  3. 5面终于拿到了字节跳动offer! 鬼知道我经历了啥...

    坐标北京,某211本科毕业生,之前学校活动有去过字节跳动公司总部参观,所以一直以来就蛮想进入字节工作的,被字节的企业文化和工作氛围所影响.字节作为发展速度最快的互联网公司,旗下的很多产品的用户都比肩B ...

  4. 【Java基础】Java中你必须知道的知识点

    目录 Java中面向对象的基础知识 1. 什么是面向对象  2. 三大基本特征和五项基本原则 3. Java的平台无关性 4. 值传递和引用传递 5. 方法重载和重写 6. 基本数据类型 7. 包装类 ...

  5. 构建和管理有效API市场的关键步骤

    API市场关键要点 各个行业的公司正在寻找通过外部API扩展服务来塑造数字业务的方法.然而,要获得API的真正好处,是需要超越基本的API管理,再到创建API市场,这是一种专注于连接生产者和消费者的专 ...

  6. zookeeper的java问题

    执行bash ./bin/zkServer.sh statusZooKeeper JMX enabled by defaultUsing config: /data/zookeeper-3.4.9/b ...

  7. 更改组织属性-以更改maxrecordsforexporttoexcel为例

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复232或者20161101可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  8. 别不信!servlet获取到的参数值,也许完全出乎你的意料!

    先贴出来简单得不能再简单的demo页面效果: 如下是spring mvc的Controller: @RequestMapping("mytest") @Controller pub ...

  9. 高通平台:USB充电【转】

    USB Battery Charging V1.2 Specification 定义了USB充电器的类型或者叫做充电源. 1. 支持的充电器类型 1.1 Standard Downstream Por ...

  10. idea安装以及使用

    1. 简介1.1 IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构. J2EE ...