Java实现的二叉搜索树,并实现对该树的搜索,插入,删除操作(合并删除,复制删除)

首先我们要有一个编码的思路,大致如下:

1、查找:根据二叉搜索树的数据特点,我们可以根据节点的值得比较来实现查找,查找值大于当前节点时向右走,反之向左走!

2、插入:我们应该知道,插入的全部都是叶子节点,所以我们就需要找到要进行插入的叶子节点的位置,插入的思路与查找的思路一致。

3、删除:

1)合并删除:一般来说会遇到以下几种情况,被删节点有左子树没右子树,此时要让当前节点的父节点指向当前节点的左子树;当被删节点有右子树没有左子树,此时要让当前节点的父节点指向该右子树;当被删节点即有左子树又有右子树时,我们可以找到被删节点的左子树的最右端的节点,然后让这个节点的右或者左“指针”指向被删节点的右子树

2)复制删除:复制删除相对而言是比较简单的删除操作,也是最为常用的删除操作。大致也有以下三种情况:当前节点无左子树有右子树时,让当前右子树的根节点替换被删节点;当前节点无右子树有左子树时,让当前左子树的根节点替换被删除节点;当前被删节点既有左子树又有右子树时,我们就要找到被删节点的替身,可以在被删节点的左子树中找到其最右端的节点,并让这个节点的值赋给被删节点,然后别忘了让此替身节点的父节点指向替身的“指针”为空,(其实在Java中无关紧要了,有垃圾处理机制自动进行处理)。你也可以在当前被删节点的右子树的最左端的节点作为替身节点来实现这一过程。


接下来就上代码吧。

首先是## 二叉搜索树节点类 ##

package SearchBinaryTree;

public class SearchBinaryTreeNode<T> {
    T data;
    public SearchBinaryTreeNode<T> leftChild;
    public SearchBinaryTreeNode<T> rightChild;

    public SearchBinaryTreeNode(){
        this.data=null;
        this.leftChild=this.rightChild=null;
    }

    public SearchBinaryTreeNode(T da){
        this.data=da;
        this.leftChild=this.rightChild=null;
    }

    public SearchBinaryTreeNode(T da,SearchBinaryTreeNode<T> left,SearchBinaryTreeNode<T>right){
        this.data=da;
        this.leftChild=left;
        this.rightChild=right;
    }

    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public SearchBinaryTreeNode<T> getLeftChild() {
        return leftChild;
    }
    public void setLeftChild(SearchBinaryTreeNode<T> leftChild) {
        this.leftChild = leftChild;
    }
    public SearchBinaryTreeNode<T> getRightChild() {
        return rightChild;
    }
    public void setRightChild(SearchBinaryTreeNode<T> rightChild) {
        this.rightChild = rightChild;
    }

    public boolean isLeaf(){
        if(this.leftChild==null&&this.rightChild==null){
            return true;
        }
        return false;
    }

}

实现二叉搜索树

package SearchBinaryTree;

public class SearchBinaryTree<T> {
    SearchBinaryTreeNode<T> root;

    public boolean isEmpty(){
        if(root==null){
            return true;
        }
        return false;
    }

    public void Visit(SearchBinaryTreeNode<T> root){
        if(root==null){
            System.out.println("this tree is empty!");
        }
        System.out.println(root.getData());
    }

    public SearchBinaryTreeNode<T> getRoot(){
        if(root==null){
            root=new SearchBinaryTreeNode<T>();
        }
        return root;
    }

    public SearchBinaryTree(){
        this.root=null;
    }

    /*
     * 创造一颗二叉树
     */
    public void CreateTree(SearchBinaryTreeNode<T> node, T data) {
        if (root == null) {
            root = new SearchBinaryTreeNode<T>();
        } else {
            if (Math.random() > 0.5) {                   //采用随机方式创建二叉树
                if (node.leftChild == null) {
                    node.leftChild = new SearchBinaryTreeNode<T>(data);
                } else {
                    CreateTree(node.leftChild, data);
                }
            } else {
                if (node.rightChild == null) {
                    node.rightChild = new SearchBinaryTreeNode<T>(data);
                } else {
                    CreateTree(node.rightChild, data);
                }
            }
        }
    }

    /*
     * 在二查搜索树中进行搜索
     */
    public SearchBinaryTreeNode<T> search(SearchBinaryTreeNode<T> root,T value){
        SearchBinaryTreeNode<T> current=root;
        while((root!=null)&&(current.getData()!=value)){
            //需要注意的是java中泛型无法比较大小,在实际的使用时我们可以使用常见的数据类型来替代这个泛型,这样就不会出错了
            current=(value<current.getData()?search(current.leftChild,value):search(current.rightChild,value));
        }
        return current;
    }

    public SearchBinaryTreeNode<T> insertNode( T value){
        SearchBinaryTreeNode<T> p=root,pre=null;
        while(p!=null){
            pre=p;
            //需要注意的是java中泛型无法比较大小,在实际的使用时我们可以使用常见的数据类型来替代这个泛型,这样就不会出错了
            if(p.getData()<value){
                p=p.rightChild;
            }else{
                p=p.leftChild;
            }
        }
        if(root==null){
            root=new SearchBinaryTreeNode<T>(value);
        }else if(pre.getData()<value){
            pre.rightChild=new SearchBinaryTreeNode<T>(value);
        }else{
            pre.leftChild=new SearchBinaryTreeNode<T>(value);
        }
    }

    /*
     * 合并删除
     */
    public void deleteByMerging(SearchBinaryTreeNode<T> node){
        SearchBinaryTreeNode<T> temp=node;
        if(node!=null){
            //若被删除节点没有右子树,用其左子树的根节点来代替被删除节点
            if(node.rightChild!=null){
                node=node.leftChild;
            }else if(node.leftChild==null){
                //若被删节点没有左子树,用其有字数的最左端的节点代替被删除的节点
                node=node.rightChild;
            }else{
                //如果被删节点左右子树均存在
                temp=node.leftChild;
                while(temp.rightChild!=null){
                    temp=temp.rightChild;     //一直查找到左子树的右节点
                }

                //将查找到的节点的右指针赋值为被删除节点的右子树的根
                temp.rightChild=node.rightChild;
                temp=node;
                node=node.leftChild;
            }
            temp=null;
        }
    }

    /*
     * 复制删除
     */
    public void deleteByCoping(SearchBinaryTreeNode<T> node){
        SearchBinaryTreeNode<T> pre=null;
        SearchBinaryTreeNode<T> temp=node;
        //如果被删节点没有右子树,用其左子树的根节点来代替被删除节点
        if(node.rightChild==null){
            node=node.leftChild;
        }else if(node.leftChild==null){
            node=node.rightChild;
        }else{
            //如果被删节点的左右子树都存在
            temp=node.leftChild;
            pre=node;
            while(temp.rightChild!=null){
                pre=temp;
                temp=temp.rightChild;      //遍历查找到左子树的最右端的节点
            }
            node.data=temp.data;           //进行赋值操作
            if(pre==node){
                pre.leftChild=node.leftChild;
            }else{
                pre.rightChild=node.rightChild;
            }
        }
        temp=null;
    }

}

测试类

package SearchBinaryTree;

public class SearchBinaryTreeTest {

    public static void main(String []args){
        SearchBinaryTree<Integer> tree=new SearchBinaryTree<Integer>();
        for(int i=1;i<10;i++){
            tree.CreateTree(new SearchBinaryTreeNode<Integer>(), i);
        }

        //搜索
        tree.search(tree.root, 7);

        //合并删除
        tree.deleteByMerging(new SearchBinaryTreeNode<Integer>(8));

        //复制删除
        tree.deleteByCoping(new SearchBinaryTreeNode<Integer>(6));
    }

}

好了,就是这样!

Java创建二叉搜索树,实现搜索,插入,删除操作的更多相关文章

  1. 二叉搜索树-php实现 插入删除查找等操作

    二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的 ...

  2. Java实现二叉搜索树

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11406176.html 尝试一下用Java实现二叉搜索树/二叉查找树,记录自己的学习历程. 1 ...

  3. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历   二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...

  4. Java实现二叉搜索树的插入、删除

    前置知识 二叉树的结构 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode( ...

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

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

  6. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它的根 ...

  7. Java实现二叉搜索树及相关操作

    package com.tree; import com.tree.BitNode; /** * * 二叉搜索树:一个节点的左子节点的关键字小于这个节点.右子节点的关键字大于或等于这个父节点 * * ...

  8. Java数据结构——二叉搜索树

    定义二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若 ...

  9. Java对二叉搜索树进行插入、查找、遍历、最大值和最小值的操作

    1.首先,须要一个节点对象的类.这些对象包括数据.数据代表存储的内容,并且还有指向节点的两个子节点的引用 class Node { public int iData; public double dD ...

随机推荐

  1. Async分析

     1:android在新版本中不允许UI线程访问网络,但是如果需要访问网络又改怎么办呐?这里有很多解决方案,比如新开一个线程,在新线程中进行访问,然后访问数据,返回后可能会更新界面也可能不更新界面,这 ...

  2. Splay伸展树入门(单点操作,区间维护)附例题模板

    Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...

  3. ACM 数塔

    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?  已经告诉你了,这是个DP的题 ...

  4. PHP date() 函数

    实例 格式化本地日期和时间,并返回格式化的日期字符串: <?php // Prints the dayecho date("l") . "<br>&qu ...

  5. Django URL (路由系统)

    URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那 ...

  6. SpringMVC之Ajax与Controller交互

    前面学习了拦截器,通过拦截器我们可以拦截请求,做进一步处理之后再往下进行,这里我们使用Ajax的时候会有一个问题就是会把js.css这些静态资源文件也进行了拦截,这样在jsp中就无法引入的静态资源文件 ...

  7. Gradle 1.12用户指南翻译——第四十七章. Build Init 插件

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  8. git 覆盖本地变化

    git fetch && git reset --hard origin/master

  9. MyEclipse中查看struts_spring_hibernate源码

    1.spring查看源码 首先下载对应的源码包 如:spring-framework-2.5.6-with-dependencies.zip   打开spring-framework-2.5.6\di ...

  10. Ubuntu和ROS一起愉快玩耍

    Ubuntu和ROS重要的两个中文网址: Ubuntu:http://cn.ubuntu.com/ROS:http://wiki.ros.org/cn Robots and drones on Ubu ...