算法笔记(三)-二叉查找树

2019-05-01  本文已影响0人  jacob_

1 定义

2 基本实现

package BinaryTree.BinarySearchTree;

public class BTS<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;
        }

        //以该节点为根的子树中的节点总数
        public int size() {
            return size(root);
        }

        private int size(Node x) {
            if (x == null) {
                return 0;
            } else {
                return x.N;
            }
        }

        //查找某个值
        public Value get(Key key) {
            return get(root, key);
        }

        public Value get(Node x, Key key) {
            //如果树为空,则返回null
            if (x == null) {
                return null;
            }
            int cmp = key.compareTo(x.key);
            //如果相等,则返回该结点,小于就去左子树,大于就去右子树
            if(cmp == 0){
                return x.value;
            }else if(cmp<0){
                return get(x.left, key);
            }else{
                return get(x.right, key);
            }
        }

        //插入某个值
        public void put(Key key, Value value) {
            //查找key,找到更新它的值,找不到则插入
            root = put(root, key, value);
        }

        public Node put(Node x, Key key, Value 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 = size(x.left) + size(x.right) + 1;
            return x;
        }

        public Key min() {
            return min(root).key;
        }

        public Node min(Node x) {
            if (x.left == null) return x;
            return min(x.left);
        }

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

        public 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);
            Node t = floor(x.right, key);
            if (t != null) return t;
            else return x;
        }
    }
}

2.1 查找

2.2 插入

2.3 最大键和最小键

        public Node min(Node x) {
            if (x.left == null) return x;
            return min(x.left);
        }
        public Node max(Node x) {
            if (x.right == null) return x;
            return min(x.right);
        }

2.4 向上取整和向下取整

        public 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);
            }else{
                //当找到小于key的键,要判断其右子树是否存在小于等于key的键,若有则返回那个节点,没有则返回当前节点
                Node t = floor(x.right, key);
                if (t != null) return t;
                else return x;
            }
        }

2.5 select选择操作

        public Node select(Node x, int 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;
            }
        }

2.6 删除最大键和最小键

        public Node deleteMin(Node x) {
            if (x.left == null) return x.right;
            x.left = deleteMin(x.left);
            x.N = size(x.left) + size(x.right) + 1;
            return x;
        }

2.7 删除任意键

        public 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.left == null) return x.right;
                Node t = x;
                x = min(t.right);
                x.right = deleteMin(t.right);
                x.left = t.left;
            }
            x.N = size(x.left) + size(x.right) +1;
            return x;
        }

2.8 范围查找

        public void key(Node x, Queue<Key> queue,Key lo,Key hi){
            if(x == null){
                return ;
            }
            int cmplo = lo.compareTo(x.key);
            int cmphi = hi.compareTo(x.key);
            if(cmplo<0){
                key(x.left,queue,lo,hi);
            }
            if(cmplo<=0&&cmphi>=0){
                queue.add(x.key);
            }
            if(cmphi>0){
                key(x.right,queue,lo,hi);
            }
        }

3 练习

3.1 插入练习

    @Test
    public void testPut(){
        BTS<Character,String> bts = new BTS<Character,String>();
        Character ch[] = {'E','A','S','Y','Q','E','S','T','I','O','N'};
        BTS.Node node = bts.new Node();
        for(char c:ch){
            node.put(c,"");
        }
        //先序遍历一下
        node.preOrder(bts.root);
    }

3.2 插入顺序导致的最优与最劣二叉查找树结构

3.3 为二叉查找树添加查询树高度的方法

        public int height() {
            return height(root);
        }
        private int height(Node x) {
            if (x == null) return 0;
            return 1 + Math.max(height(x.left), height(x.right));
        }

3.4 方法测试

package BinaryTree.BinarySearchTree;


import sun.misc.Queue;

public class BTS<Key extends Comparable<Key>, Value> {
    //二叉树根节点
    public Node root;

    public class Node {
        private Key key; //键
        private Value value;//值
        private Node left, right;//左节点和右节点
        private int N;//以该节点为根的子树中的节点总数
        public Node(){

        }
        //构造方法
        public Node(Key key, Value value, int N) {
            this.key = key;
            this.value = value;
            this.N = N;
        }


        public int height() {
            return height(root);
        }
        private int height(Node x) {
            if (x == null) return 0;
            return 1 + Math.max(height(x.left), height(x.right));
        }
        //线序遍历
        public void preOrder(){
            preOrder(root);
        }
        //线序遍历
        private void preOrder(Node x){
            if(x == null) return;
            System.out.print(x.key);
            preOrder(x.left);
            preOrder(x.right);
        }
        //以该节点为根的子树中的节点总数
        public int size() {
            return size(root);
        }

        private int size(Node x) {
            if (x == null) {
                return 0;
            } else {
                return x.N;
            }
        }

        //查找某个值
        public Value get(Key key) {
            return get(root, key);
        }

        private Value get(Node x, Key key) {
            //如果树为空,则返回null
            if (x == null) {
                return null;
            }
            int cmp = key.compareTo(x.key);
            if (cmp == 0) {
                return x.value;
            } else if (cmp < 0) {
                return get(x.left, key);
            } else {
                return get(x.right, key);
            }
        }

        //插入某个值
        public void put(Key key, Value value) {
            //查找key,找到更新它的值,找不到则插入
            root = put(root, key, value);
        }

        private Node put(Node x, Key key, Value value) {
            if (x == null) {
                return new Node(key, value, 1);
            }
            int cmp = key.compareTo(x.key);
            if (cmp == 0) {
                x.value = value;
            } else if (cmp < 0) {
                x.left = put(x.left, key, value);
            } else {
                x.right = put(x.right, key, value);
            }
            x.N = size(x.left) + size(x.right) + 1;
            return x;
        }

        public Key min() {
            return min(root).key;
        }

        public Node min(Node x) {
            if (x.left == null) return x;
            return min(x.left);
        }

        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);
            } else {
                //当找到小于key的键,要判断其右子树是否存在小于等于key的键,若有则返回那个节点,没有则返回当前节点
                Node t = floor(x.right, key);
                if (t != null) return t;
                else return x;
            }
        }
        public Key select(int k){
            return select(root,k).key;
        }
        private Node select(Node x, int 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;
            }
        }
        public void deleteMin(){
            root = deleteMin(root);
        }
        private Node deleteMin(Node x) {
            if (x.left == null) return x.right;
            x.left = deleteMin(x.left);
            x.N = size(x.left) + size(x.right) + 1;
            return x;
        }

        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;
                if(x.left == null) return x.right;
                Node t = x;
                x = min(t.right);
                x.right = deleteMin(t.right);
                x.left = t.left;
            }
            x.N = size(x.left) + size(x.right) +1;
            return x;
        }
        public Queue<Key> keys(Key lo,Key hi){
            Queue<Key> queue = new Queue<Key>();
            keys(root,queue,lo,hi);
            return  queue;
        }

        private void keys(Node x, Queue<Key> queue,Key lo,Key hi){
            if(x == null){
                return ;
            }
            int cmplo = lo.compareTo(x.key);
            int cmphi = hi.compareTo(x.key);
            if(cmplo<0){
                keys(x.left,queue,lo,hi);
            }
            if(cmplo<=0&&cmphi>=0){
                queue.enqueue(x.key);
            }
            if(cmphi>0){
                keys(x.right,queue,lo,hi);
            }
        }
    }
}
package BinaryTree.BinarySearchTree;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import sun.misc.Queue;

import static org.junit.Assert.*;

public class BTSTest {
    BTS<Character, Integer> bts = new BTS<Character, Integer>();
    Character ch[] = {'E', 'A', 'S', 'Y', 'Q', 'E', 'S', 'T', 'I', 'O', 'N'};
    BTS.Node node = bts.new Node();

    @Before
    public void testBefore() {
        for (int i = 1; i <= ch.length; i++) {
            node.put(ch[i - 1], i);
        }
    }

    @Test
    public void testPut() {
        //先序遍历一下
        node.preOrder();
        System.out.println();
        //求树高度
        System.out.print(node.height());
    }

    @Test
    public void testGet() {
        //asn = 7
        System.out.println(node.get('S'));
    }
    @Test
    public void testFloor(){
        //找小于F的最大键,ans = E
        System.out.println(node.floor('F'));
    }
    @Test
    public void testSelect(){
        //选出比5个键大的那个键asn = Q
        System.out.println(node.select(5));
    }
    @Test
    public void testDeleteMin(){
        node.deleteMin();
        node.preOrder();
    }
    @Test
    public void testDelete(){
        node.delete('E');
        node.preOrder();
    }
    @Test
    public void testKeys() throws InterruptedException {
        Queue<Character> queue = node.keys('I','T');
        while (!queue.isEmpty()){
            System.out.print(queue.dequeue());
        }
    }
}
代码中生成的树

3.5 完美平衡

    @Test
    public void testPrefect(){
        Arrays.sort(ch);
        prefect(ch,0,ch.length-1);
        bts.preOrder();
    }
    private void prefect(Character []a,int lo, int hi){
        if(lo > hi) return ;
        int mid = lo + ((hi - lo)>>1);
        bts.put(a[mid],mid);
        prefect(a,lo,mid-1);
        prefect(a,mid +1 ,hi);
    }
上一篇 下一篇

猜你喜欢

热点阅读