Algorithms-3.2 Binary Search Trees 二叉查找树

本文介绍了二叉查找树(BSTs),包括其最坏情况下的效率问题,以及有序操作如查找最大键、最小键、向上取整、向下取整和排名的方法。在删除操作中,探讨了删除最小键和Hibbard删除策略,以及它们对树结构的影响。
摘要由CSDN通过智能技术生成

1 BSTs 二叉查找树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • no more tree (search miss)
    在这里插入图片描述
    在这里插入图片描述
package Chapter03;

//基于二叉查找树的符号表
public class BST<Key extends Comparable<Key>, Value>{

    private Node root; //二叉查找树的根结点

    //内部类
    private class Node{
        private Key key;
        private Value val;
        private Node left, right; //指向子树的链接

        //构造器
        public Node(Key key, Value val){
            this.key = key;
            this.val = val;
        }
    }

    public void put(Key key, Value val){
        //查找key,找到则更新它的值,否则为它创造一个新的结点
        root = put(root, key, val);//root根结点
    }
    //cost: number of compare is equal to 1 + depth of node
    private Node put(Node x, Key key, Value val){
        //如果key存在于以x为根结点的子树中则更新它的值,否则将以key和val为键值对的新结点插入到该子树中
        if (x == null)    return new Node(key,val);
        int cmp = key.compareTo(x.key);
        if      (cmp < 0) x.left = put(x.left,key,val);//递归
        else if (cmp > 0) x.right = put(x.right,key,val);
        else              x.val = val;
        return x;//最终回到一个node
    }

    //return value corresponding to given key, or null if no such key
    //cost: number of compare is equal to 1 + depth of node
    public Value get(Key key){
        Node x = root;
        while (x != null){
            int cmp = key.compareTo(x.key); //key和key比较
            if      (cmp < 0)   x = x.left;
            else if (cmp > 0)   x = x.right;
            else                return x.val;
        }
        return null;
    }
}

在这里插入图片描述

  • worst case和链表一样,按字母从小到大的顺序输入的
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2 ordered operations in BSTs 有序性相关方法

2.1 最大键和最小键

在这里插入图片描述

  • 从root开始一直往右,直到找到一个null的右链接,就找到了最大键;同理,一直向左,可找到最小键
	public Key min(){
        return min(root).key;
    }
    private Node min(Node x){
        if (x.left == null) return x;
        return min(x.left);
    }
  • max()将left和right调换

2.2 向上取整和向下取整

在这里插入图片描述
在这里插入图片描述

	//寻找小于等于key的最大的Key
    public Key floor(Key key){
        Node x = floor(root, key);
        if (x == null) return null;
        return x.key;
    }

    private Node floor(Node x, Key key){
        if (x == null) return null;
        int cmp = key.compareTo(x.key);

        if (cmp == 0)  return x;

        if (cmp < 0)   return floor(x.left,key);

        //cmp > 0
        Node t = floor(x.right,key);
        if (t != null) return t;//在x.right子树中找到一个node
        else           return x;//如果是空,回到上一级Key,上一级Key即为最终结果,说明右边子树不符合小于等于key的条件
    }
  • 把所有的左变右(同时将小于变成大于)就能得到ceiling()的算法

2.3 排名

在这里插入图片描述

2.3.1 size()

在这里插入图片描述

package Chapter03;

//基于二叉查找树的符号表
public class BST<Key extends Comparable<Key>, Value>{

    private Node root; //二叉查找树的根结点

    //内部类
    private class Node{
        private Key key;
        private Value val;
        private Node left, right; //指向子树的链接
        private int count;//number of nodes in subtrees

        //构造器
        public Node(Key key, Value val, int count){
            this.key = key;
            this.val = val;
            this.count = count;
        }
    }

    public void put(Key key, Value val){
        //查找key,找到则更新它的值,否则为它创造一个新的结点
        root = put(root, key, val);//root根结点
    }
    //cost: number of compare is equal to 1 + depth of node
    private Node put(Node x, Key key, Value val){
        //如果key存在于以x为根结点的子树中则更新它的值,否则将以key和val为键值对的新结点插入到该子树中
        if (x == null)    return new Node(key,val,1);
        int cmp = key.compareTo(x.key);
        if      (cmp < 0) x.left = put(x.left,key,val);//递归
        else if (cmp > 0) x.right = put(x.right,key,val);
        else              x.val = val;
        x.count = 1 + size(x.left) + size(x.right);//递归
        return x;//最终回到一个node
    }

    public int size(){
        return size(root);
    }
    private int size(Node x){
        if (x == null) return 0;
        return x.count;
    }
}

2.3.2 rank()

  • how many keys < k ?
	public int rank(Key key){
        return rank(key, root);
    }
    private int rank(Key key, Node x){
        //返回以x为根结点的子树中小于x.key的键的数量
        if      (x == null) return 0;
        int cmp = key.compareTo(x.key);
        if      (cmp < 0)   return rank(key, x.left);//若key小于根结点,返回key在左子树的排名(递归)
        else if (cmp > 0)   return 1 + size(x.left) + rank(key, x.right);
        else                return size(x.left);//如果key和根结点的key相等,rank就是左边子树的结点总数
    }

2.3.3 中序遍历

在这里插入图片描述
遍历过程如下:

  1. 访问左子树,
  2. 访问根节点,
  3. 访问右子树。
  • 队列(queue)是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
	//中序遍历:迭代
    public Iterable<Key> keys(){
        Queue<Key> q = new Queue<Key>();
        inorder(root, q);
        return q;
    }
    private void inorder(Node x, Queue<Key> q){
        if (x == null) return;
        inorder(x.left, q);//递归
        q.enqueue(x.key);//把根结点加入队列
        inorder(x.right, q);
    }

2.3.4 summary

在这里插入图片描述

3 deletion 删除操作

在这里插入图片描述

  • tombstone 墓碑
  • 如果有大量的删除操作,内存过载

3.1 删除最小键

在这里插入图片描述

	//删除最小键
    public void deleteMin(){
        root = delete(root);
    }
    private Node deleteMin(Node x){
        if (x.left == null) return x.right;
        x.left = deleteMin(x.left);//x.left被重新赋值,新的left是原来的left的right
        x.count = size(x.left) + size(x.right) + 1;
        return x;
    }

3.2 Hibbard deletion

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//删除键值对
    public void delete(Key key){
        root = delete(root, key);
    }
    private Node delete(Node x, Key key){
        if (x == null) return null;
        int cmp = key.compareTo(x.key);
        if      (cmp < 0)   x.left = delete(x.left, key);//递归
        else if (cmp > 0)   x.right = delete(x.right, key);
        else{//已找到要删除的键
            if (x.right == null) return x.left;//no right child
            if (x.left == null) return x.right;//no left child
            //replace with successor,有两个子树的情况
            Node t = x;//x为即将被删除的结点
            x = min(t.right);//x更新为x的右子树的最小结点,作为新"根"结点
            x.right = deleteMin(t.right);//将x的右链接
            x.left = t.left;//把t的左子树安装到后继结点(新x)的左边
        }
        x.count = size(x.left) + size(x.right) + 1;//update subtree counts
        return x;
    }

在这里插入图片描述

  • 删除会使得二叉树变得不对称
  • after a sequence of insert and delete, 树的高度变为square root of N --> 根号N,比期待的logN大很多

3.3 summary

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值