二叉搜索树基本操作

求树中的结点个数
判断节点是否为空
向树中插入新结点key-value
树中是否存在key
返回树中key对应的value值
先序遍历
中序遍历
后续遍历
层序遍历
求树中key最小的结点
求树中key最大的结点
删除树中key最小的结点
删除树中key最大的结点
树中删除一个结点

  代码:

/**
* @param <Key> 键的泛型
* @param <Value> 值的泛型
*/
public class BinarySearchTree<Key extends Comparable<? super Key>, Value> {
private class Node {
private Key key; // 键,相当于词典里的单词
private Value value; // 值,相当于词典里的解释
private Node left; // 左孩子结点
private Node right;// 右孩子结点 //结点的构造函数
public Node(Key key, Value value) {
this.key = key;
this.value = value;
this.left = null;
this.right = null;
} // getters and setters
public Key getKey() {
return key;
} public void setKey(Key key) {
this.key = key;
} public Value getValue() {
return value;
} public void setValue(Value value) {
this.value = value;
} public Node getLeft() {
return left;
} public void setLeft(Node left) {
this.left = left;
} public Node getRight() {
return right;
} public void setRight(Node right) {
this.right = right;
} @Override
public String toString() {
return "Node{" +
"key=" + key +
", value=" + value +
'}';
}
} private Node root; // 二叉搜索树的根节点
private int size; //二叉搜索树中的结点个数 //树的构造函数
public BinarySearchTree() {
this.root = null;
this.size = 0;
} //求树中的结点个数
public int size() {
return this.size;
} //判断节点是否为空
public boolean isEmpty() {
return this.size == 0;
} //以node结点为根的树(子树)中插入key-value
private Node insert(Node node, Key key, Value value) {
if (node == null) {
size++;
return new Node(key, value);
} else if (node.key.compareTo(key) > 0) {
node.setLeft(insert(node.getLeft(), key, value));
} else if (node.key.compareTo(key) < 0) {
node.setRight(insert(node.getRight(), key, value));
} else { // 相等的时候
node.value = value;
}
return node;
} //向树中插入新结点key-value
public void insert(Key key, Value value) {
root = insert(root, key, value);
} // node结点为根的树(子树)中是否存在key
private boolean contain(Node node, Key key) {
if (node == null) {
return false;
} else if (node.key.compareTo(key) == 0) {
return true;
} else if (node.key.compareTo(key) > 0) {
return contain(node.getLeft(), key);
} else {
return contain(node.getRight(), key);
}
} //树中是否存在key
public boolean contain(Key key) {
return contain(root, key);
} //返回node结点为根的树(子树)中key对应的value值
private Value search(Node node, Key key) {
if (node == null) {
return null;
} else if (node.getKey().compareTo(key) == 0) {
return node.getValue();
} else if (node.getKey().compareTo(key) > 0) {
return search(node.getLeft(), key);
} else {
return search(node.getRight(), key);
}
}
//返回树中key对应的value值
public Value search(Key key) {
return search(root, key);
} //先序遍历
private void preOrder(Node node) {
if (node == null) return;
System.out.println(node.key);
preOrder(node.getLeft());
preOrder(node.getRight());
} //先序遍历
public void preOrder() {
preOrder(root);
} //中序遍历
private void inOrder(Node node) {
if (node == null) return;
inOrder(node.getLeft());
System.out.println(node.getKey());
inOrder(node.getRight());
} //中序遍历
public void inOrder() {
inOrder(root);
} //后续遍历
private void postOrder(Node node) {
if (node == null) return;
postOrder(node.getLeft());
postOrder(node.getRight());
System.out.println(node.getKey());
} //后续遍历
public void postOrder() {
postOrder(root);
} //层序遍历
public void levelOrder() {
if (root == null) return;
java.util.LinkedList<Node> queue = new java.util.LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
Node node = queue.pop();
System.out.println(node);
if (node.getLeft() != null) {
queue.add(node.getLeft());
}
if (node.getRight() != null) {
queue.add(node.getRight());
}
}
} //以node为根的树中,key最小的结点
private Node minNode(Node node) {
if (node.getLeft() == null) return node; return minNode(node.getLeft());
} //树中key最小的结点
public Node minNode() {
return minNode(root);
} //以node为根的树中,key最大的结点
private Node maxNode(Node node) {
if (node.getRight() == null) return node; return maxNode(node.getRight());
} //树中key最大的结点
public Node maxNode() {
return maxNode(root);
} //删除node为根的树(子树)中key最小的结点
private Node removeMin(Node node) {
if (node == null) return null;
if (node.getLeft() == null) {
Node rightNode = node.getRight();
node.setRight(null);
size--;
return rightNode;
}
node.setLeft(removeMin(node.getLeft()));
return node;
} //删除树中key最小的结点
public void removeMin() {
root = removeMin(root);
} //删除node为根的树(子树)中key最大的结点
private Node removeMax(Node node) {
if (node == null) return null;
if (node.getRight() == null) {
Node leftNode = node.getLeft();
node.setLeft(null);
size--;
return leftNode;
}
node.setRight(removeMax(node.getRight()));
return node;
} //删除树中key最大的结点
public void removeMax() {
root = removeMax(root);
} //删除一个结点
private Node remove(Node node, Key key) {
if (node == null) return null;
if (key.compareTo(node.key) < 0) {//如果比根小,去左子树删除,然后返回根
node.setLeft(remove(node.getLeft(), key));
return node;
} else if (key.compareTo(node.key) > 0) {//如果比根大,去右子树删除,然后返回根
node.setRight(remove(node.getRight(), key));
return node;
} else { //key == node.key //如果与当点子树的根key相等
if (node.getLeft() == null) { //判断当前子树的根是否有左子树
Node rightNode = node.getRight();
node.setRight(null);
size--;
return rightNode;
} else if (node.getRight() == null) {//判断当前子树的根是否有右子树
Node leftNode = node.getLeft();
node.setLeft(null);
size--;
return leftNode;
} else { // 如果当前子树既有左子树,又有右子树
Node successor = minNode(node.getRight());//寻找后继结点,也就是右子树中最小的结点
successor = new Node(successor.getKey(), successor.getValue());//新建一个与后继结点一模一样的,为了替换
size++;//相当于添加一个结点
successor.setRight(removeMin(node.getRight()));//删除后继结点,然后连上原来的右边
successor.setLeft(node.getLeft());//连上原来的左边
node.left = node.right = null;//原来的结点已经被替换了,可以不要了。
size--;//相当于删除一个节点
return successor;//当前新的子树根就是successor
}
}
} public void remove(Key key) {
root = remove(root, key);
} public static void main(String[] args) {
//建立一颗二叉搜索树
BinarySearchTree<String, String> bst = new BinarySearchTree<>(); //插入数据
bst.insert("dog", "狗,一种动物");
bst.insert("password", "密码");
bst.insert("cat", "猫,一种动物");
bst.insert("cup", "杯子");
bst.insert("tom", "汤姆,《猫和老鼠》中的猫");
bst.insert("jerry", "杰瑞,《猫和老鼠》中的老鼠");
bst.insert("a", "26个英文字母中的第一个"); //search()
System.out.println(bst.search("a"));//26个英文字母中的第一个
System.out.println(bst.search("dog"));//狗,一种动物
System.out.println(bst.search("ttttt"));//null //contain()
System.out.println(bst.contain("cup"));//true
System.out.println(bst.contain("tom"));//true
System.out.println(bst.contain("tttttt"));//false //maxNode()
System.out.println(bst.maxNode());//Node{key=tom, value=汤姆,《猫和老鼠》中的猫} //minNode()
System.out.println(bst.minNode());//Node{key=a, value=26个英文字母中的第一个} //removeMax()
bst.removeMax();
System.out.println(bst.maxNode());//Node{key=password, value=密码} //removeMin()
bst.removeMin();
System.out.println(bst.minNode());//Node{key=cat, value=猫,一种动物} //size()
System.out.println(bst.size());//5 //levelOrder()
bst.levelOrder(); //remove();
System.out.println("--------------");
bst.remove("password");
bst.preOrder();
}
}

  

二叉搜索树(Java实现)的更多相关文章

  1. 二叉搜索树Java实现(查找、插入、删除、遍历)

    由于最近想要阅读下 JDK1.8 中 HashMap 的具体实现,但是由于 HashMap 的实现中用到了红黑树,所以我觉得有必要先复习下红黑树的相关知识,所以写下这篇随笔备忘,有不对的地方请指出- ...

  2. leetcode- 将有序数组转换为二叉搜索树(java)

    将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10,-3,0, ...

  3. 数据结构-二叉搜索树Java实现

    1,Node.java 生成基础二叉树的结构 package com.cnblogs.mufasa.searchTree; /** * 节点配置父+左+右 */ public class Node{ ...

  4. 有序链表转换二叉搜索树(LeetCode)

    将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10,-3,0, ...

  5. 【算法与数据结构】二叉搜索树的Java实现

    为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指 ...

  6. Java实现二叉搜索树的添加,前序、后序、中序及层序遍历,求树的节点数,求树的最大值、最小值,查找等操作

    什么也不说了,直接上代码. 首先是节点类,大家都懂得 /** * 二叉树的节点类 * * @author HeYufan * * @param <T> */ class Node<T ...

  7. Java与算法之(13) - 二叉搜索树

    查找是指在一批记录中找出满足指定条件的某一记录的过程,例如在数组{ 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 }中查找数字15,实现代码很简单 ...

  8. Java创建二叉搜索树,实现搜索,插入,删除操作

    Java实现的二叉搜索树,并实现对该树的搜索,插入,删除操作(合并删除,复制删除) 首先我们要有一个编码的思路,大致如下: 1.查找:根据二叉搜索树的数据特点,我们可以根据节点的值得比较来实现查找,查 ...

  9. 自己动手实现java数据结构(六)二叉搜索树

    1.二叉搜索树介绍 前面我们已经介绍过了向量和链表.有序向量可以以二分查找的方式高效的查找特定元素,而缺点是插入删除的效率较低(需要整体移动内部元素):链表的优点在于插入,删除元素时效率较高,但由于不 ...

随机推荐

  1. docker mysql 主从复制

    当然首先 docker pull mysql mkdir /usr/local/mysqlData/master/cnf mkdir /usr/local/mysqlData/master/data ...

  2. PV和UV的简单记录

    1.什么是PV值 PV(page view)即页面浏览量或点击量,是衡量一个网站或网页用户访问量.具体的说,PV值就是所有访问者在24小时(0点到24点)内看了某个网站多少个页面或某个网页多少次.PV ...

  3. duilib界面库学习(仿PC微信界面,有服务器,有数据库,可以网络通信)

    客户端代码:https://github.com/TTGuoying/duilib_ChatClient 服务器代码:https://github.com/TTGuoying/duilib_ChatS ...

  4. 使用TensorFlow的卷积神经网络识别自己的单个手写数字,填坑总结

    折腾了几天,爬了大大小小若干的坑,特记录如下.代码在最后面. 环境: Python3.6.4 + TensorFlow 1.5.1 + Win7 64位 + I5 3570 CPU 方法: 先用MNI ...

  5. JavaScript预编译原理分析

    一直对变量对象,活动对象,预编译,变量提升,执行上下文的时间顺序有着凌乱的认识,但是这些对理解JS语法有着很重要的作用.读了很多人的文章,都没有一个特别清晰的把这些写出来. 今天主要总结一下现阶段自己 ...

  6. iOS.Animations.by.Tutorials.v2.0汉化(二)

    翻译自:iOS.Animations.by.Tutorials.v2.0 第一节(第1章) 动画属性 现在你已经看到了动画是多么的简单,你可能很想知道你的视图控件是怎么动起来的.本节将给你一个UIVi ...

  7. linux dns子域授权 split分离解析 缓存dns服务器

    DNS子域授权作用:适用于同一个DNS组织父/子域名的解析工作由不同的dns服务器负责父dns服务器应该有为子域名迭代的能力 上下级区域属于不同的机构管理:.cn与.Anonymous.cn.cn需要 ...

  8. python语言中的AOP利器:装饰器

    一.前言 面向切面编程(AOP)是一种编程思想,与OOP并不矛盾,只是它们的关注点相同.面向对象的目的在于抽象和管理,而面向切面的目的在于解耦和复用. 举两个大家都接触过的AOP的例子: 1)java ...

  9. R语言︱基本函数、统计量、常用操作函数

    先言:R语言常用界面操作 帮助:help(nnet) = ?nnet =??nnet 清除命令框中所有显示内容:Ctrl+L 清除R空间中内存变量:rm(list=ls()).gc() 获取或者设置当 ...

  10. R语言︱缺失值处理

    #缺失值 an=c(1,2,NA) is.na(an) #会形成一个布尔向量 布尔向量就是一群像(FALSE,FALSE,TURE)这样的向量. 关于缺失值还有一个函数:complete.cases函 ...