二分搜索树的基本实现

基本操作的动画演示

插入(略)

搜索(略)

删除节点

img

代码

package com.yunche.datastructure;import java.util.LinkedList;
import java.util.Queue;/*** @ClassName: BST* @Description: 二叉搜索树:每个节点的左子树的值都小于节点的值,每个节点的右子树的值都大于节点的值* 注:二叉搜索树不一定是完全二叉树* @author: yunche* @date: 2018/12/27*/
public class BST<K extends Comparable<K>, V> {/*** 内部私有节点类*/private class Node {private K key;private V value;private Node left;private Node right;public Node(K key, V value) {this.key = key;this.value = value;left = right = null;}}/*** 根节点*/private Node root;/*** 节点个数*/private int count;/*** 返回节点的个数** @return*/public int size() {return count;}/*** 返回二叉搜索树是否为空** @return*/public boolean isEmpty() {return count == 0;}/*** 构造函数默认构造一棵空的二叉搜索树*/public BST() {root = null;count = 0;}/*** 向二叉搜索树中插入一个新的(key, value)数据对** @param key* @param value*/public void insert(K key, V value) {root = insert(root, key, value);}/*** 判断二叉搜索树中是否包含该键** @param key* @return*/public boolean contain(K key) {return contain(root, key);}/*** 在二叉搜索树中,搜索该键对应的值,并返回,若盖建不存在,返回null** @param key* @return*/public V search(K key) {return search(root, key);}/*** 二叉搜索树的前序遍历*/public void preOrder() {preOrder(root);}/*** 二分搜索树的中序遍历*/public void inOrder() {inOrder(root);}/*** 二分搜索树的后序遍历*/public void postOrder() {postOrder(root);}/*** 二分搜索树的层序遍历*/public void levelOrder() {//使用LinkedList作为队列Queue<Node> queue = new LinkedList<Node>();if (root != null) {queue.add(root);}while (!queue.isEmpty()) {Node node = queue.remove();System.out.println(node.key);if (node.left != null) {queue.add(node.left);}if (node.right != null) {queue.add(node.right);}}}/*** 返回二分搜索树中最小的键值** @return*/public K min() {if (root != null) {return min(root).key;}return null;}/*** 返回二分搜索树中最大的键值** @return*/public K max() {if (root != null) {return max(root).key;}return null;}/*** 从二分搜索树中删除最小的键值*/public void removeMin() {if (root != null) {root = removeMin(root);}}/*** 从二分搜索树中删除最大的键值*/public void removeMax() {if (root != null) {root = removeMax(root);}}/*** 删除指定键的节点** @param key*/public void remove(K key) {root = remove(key, root);}/*** @param node  该插入的节点位置* @param key* @param value* @return 返回插入后的新节点*/private Node insert(Node node, K key, V value) {//递归边界if (node == null) {count++;return new Node(key, value);}if (node.key.compareTo(key) == 0) {node.value = value;} else if (key.compareTo(node.key) < 0) {node.left = insert(node.left, key, value);} else {node.right = insert(node.right, key, value);}return node;}/*** 递归contain算法,返回在以node为根节点的树中是否存在该键** @param node* @param key* @return*/private boolean contain(Node node, K key) {//递归边界if (node == null) {return false;}if (key.compareTo(node.key) == 0) {return true;} else if (key.compareTo(node.key) < 0) {return contain(node.left, key);} else {return contain(node.right, key);}}/*** 递归search算法** @param node 待搜索树的根节点* @param key  待搜索的键* @return*/private V search(Node node, K key) {//递归边界if (node == null) {return null;}if (key.compareTo(node.key) == 0) {return node.value;} else if (key.compareTo(node.key) < 0) {return search(node.left, key);} else {return search(node.right, key);}}/*** 将以node为根节点的树进行先序遍历,递归算法** @param node*/private void preOrder(Node node) {//递归边界if (node == null) {return;}System.out.println(node.key);preOrder(node.left);preOrder(node.right);}/*** 将以node为根节点的树进行中序遍历,递归算法** @param node*/private void inOrder(Node node) {//递归边界if (node == null) {return;}inOrder(node.left);System.out.println(node.key);inOrder(node.right);}/*** 将以node为根节点的树进行后序遍历,递归算法** @param node*/private void postOrder(Node node) {//递归边界if (node == null) {return;}postOrder(node.left);postOrder(node.right);System.out.println(node.key);}/*** 返回最小键值的节点,递归算法** @param node 待搜索树的根节点* @return*/private Node min(Node node) {//递归边界if (node.left == null) {return node;}return min(node.left);}/*** 返回最大键值的节点,递归算法** @param node 待搜索树的根节点* @return*/private Node max(Node node) {//递归边界if (node.right == null) {return node;}return max(node.right);}/*** 删除最小键值节点 递归算法** @param node 最小键值所在树的根节点* @return 返回删除节点后新的二分搜索树的根*/private Node removeMin(Node node) {//递归边界if (node.left == null) {Node childRight = node.right;node.right = null;count--;return childRight;}node.left = removeMin(node.left);return node;}/*** 删除最大键值节点 递归算法** @param node 最大键值所在树的根节点* @return 返回删除节点后新的二分搜索树的根*/private Node removeMax(Node node) {//递归边界if (node.right == null) {Node childLeft = node.left;node.left = null;count--;return childLeft;}node.right = removeMax(node.right);return node;}/*** 删除指定键值对应的节点,并返回删除后新的根节点. 递归算法** @param key  要删除的键值* @param node 删除键值的节点位于以该节点为根的树里* @return 删除后子树新的根节点.*/private Node remove(K key, Node node) {//递归边界if (node == null) {return null;}if (key.compareTo(node.key) == 0) {//将该节点右子树中的最小键值的节点放在现在节点的位置//并使该位置(删除节点的位置)上的新节点的左孩子指向原该位置上原来节点的左孩子//并使该位置(删除节点的位置)上的新节点的右孩子指向原该位置上原来节点的右孩子if (node.right == null) {Node leftNode = node.left;node = null;count--;return leftNode;}Node successor = min(node.right);successor.right = removeMin(node.right);successor.left = node.left;node = null;return successor;} else if (key.compareTo(node.key) < 0) {node.left = remove(key, node.left);} else {node.right = remove(key, node.right);}return node;}public static void main(String[] args) {BST<Integer, Integer> bst = new BST<Integer, Integer>();// 取n个取值范围在[0...m)的随机整数放进二分搜索树中int N = 10;int M = 100;for (int i = 0; i < N; i++) {Integer key = new Integer((int) (Math.random() * M));// 为了后续测试方便,这里value值取和key值一样bst.insert(key, key);System.out.print(key + " ");}System.out.println();// 测试二分搜索树的size()System.out.println("size: " + bst.size());System.out.println();//        //若要测试,取消该代码片段注释即可
//        //********测试遍历(前中后) 和层序遍历开始********//
//        // 测试二分搜索树的前序遍历 preOrder
//        System.out.println("preOrder: ");
//        bst.preOrder();
//        System.out.println();
//
//        // 测试二分搜索树的中序遍历 inOrder
//        System.out.println("inOrder: ");
//        bst.inOrder();
//        System.out.println();
//
//        // 测试二分搜索树的后序遍历 postOrder
//        System.out.println("postOrder: ");
//        bst.postOrder();
//        System.out.println();
//        //********测试插入、遍历(前中后)和层序遍历 结束**********//
//
//
//        // 测试二分搜索树的层序遍历 levelOrder
//        System.out.println("levelOrder: ");
//        bst.levelOrder();
//        System.out.println();
//********测试遍历(前中后) 和层序遍历结束*******////        //*****测试搜索最小、最大键值 开始**********
//        System.out.println("min: " + bst.min());
//        System.out.println("max: " + bst.max());
//        //*****测试搜索最小、最大键值  结束**********//        //******* 测试 removeMin 和 removeMax开始
//        // 输出的元素应该是从小到大排列的
//        System.out.println("Test removeMin: ");
//        while( !bst.isEmpty() ){
//            System.out.print("min: " + bst.min() + " , ");
//            bst.removeMin();
//            System.out.println("After removeMin, size = " + bst.size() );
//        }
//        System.out.println();
//
//
//        for(int i = 0 ; i < N ; i ++){
//            Integer key = new Integer((int)(Math.random()*M));
//            // 为了后续测试方便,这里value值取和key值一样
//            bst.insert(key, key);
//        }
//        // 注意, 由于随机生成的数据有重复, 所以bst中的数据数量大概率是小于n的
//
//        // 测试 removeMax
//        // 输出的元素应该是从大到小排列的
//        System.out.println("Test removeMax: ");
//        while( !bst.isEmpty() ){
//            System.out.print("max: " + bst.max() + " , ");
//            bst.removeMax();
//            System.out.println("After removeMax, size = " + bst.size() );
//        }
//        //******* 测试 removeMin 和 removeMax结束//        //******测试 remove 开始
//        BST<Integer, Integer> bstDelete = new BST<Integer, Integer>();
//        bstDelete.insert(2, 2);
//        bstDelete.insert(1, 1);
//        bstDelete.insert(3, 3);
//        bstDelete.insert(4, 4);
//        bstDelete.insert(0, 0);
//        bstDelete.remove(1);
//        System.out.println("levelOrder: ");
//        bstDelete.levelOrder();
//        System.out.println("inOrder: ");
//        bstDelete.inOrder();
//        System.out.println();
//        //***测试remove 结束}}

转载于:https://www.cnblogs.com/yunche/p/10196414.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

d9900 修改ip 思科dcm_思科设备SSH登陆详细配置过程

思科设备SSH登陆详细配置过程我们用GNS3进行拓扑搭建。实验拓扑图如下&#xff1a;进行完基本配置之后开始配置SSH服务器(R2)1.首先验证设备是否支持SSHR2#show ip ssh能够识别这条命令就说明支持。2.配置IP域名。使用config# ip domain-name domain-name全局配置模式命令配置网…

java 把string转为keyevent_盘点现在Java强大第三方库(字符串操作),程序员都该知道!...

1.字符串与集合间的转化引用第三方库 Apache Commons Lang jre连接值得一提的自JDK1.8以后字符串集合转为字符串可以使用String类下的join()方法,但别的数据类型还是要依靠第三方库--对比JDK和第三库代码如下我自己是一名从事了多年开发的java老程序员&#xff0c;这段时间整理…

Redis安装文档

1.前置条件 前置条件&#xff1a;linux已经可以上网&#xff0c;参考&#xff1a;https://www.cnblogs.com/ZenoLiang/p/10201875.html 2.安装redis 2.1依赖包检查 1. yum install cpp -y 2. yum install binutils -y 3. yum install glibc-kernheaders -y 4. yum install…

我用Mono(1)

我在Mono 0.1就开始关注和试用Mono了。我印象最深的一次是&#xff0c;我在FreeBSD里编译好了Mono&#xff08;FreeBSD装在VPC里&#xff09;。我用了同样的算法写了一个CS文件和JAVA文件。然后在虚拟机的FreeBSD的Mono下编译运行&#xff0c;把Java文件在真实机器的Windows XP…

Java基本数据类型的传值

传递值&#xff1a; 说明&#xff1a;标题其实说法是错误的。Java中只有值传递&#xff0c;没有引用传递。 ... ... //定义了一个改变参数值的函数 public static void changeValue(int x) { x x *2; } ... ... //调用该函数 int num 5; System.out.println(num); change…

红楼梦人物分析系统c语言,Gephi分析红楼梦

前言上一周赶了好久的社会网络计算&#xff0c;貌似是第四周还是第五周的时候&#xff0c;那时候我们就把题目定下来了吧&#xff0c;然后一直拖着没有做。其中的原因多种多样 &#xff0c;其实也可以说没有什么原因&#xff0c;就是不想做而已&#xff0c;然后就假装忘记23333…

二、MyBatis-HelloWorld

环境准备 1.创建数据库表 create table tbl_employee (id int(11) primary key AUTO_INCREMENT comment "ID",last_name varchar(20) default null comment "姓名",email varchar(20) default null comment "邮件",gender varchar(1) default nu…

洪水同频率放大的方法_我们应该怎么选择放大器配件?

在市面上&#xff0c;手机信号放大器高达百种型号与品牌&#xff0c;每种手机信号放大器所需的配件也不相同&#xff0c;我们需要选择合适的配件&#xff0c;才能让手机信号放大器更稳定的运行。下面佛山红岸谷通讯教大家怎么选适合自己的手机信号放大器配件。主要有以下几点。…

斑能不能彻底去掉_用茶树精油祛痘时,千万不能做这5件事!!!

祛痘注意事项~用茶树精油祛痘时&#xff0c;千万不能做这5件事&#xff01;&#xff01;&#xff01;长痘痘虽然是令人很头疼的事&#xff0c;但是茶树精油祛痘、去痘印功效可谓是无敌的&#xff01;茶树精油是自然界中的抗菌大师&#xff0c;能净化皮肤、平衡皮肤油脂分泌&…

JAX-RS 2.0:自定义内容处理

我试图想到一个更好的标题&#xff0c;但未能拿出一个&#xff01; 请多多包涵……。 JAX-RS 2.0规范允许我们无缝地将JAXB对象编组到HTTP请求/响应主体/从HTTP请求/响应主体中解组。 简而言之&#xff0c;我们可以使用域对象&#xff0c;而不必担心基于JAX-RS的解决方案中的低…

Waymo在美国推出自动驾驶汽车共享服务

导读经过数月的测试和数百万英里的无人驾驶汽车技术开发&#xff0c;Waymo 正式在美国推出了具有商业性质的自动驾驶汽车的共享服务。该公司的 Waymo One 项目将为客户提供 24 小时自动驾驶汽车服务。最初&#xff0c;这项服务将仅限于菲尼克斯周边城市&#xff0c;包括坦佩 (T…

2019春第一次课程设计实验报告

一、实验项目名称&#xff1a; 飞机游戏简化的编写 二、实验项目功能描述&#xff1a; 这个实验主要是实现游戏的正常运行&#xff0c;实现控制飞机的移动功能&#xff0c;增加其实用度&#xff0c; 同时还实现发射子弹和出现敌机的操作&#xff0c;利用函数封装重构飞机游戏&a…

区别和联系_动机与主题的区别与联系

今天我算是彻底弄明白了动机与主题的区别与联系&#xff08;暴论&#xff09;。当前些天我开始尝试写简单的奏鸣曲时&#xff0c;主题是什么&#xff0c;这个问题卡住了我&#xff0c;因为之前写的练习曲都是基于简单动机的。所以我求助于维基百科。主题是什么&#xff1f;参考…

巴顿又吃回头草

巴顿是一名好车手&#xff0c;一个会给shumi以及kimi造成威胁的家伙&#xff0c;我并不在意他在哪个车队&#xff0c;只希望他跑得比kimi慢才好。from新浪&#xff1a;宛如平地一声雷&#xff0c;巴顿重返威廉姆斯的消息不仅让车迷感到错愕&#xff0c;英美车队的老板理查兹更是…

尝试将WCF映射到Java术语

通过写这篇文章&#xff0c;我冒着被.NET和Java社区拒绝的巨大风险。 试图解释Java术语WCF &#xff08;代表Windows Communication Foundation&#xff09;是什么。 从WCF到Java的映射并不是很简单。 我缺乏对WFC使用者应该了解的与服务通信类型的了解&#xff1a;请求/响应或…

android fragment界面滑动切换效果,Android App中使用ViewPager+Fragment实现滑动切换效果...

在android应用中&#xff0c;多屏滑动是一种很常见的风格&#xff0c;没有采用viewpager的代码实现会很长&#xff0c;如果采用ViewPager&#xff0c;代码就会短很多&#xff0c;但是使用ViewPager也有弊端&#xff1a;需要导入android-support-v4.jar、细节无法控制。不过现在…

相对路径./与../区别

一、基本概念 1、相对路径-顾名思义&#xff0c;相对路径就是相对于当前文件的路径。网页中一般表示路径使用这个方法。 2、绝对路径-绝对路径就是你的主页上的文件或目录在硬盘上真正的路径。绝对路径就是你的主页上的文件或目录在硬盘上真正的路径&#xff0c;比如&#xff0…

shouji android输入法,安卓手机主流输入法对比

什么是合格的输入法&#xff1f;1. 按键布局合理2. 词库丰富且云识别准确3. 文字编辑4. 符号快捷输入5. 翻译功能6. 语音识别转文字对比五款主流输入法&#xff1a;触宝、百度、搜狗、讯飞、QQ均为默认皮肤和设置。1. 按键布局从哪进从哪出&#xff0c;这应该是一个输入法最基本…

DS博客作业06--图

1.本周学习总结 1.思维导图 2.谈谈你对图结构的认识及学习体会。 原本以为树已经够难的了&#xff0c;结果发现觉得太早了。图好难&#xff0c;看不懂。图是由两个集合V和E组成&#xff0c;V指的是顶点的有限集合&#xff0c;E代表两个不同顶点的边的有限集合&#xff0c;图也分…

c 给定字符串中查找_面试 | 查找类算法精析

点击上方蓝字设为星标每周一、三、五上午 8:30 准时推送下面开始今天的学习&#xff5e;前言查找&#xff0c;是使用计算机处理问题时的一个最基本的任务&#xff0c;因此也是算法面试中非常常见的一类问题。很多算法问题的本质&#xff0c;就是要能够高效使用查找。LeetCode 中…