排序二叉树(BST)

一.简介

任何一个节点的左子树上的点,都必须小于当前节点,任何一个节点的右子树上的点,都必须大于当前节点,等于当前节点的数据可以放在左节点或右节点。

二.实现

对于节点的删除有如下判断:
1.待删除节点是叶子节点则找到父节点直接删除

2.待删除结点只有左节点,则父节点直接指向待删除结点的左节点

3.待删除结点只有右节点,则父节点直接指向待删除结点的右节点

4.待删除结点有左右节点,则寻找待删除结点左子树最大值或待删除结点右子树最小值替换待删除结点值,并把寻找到的节点删除。

package com.vincent;


import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BinSortTree<Integer> tree = new BinSortTree<>();
        for(int i=0;i<32;i++){
            tree.add((int)(Math.random() * 100));
        }
        List<Integer> list = tree.infixList();
        System.out.println(list);
        System.out.println("删除:" + list.get(0));
        tree.delete(list.get(0));
        list = tree.infixList();
        System.out.println(list);

        System.out.println("删除:" + list.get(list.size()-1));
        tree.delete(list.get(list.size()-1));
        list = tree.infixList();
        System.out.println(list);

        System.out.println("删除:" + list.get(list.size()/2));
        tree.delete(list.get(list.size()/2));
        list = tree.infixList();
        System.out.println(list);
    }
}

//二叉排序树(BST)
class BinSortTree<T extends Comparable<T>>{
    static class Node<T extends Comparable<T>> {
        private T item;
        private Node<T> left;
        private Node<T> right;

        public Node(T item) {
            this.item = item;
        }

        public void add(Node<T> node){
            if(node.item.compareTo(this.item) <= 0){
                if(this.left == null){
                    this.left = node;
                }
                else{
                    this.left.add(node);
                }
            }
            else{
                if(this.right == null){
                    this.right = node;
                }
                else{
                    this.right.add(node);
                }
            }
        }

        /**
         * 从当前节点开始寻找等于item的节点
         * @param item      带查找结点的值
         * @return
         */
        public Node<T> searchParentNode(T item){
            if(this.left != null && this.left.item.compareTo(item)==0 || this.right!=null && this.right.item.compareTo(item)==0){
                return this;
            }
            Node<T> value = null;
            if(this.left != null){
                value = this.left.searchParentNode(item);
            }
            if(value != null){
                return value;
            }
            if(this.right != null){
                return this.right.searchParentNode(item);
            }
            return null;
        }


        /**
         * 获取当前节点子树最小节点
         * @return
         */
        public Node<T> minNode(){
            if(this.left != null){
                return this.left.minNode();
            }
            return this;
        }

        /**
         * 节点的中序遍历
         * @param dst   遍历节点的存放容器
         */
        public void infixList(List<T> dst){
            if(this.left != null){
                this.left.infixList(dst);
            }
            dst.add(this.item);
            if(this.right != null){
                this.right.infixList(dst);
            }
        }

        @Override
        public String toString() {
            return "Node{" +
                    "item=" + item +
                    '}';
        }
    }

    private Node<T> root;

    public void add(T item){
        Node<T> node = new Node<>(item);
        if(this.root == null){
            this.root = node;
        }
        else{
            this.root.add(node);
        }
    }

    public boolean delete(T item){
        if(root.item.compareTo(item)==0){//删除根节点
            if(root.left==null && root.right==null){
                this.root = null;
                return true;
            }
            else if(root.left==null){
                this.root = root.right;
                return true;
            }
            else if(root.right==null){
                this.root = root.left;
                return true;
            }
            else if(root.left!=null && root.right!=null){
                //寻找右子树最小节点
                Node<T> parent = this.root;
                Node<T> node = this.root.right;
                while(node.left!=null){
                    parent = node;
                    node = node.left;
                }

                parent.left = null;
                this.root.item = node.item;
                return true;
            }
        }
        //待删除结点的父节点
        Node<T> parent = this.root.searchParentNode(item);
        if(parent == null){
            return false;
        }
        //待删除结点
        Node<T> node = parent.left;
        if(parent.right != null && item.compareTo(parent.right.item)==0){
            node = parent.right;
        }
        if(node.left==null && node.right==null){
            if(parent.left==node){
                parent.left = null;
            }
            else{
                parent.right = null;
            }
        }
        else if(node.left==null){
            if(parent.left==node){
                parent.left = node.right;
            }
            else{
                parent.right = node.right;
            }
        }
        else if(node.right==null){
            if(parent.left==node){
                parent.left = node.left;
            }
            else{
                parent.right = node.left;
            }
        }
        else{
            //寻找待删除结点左节点最大节点
            Node<T> maxParent = null;
            Node<T> maxNode = node.left;
            while(maxNode.right != null){
                maxParent = maxNode;
                maxNode = maxNode.right;
            }
            if(maxParent==null){
                node.left = null;
            }
            else{
                maxParent.right = null;
            }

            node.item = maxNode.item;
        }
        return true;
    }

    public List<T> infixList(){
        List<T> rst = new ArrayList<>();
        this.root.infixList(rst);
        return rst;
    }
}

效果:

在这里插入图片描述

三.总结

1.对排序二叉树中序遍历可得到一个有序数列

2.子节点没有指向父节点的指针,对于删除操作将寻找节点的父节点,相对繁琐,可以为每个节点增加一个指向父节点的指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值