二叉查找树(理论及实现)

  1. 二叉查找树的定义
    二叉查找树是按二叉树结构来组织的,即可按照二叉树的数据结构来构造。即每个节点都包含域left,right和key。
    设x是二叉查找树的一个节点。如果y是x的左子树的一个结点,则key[y]<=key[x]。如果y是x的右子树的一个节点,则key[y]>=key[x]。如:
    这里写图片描述
  2. 二叉查找树的遍历
    中序遍历结果是有序,结果为3,4,5,6,7
  3. 二叉查找树的查询
    1、按key值查询——-二叉查找,在O(h)时间内完成。
    2、查找最小节点——-沿左节点向下查找,最小节点为3
    3、查找最大节点——-沿右节点向下查找,最大节点为7
    4、查找某节点x的后继—-如果该节点x右子树非空,则后继是右子树的最左节点。如果右子树为空,且该节点存在后继,则后继是x的最低祖先节点O(h)。4的后继是5
    5、查找某节点的前继—-和后继对称O(h)。6的前驱是5。

  4. 二叉查找树的插入与删除
    1、插入—-简单操作
    2、删除—-删除给定节点Z有3种情况。1)、Z没有子女,则直接删除。2)、Z只有一个子女,则通过其子节点与父节点之间建立一条连接来删除Z。3)、Z有2个子女,则先删除Z的后继y(y没有左子树),再用y的内容来替代Z的内容。

  5. 随机构造二叉查找树(只说一下思路,不加证明)
    1.插入—-1/N的概率作为根节点,(N-1)/N的概率递归到子节点,重复上述步骤。
    2.删除—-由于删除普通做法是:利用被删节点的后继(右子树最小节点)为根,这对左子树不公平。优化方案:以概率的方式来决定谁来做根,一般是大子树做根的概率大,从而拉低大子树的高度,达到平衡。
//二叉查找树
public class BinarySearchTree<T extends Comparable<T>> {
    //TreeNode<T> root;
    static class TreeNode<T extends Comparable<T>>
    {
        T val;
        TreeNode parent;
        TreeNode left;
        TreeNode right;
        public TreeNode(T val) {
            // TODO Auto-generated constructor stub
            this.val = val;
        }
        public TreeNode() {
            // TODO Auto-generated constructor stub
        }

    }
    public BinarySearchTree() {
        // TODO Auto-generated constructor stub
    }
    public void insert(T val, TreeNode<T> x)
    {
        if(x.val == null){x.val = val;return;}
        TreeNode<T> node = new TreeNode<T>(val);
        TreeNode<T> y = x;
        TreeNode<T> temp = null;
        while(y != null)
        {
            temp = y;
            if(val.compareTo(y.val)>0)
            {
                y = y.right;
            }else
                y = y.left;

        }
        if(val.compareTo(temp.val) >0)
        {
            temp.right = node;
        }else
        {
            temp.left = node;
        }
        node.parent = temp;

    }
    public TreeNode<T> remove(TreeNode<T> z, TreeNode<T> root)
    {
        //three situation
        TreeNode<T> y = null;
        TreeNode<T> x = null;
        //找到y
        if(z.left == null || z.right == null)
        {
            y = z;
        }else
            y = treeSuccessor(z);//最多只有一个子节点
        //对y删除,连接。。。。。。
        //找到y的非空子节点
        if(y.left != null)
            x = y.left;
        else
            x = y.right;
        //
        if(x != null)
        {
            x.parent = y.parent;
        }
        //
        if(y.parent == null)//即y是根节点
        {
            root = x;
        }else
            if(y.parent.left == y)
                y.parent.left = x;
            else
                y.parent.right = x;
        //如果是左右都不为空情况
        if(y != z)
        {
            z.val = y.val;
        }
        return root;    

    }
    public void treeWalk(TreeNode<T> x){
        if(x == null){return;}
        treeWalk(x.left);
        System.out.println(x.val+" ");
        treeWalk(x.right);
    }
    public T treeSearch(T val, TreeNode<T> x)
    {
        if(x == null) return null;
        if(val.compareTo(x.val)==0) {return val;}
        if(val.compareTo(x.val)>0) 
            return treeSearch(val, x.right);
        else
            return treeSearch(val, x.left);
    }
    public TreeNode<T> treeMinmum(TreeNode<T> x)
    {
        if(x == null) return null;
        if(x.left == null) return x;
        return treeMaxmum(x.left);
    }
    public TreeNode<T> treeMaxmum(TreeNode<T> x)
    {
        if(x == null) return null;
        if(x.right == null) return x;
        return treeMaxmum(x.right);
    }
    public TreeNode<T> treeSuccessor(TreeNode<T> x)//crucial
    {
        if(x == null ) return null;
        if(x.right != null) 
            return treeMinmum(x.right);
        else
        {
            TreeNode<T> y = x.parent;
            while(y!=null && y.right == x)
            {
                x = y;
                y = x.parent;
            }
            return y;
        }

    }
    public TreeNode<T> treePredecessor(TreeNode<T> x)//important
    {
        if(x == null) return null;
        if(x.left != null) return treeMaxmum(x.left);
        else
        {
            TreeNode<T> y = x.parent;
            while(y!=null && y.left == x)
            {
                x = y;
                y = x.parent;
            }
            return y;
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        BinarySearchTree<Integer> bst = new BinarySearchTree<>();
        TreeNode<Integer> root = new TreeNode<>();
        bst.insert(2, root);
        bst.insert(3, root);
        bst.insert(1, root);
        bst.insert(5, root);
        bst.insert(4, root);
        bst.treeWalk(root);
        System.out.println("maxMum:"+bst.treeMaxmum(root).val);
        System.out.println("minMun:"+bst.treeMinmum(root).val);;
        System.out.println("root:"+root.val);
        System.out.println("root successor:"+bst.treeSuccessor(root).val);
        System.out.println("root predecessor:"+bst.treePredecessor(root).val);

        root = bst.remove(root, root);
        System.out.println("remove root:");
        bst.treeWalk(root);
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值