二叉查找树(BST)

0.

二叉查找树是按照二叉树的结构来组织的,二叉查找树满足这样的性质:
设x为二叉查找树中的一个结点,left(x)是它的左孩子,right(x)是它的右孩子,那么left(x)<=x<=right(x).
二叉查找树是一种较为简单的数据结构。

1.二叉查找树的操作及其Java实现

注意:Java没有指针,很多修改都是通过返回值带出来的
①插入
INSERT:插入指定元素

public Node treeInsert(int value,Node root) {   //传值传递,没指针,只能用返回值带出来了
        if(root!=null) {
            if(value <= root.value) {
                root.left = treeInsert(value,root.left);
            }
            else {
                root.right = treeInsert(value,root.right);
            }
        }
        else {
            return new Node(value);
        }
        return root;
    }

注:初始化一棵BST就是不断向它插入结点的过程
②遍历
TRAVERSE:遍历整棵树(本文以中序遍历为例)
//中序遍历BST能得到一个有序的序列

public void middleTraverse(Node root) {
        if(root.left!=null) {
            middleTraverse(root.left);
        }
        System.out.print(root.value + " ");
        if(root.right!=null) {
            middleTraverse(root.right);
        }   
    }

③查找
SEARCH:查找给定的元素

public Node search(int x,Node root) { //根据BST的性质,小的往左,大的往右
        if(root == null) return null;
        if(root.value == x) {
            return root;
        }
        else if(x<root.value) {
            search(x,root.left); 
        }
        else {
            search(x,root.right);
        }
        return null;
    }

MINIMUM:查找树中最小的元素
//由BST的性质可知,最小的元素在BST最左下角

    public Node minimum(Node root) {
        if(root == null)
            return null;
        if(root.left == null)
            return root;
        else {
            return minimum(root.left);
        }
    }

MAXIMUM:查找树中最大的元素
//由BST的性质可知,最大的元素在BST最右下角

    public Node maximum(Node root) {
        if(root == null)
            return null;
        if(root.right == null)
            return root;
        else {
            return maximum(root.right);
        }
    }

PREDECESSOR:查找给定元素的父结点
//在前序遍历的基础上做一些改动即可

public Node predecessor(Node root,int value) {
        if(root == null)
            return null;
        if(root.left!=null) {
            if(value == root.left.value) return root;
            if(value < root.left.value) {
                return predecessor(root.left,value);
            }
            return predecessor(root.right,value);
        }
        if(root.right!=null) {
            if(value == root.right.value) return root;
            if(value < root.right.value) {
                return predecessor(root.left,value);
            }
            return predecessor(root.right,value);
        }
        return null;
    }

SUCCESSOR:查找给定元素的后继
//在前序遍历的基础上做一些改动即可
//分为找左孩子还是右孩子,这里写一个找左孩子的

    public Node leftSuccessor(Node root,int value) {
        if(root.value == value)
            return root.left;
        if(value <= root.left.value) {
            return leftSuccessor(root.left,value);
        }
        return leftSuccessor(root.right,value);
    }

④删除
按删除结点的特点,删除的情况分为三种:
(1)删除的结点为叶子结点
若该结点为叶子结点,修改其父结点的引用,将指向该结点的引用置为空
(2)删除的结点只有左孩子或者右孩子
若该结点只有一个孩子,修改其父结点的引用,降指向该结点的引用指向该节点的孩子
(3)删除的结点既有左孩子也有右孩子
有两种方法可以解决该问题:
方法一:为了维持BST性质,我们可以在该结点的左子树里找到最大值所在的结点(或在右子树里找最小值所在的结点),和该结点交换数据后删除。这是一个递归的过程,最后删除结点的为叶子结点或者只有一个孩子的结点。
方法二:将指向该结点的前驱指向该结点的左孩子,再将该结点的右子树一整棵插入该结点的左子树
删除图例1
删除图例2
方法一代码:

public void treeDelete(Node temp,int value) {
        Node pred = predecessor(temp,value);
        if(pred != null) { //不是根结点
            Node node = search(value,temp);  //value所在结点
            if(node.left == null) {
                if(pred.left == node) {
                    pred.left = node.right;
                }
                else {
                    pred.right = node.right;
                }
            }
            else if(node.left!=null && node.right ==null) {
                if(pred.left == node) {
                    pred.left = node.left;
                }
                else {
                    pred.right = node.left;
                }
            }
            else {
                Node mini = minimum(node.right);
                mini.value = node.value;
                treeDelete(node.right,node.value);
            }
        }

方法二代码:

public void delete(Node node,int value) {
        //根结点无前驱,拉出来特殊处理
        if(predecessor(node,value) == null) {
            if(root.right==null) {
                root = root.left;
            }
            else {
                treeInsert(root.right.value,root.left);  //在左子树中插入整颗右子树
                Node temp = search(root.right.value,root.left);
                temp.left = root.right.left;
                temp.right = root.right.right;
                root = root.left;    //把原来的root丢进垃圾箱
            }
        }
        else {
            Node pred = predecessor(node,value);
            treeInsert(node.right.value,node.left);
            if(node.right == null) {
                pred.left = node.left;
            }
            else {
                treeInsert(node.right.value, node.left);
                Node temp = search(root.right.value,root.left);
                temp.left = node.right.left;
                temp.right = node.right.right;
            }
            if(pred.left == node) {  //要删除的结点是其前驱的左孩子
                pred.left = node.left;
            }
            else {
                pred.right = node.right;
            }
        }
    }

//如有错误,欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值