Binary Search Tree

Binary search tree

structure

  • exactly one node per key.
  • most basic operation:
    • each node has :
      • left child pointer
      • right child pointer
      • parent pointer
  • for an arbitrary node x of tree, all keys in its left subtree should x .
  • all keys in its right subtree should x .

Height of a BST

for a set of keys, there many possible trees.
the height could a tree with n nodes could be anywhere from ~ logn2 to ~ n .

Search and inserting

To search for a key k in tree T

    start at the root
    set current_node = root
    while current_node != null and current_node.key != k
        if k < current_node.key
            current_node = current_node.left_child
        if k > current_node.key
            current_node = current_node.right_child
    if current_node == null
        return null
    else return current_node.key

To insert a new key k into a tree T .


Min, Max, Pred, And Succ

To compute the minimum (maximum) key of a tree.

  • start at root
  • follow left_child pointers(right ptrs, for maximum) until you can’t any more(return last key found)

To compute predecessor of key k
- easy case: If k’s left subtree nonempty, return max key in left subtree.
- otherwise : follow parent pointers until you get to a key less than k .

Succ is similar to Pred.

Traverse of BST

In order traversal

To print out keys in increasing order

    let r = root of search tree, with subtree TL and TR
    recurse on TL
    print out r's key
    recurse on TR

Running time: O(n)

Deletion

To delete a key k from a search tree .

search for k
happy case(k’s node has no children):
      just delete k’s node from tree, done.
median case(k’s node ha one child):
      unique child assumes position previously held by k’s node.
difficult case(k’s node has two children):
      compute k’s predecessor l.[i.e. , traverse k’s left child pointer, then right child pointers until no longer possible].
      swap k and l.
In this new position, k has no right child! Then we turn to the happy case or median case.

Analysis about BST

  • How efficient are the order-based operations in BSTs?
    There is a preposition to answer this question.

    Preposition. In a BST, all operations take time propotional to the height of the tree, in the worst case.
    Preposition. Search hits in a BST built from N random keys require ~ 2 ln N
    (about 1.39 lg N) compares, on the average.
    Preposition. Insertions and search misses in a BST built from N random keys
    require ~ 2 ln N (about 1.39 lg N) compares, on the average.


       The average height of a BST built from random keys was shown to be logarithmetic by J.Robson in 1979, and L.Devroye later showed that the value approaches 2.99lgN for large N <script type="math/tex" id="MathJax-Element-24">N</script>
  • In summary, BSTs are not difficult to implement and can provide fast search and insertion for practical applications of all kinds if the key insertions are well-approximated by the random-key model. Good performance of the basic BST implementation is dependent on the keys being sufficiently similar to random keys that the tree is not likely to contain many long paths.With quicksort, we were able to randomize; with a symbol-table API, we do not have that freedom, because the client controls the mix of operations. Indeed, the worst-case behavior is not unlikely in practice—it arises when a client inserts keys
    in order or in reverse order.

Inplementation

Here is a BST inplementation using Java. Mainly from the book “Algorithm 4th ed”[Sedgewick, Wayne].

/**
* <p>Title: BST.java</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2015</p>
* <p>Company: CSY</p>
* @author chenshiyang
* @date Aug 6, 2015
* @version jdk8.0
*/
package partone.week5;

import java.util.Queue;

/**
 * <p>Title: BST</p>
 * <p>Description: </p>
 * @author chenshiyang
 * @date Aug 6, 2015
 * @time 9:36:13 AM
 */
public class BST<Key extends Comparable<Key>, Value> {
    private Node root;
    private class Node{
        private Key key;
        private Value value;
        private Node left, right;
        private int N;

        public Node(Key key, Value value, int N){
            this.key = key;
            this.value = value;
            this.N = N;
        }
    }

    /**
    * <p>Description: return the size of this tree</p>
    * @return
    */
    public int size(){
        return size(root);
    }

    /**
    * <p>Description: return the size of subtree rooted at node x.</p>
    * @param x
    * @return
    */
    private int size(Node x){
        if(x == null) return 0;
        else return x.N;
    }

    /**
    * <p>Description: return the value of node in this tree given node key.
    *   </p>if the tree is null, return null.</p>
    * @param key
    * @return
    */
    public Value get(Key key){
        return get(root, key);
    }

    /**
    * <p>Description: Return value associated with key in the subtree rooted at x;
    *   </p>
    * return null if key not present in subtree  rooted at x.
    * @param x
    * @param key
    * @return
    */
    private Value get(Node x, Key key){
        //Return value associated with key in the subtree rooted at x;
        //return null if key not present in subtree  rooted at x.
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0) return get(x.left, key);
        else if(cmp > 0) return get(x.right, key);
        else return x.value;            
    }

    /**
    * <p>Description: Search for key. Update value if found; grow table if new.</p>
    * @param key
    * @param value
    */
    public void put(Key key, Value value){
        //Search for key. Update value if found; grow table if new.
        root = put(root, key, value);
    }

    /**
    * <p>Description: Change key's value to value if key in subtree rooted at x.</p>
    * Otherwise, add new node to subtree associating key with value.
    * @param x
    * @param key
    * @param value
    * @return the new root
    */
    private Node put(Node x, Key key, Value value){
        //Change key's value to value if key in subtree rooted at x.
        //otherwise, add new node to subtree associating key with value.
        if(x == null) return new Node(key, value, 1);
        int cmp = key.compareTo(x.key);
        if(cmp < 0) x.left = put(x.left, key, value);
        else if (cmp > 0) x.right = put(x.right, key, value);
        else x.value = value;
        x.N = x.left.N + x.right.N + 1;
        return x;
    }

    /**
    * <p>Description: Return the minimum key in this tree</p>
    * @return
    */
    public Key min(){
        return min(root).key;
    }

    /**
    * <p>Description: Return the node with the minimum key in the subtree rooted at node x.</p>
    * @param x
    * @return
    */
    private Node min(Node x){
        if(x.left == null) return x;
        return min(x.left);
    }

    /**
    * <p>Description: Return the maximum key in this tree</p>
    * @return
    */
    public Key max(){
        return max(root).key;
    }

    /**
    * <p>Description: Return the node with the maximum key in the subtree rooted at node x.</p>
    * @param x
    * @return
    */
    private Node max(Node x){
        if(x.right == null) return x;
        return max(x.right);
    }

    /**
    * <p>Description: return the largest key that is smaller than the key at the root of a BST</p>
    * @param key
    * @return
    */
    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;
        else if(cmp < 0) return floor(x.left, key);
        Node t = floor(x.right, key);
        if(t != null) return t;
        else return x;
    }

    public Key ceil(Key key){
        Node x = ceil(root, key);
        if(x == null) return null;
        return x.key;
    }

    private Node ceil(Node x, Key key){
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp == 0) return x;
        else if(cmp > 0) return ceil(x.right, key);
        Node t = floor(x.left, key);
        if(t != null) return t;
        else return x;
    }

    /**
    * <p>Description: Return the key of node whose rank is equal to k.</p>
    * @param k
    * @return
    */
    public Key select(int k){
        return select(root, k).key;
    }

    private Node select (Node x, int k){
        //Return node containing key of rank k.
        if(x == null) return null;
        int t = size(x.left);
        if(t > k) return select(x.left, k);
        else if (t < k) return select(x.right, k - t - 1);
        else return x;
    }

    /**
    * <p>Description: Return the given key's rank in this tree.</p>
    * @param key
    * @return
    */
    public int rank(Key key){
        return rank(root, key);
    }

    private int rank(Node x, Key key){
        if(x == null) return 0;
        int cmp = key.compareTo(x.key);
        if(cmp < 0) return rank(x.left, key);
        else if(cmp > 0) return size(x.left) + 1 + rank(x.right, key);
        else return size(x.left);
    }

    /**
    * <p>Description: Delete the node with minimum key in this tree.</p>
    */
    public void deleteMin(){
        root = deleteMin(root);
    }

    private Node deleteMin(Node x){
        if(x.left == null) return x.right;//simply delete x itself.
        x.left = deleteMin(x.left);
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    /**
    * <p>Description: Delete the node with maximum key in this tree.</p>
    */
    public void deleteMax(){
        root = deleteMax(root);
    }

    private Node deleteMax(Node x){
        if(x.right == null) return x.left;// simply delete x itself.
        x.right = deleteMax(x.right);
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    /**
    * <p>Description: Given key, delete the corresponding node. </p>
    * @param key
    */
    public void delete(Key key){
        root = delete(root, key);
    }

    /**
    * <p>Description: Delete the node whose key is equal to given key in the subtree rooted at node x.</p>
    * And return the new root.<\p>
    * @param x
    * @param key
    * @return the new root.
    */
    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;//if x has only left child, simply delete x and return x's left child.
            if(x.left == null) return x.right;//if x has only right child, simply delete x and return x's right child.
            Node t = x;
            x = min(x.right);//new x is x's successor.
            x.right = deleteMin(t.right);//x's right subtree is the original x's subtree except the min in subtree.
            x.left = t.left;//new x's left is old x's left.
        }
        //Update counts.
        x.N = size(x.left) + size(x.right) + 1;
        return x;
    }

    public Iterable<Key> keys(){
        return keys(min(), max());
    }

    public Iterable<Key> keys(Key low, Key high){
        Queue<Key> queue = new Queue<Key>();
        keys(root, queue, low, high);
        return queue;
    }

    private void keys(Node x, Queue<Key> queue, Key low, Key high){
        if(x == null) return;
        int cmplow = low.compareTo(x.key);
        int cmphigh = high.compareTo(x.key);
        if(cmplow < 0) keys(x.left, queue, low, high);
        if(cmplow <= 0 && cmphigh >= 0)
            queue.add(x.key);
        if(cmphigh > 0 ) keys(x.right, queue, low, high);
    }
}

references

[1] coursera standford algorithm part I
[2] algorithm 4th edition, Sedgewick, Wayne

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值