美文网首页
二叉查找树

二叉查找树

作者: sadamu0912 | 来源:发表于2019-01-12 16:07 被阅读0次

什么叫二叉查找树

一个节点最多只有左子树和右子树。而且左子树中的节点都小于节点,右子树中的所有节点都大于根节点。

什么叫满二叉树

除了叶子节点外所有节点都有左子树和右子树。而且叶子节点个数满足。假设高度h,则叶子节点个数是2的
(h-1)次方。
如下图:


image.png

什么叫完全二叉树

就是把满二叉树,从上到下从左到右编号1~n。然后完全二叉树有k个节点,k小于n,则1到k的每个节点和满二叉树一一对应。就是完全二叉树
如下图:


image.png

深度遍历(3种)

1 前序遍历
按照满二叉树的编号,1,2,3 1--->2--->3
2 中序遍历,还是按照满二叉树的编号 2--->1--->3
3 后序遍历 2---3---1
如果遇到的是一颗树,那就按照基本的在走一遍。比如前序遍历


image.png

前序遍历:1 2 4 5 7 8 3 6 (优先遍历左子树,然后到叶子节点之后,再回过来遍历,最上层的右子树)

中序遍历:4 2 7 5 8 1 3 6

后序遍历:4 7 8 5 2 6 3 1

层次遍历:1 2 3 4 5 6 7 8
最后上代码,说明BST(二叉查找树)如何进行增删查找。

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class BSTreeComparable<T extends Comparable> {

    private transient Node root;

    private static final String SUCCESSOR="successor";

    private static final String SUCCESSOR_PARENT="parent";

    private static final Node EMPTY_NODE = new Node(null,null,null,"empty node");

    public BSTreeComparable() { //初始化为一个空树
        root = null;
    }

    /**ConcurrentHashMap
     * 查询数据方法
     * @param key
     * @return
     */
    public Node get(T key){
        if(root ==null) return null;
        Node node =  getRecursive(root,key);
        if(node ==null) return  EMPTY_NODE;
        return node;
    }

    /**
     * 递归比较大小,如果小于该节点,则拿左节点继续比较
     * 如果大于该节点,就拿右节点继续比较
     * @param tree
     * @param key
     * @return
     */
    private Node getRecursive(Node tree,T key){
        if(tree==null) return null;
        if(key.compareTo(tree.key)<0){
            return getRecursive(tree.leftNode,key);
        }else if(key.compareTo(tree.key)>0){
            return getRecursive(tree.rightNode,key);
        }else{
            return tree;
        }
    }

    /**
     * 往BST中插入数据
     * @param key
     * @param value
     */
    public  void put(T key,Object value){
        if (root == null){
            root =  new Node(null,null,key,value);
        }else{
            putRecursive(root,key,value);
        }
    }
    private Node  putRecursive(Node tree,T key,Object value){
        if(tree==null) return new Node(null,null,key,value);
        if(key.compareTo(tree.key)<0){
            tree.leftNode = putRecursive(tree.leftNode,key,value);
        }else if(key.compareTo(tree.key)>0){
            tree.rightNode = putRecursive(tree.rightNode,key,value);
        }else{
            tree.content = value;
        }
        return tree;
    }

    public void remove(T key){
       Node newTree = remove(root,key);
       root = newTree;
    }

    /**
     * 从tree中找到这个节点,然后干掉,然后返回一颗新的树
     * @param tree
     * @param key
     * @return
     */
    private Node remove(Node tree ,T key){
        if(tree==null) return null;

        //先递归去找到这个节点
        if (key.compareTo(tree.key) < 0) {
            tree.leftNode = remove(tree.leftNode, key);
            return tree;
        }
        else if (key.compareTo(tree.key) > 0) {
            tree.rightNode = remove(tree.rightNode, key);
            return tree;
        }// 相等说明已经找到这个节点了
        else{
            //case 1 假如这个节点左子树为空,则右子树顶包
            if (tree.leftNode == null && tree.rightNode!=null) {
                Node rightTree = tree.rightNode;
               tree=null;
                return rightTree;
            }
            //case 2 假如这个节点右子树为空,则左子树顶包
            else if (tree.rightNode == null&& tree.leftNode!=null){
                Node leftTree = tree.leftNode;
                tree=null;
                return  leftTree;
                //case 3 是叶子节点
            }else if(tree.rightNode == null&& tree.leftNode==null){
                tree=null;    return  null;

            }
            //case 4 假如这个节点左右子树都不为空,则找到右子树种的最小值顶包
            else{
                Node toBeDeleted = tree;
                Map map = getSuccessor(tree.rightNode,null);
                Node successor = (Node) map.get(SUCCESSOR);
                Node successorParent = (Node) map.get(SUCCESSOR_PARENT);
                //如果successorParent是null的话,说明successor就是右节点
                if(successorParent==null){
                    successor.leftNode = toBeDeleted.leftNode;
                    tree=null;
                    toBeDeleted =null;
                    return   successor;
                }else{
                    successor.leftNode = toBeDeleted.leftNode;
                    successor.rightNode = toBeDeleted.rightNode;
                    successorParent.leftNode =null;
                    tree=null;
                    toBeDeleted =null;
                    return successor;
                }
            }
        }
    }

    /**
     * 返回顶包的节点,右子树的最小值就是继承者
     * @param tree
     * @param map
     * @return
     */
    private Map<String,Node> getSuccessor(Node tree,Map<String,Node> map) {
        if (map == null) {
            map =  new HashMap<>();
        }
        if (tree.leftNode == null){
            map.put(SUCCESSOR,tree);
            return map;
        }
        map.put(SUCCESSOR_PARENT,tree);
        Map<String,Node> map2 =  getSuccessor(tree.leftNode,map);
        return map2;
    }


    public static int getHeight(Node root) {
        if (root == null) {
            return 0;
        }
        int leftHeight = 0;//记录左子树的树高
        int rightHeight = 0;//记录右子树树高
        if (root.leftNode != null) {//左子树不为空
            leftHeight += getHeight(root.leftNode) + 1;//实际就是左子树树高的累计,加上root节点,如果不加1,得到的就是最大子树的树高,不好root节点
        }
        if (root.rightNode != null) {
            rightHeight += getHeight(root.rightNode) + 1;
        }
        return leftHeight >= rightHeight ? leftHeight : rightHeight;
    }
    public void displayTree(){
        Stack globalStack = new Stack();
        globalStack.push(root);
        int treeHeight = getHeight(root);
        int nBlanks = (int) Math.pow(2d,(double)treeHeight);
        boolean isRowEmpty = false;
        System.out.println("=========================================================================");
        while(!isRowEmpty) {
            Stack localStack = new Stack();
            isRowEmpty = true;
            for (int  j =0;j<nBlanks;j++) {
                System.out.print(" ");
            }

            while (!globalStack.isEmpty()) {
                Node temp = (Node)globalStack.pop();
                if (temp!=null) {
                    System.out.print(temp.key);
                    localStack.push(temp.leftNode);
                    localStack.push(temp.rightNode);
                    if (temp.leftNode != null || temp.rightNode !=null) {
                        isRowEmpty = false;
                    }
                }
                else {
                    System.out.print("--");
                    localStack.push(null);
                    localStack.push(null);
                }
                for (int j = 0;j<nBlanks*2-2;j++) {
                    System.out.print(" ");
                }
            }
            System.out.println();
            nBlanks /= 2;
            while (!localStack.isEmpty()) {
                globalStack.push(localStack.pop());
            }
        }
        System.out.println("=========================================================================");
    }

    static final class Node<T>{
        public Node leftNode;
        public Node rightNode;
        public T key;
        public Object content;

        public Node(Node leftNode, Node rightNode, T key, Object content) {
            this.leftNode = leftNode;
            this.rightNode = rightNode;
            this.key = key;
            this.content = content;
        }
    }
}

测试类如下图:

public class BSTreeComparableTest {
    public static void main(String[] args) {
        BSTreeComparable tree = new BSTreeComparable();
        tree.put(20,"20");
        tree.put(10,"10");
        tree.put(7,"7");
        tree.put(4,"4");
        tree.put(30,"30");
        tree.put(40,"40");
        tree.put(14,"14");
        tree.put(12,"12");
        tree.put(15,"15");
        //tree.remove(12);  //删除叶子节点
        //tree.remove(30);  //删除有右子树的节点
        //tree.remove(7);  //删除有左子树的节点
        //tree.remove(1);  //删除不存在的节点
        //tree.remove(10); //删除有左子树和右子树的节点
       tree.displayTree();
    }
}

相关文章

  • 极客时间数据结构与算法之美笔记25~26

    二叉树到二叉查找树,是为了查找数据的效率接近logN。 二叉查找树到平衡二叉查找树,是为了防止二叉查找树沦为链表。...

  • 二叉查找树

    1)二叉查找树是什么?2)二叉查找树的插入、删除、查找?3)Go代码实现 一、二叉查找树是什么?二叉查找树(BST...

  • 红黑树

    红黑树的本质就是一棵二叉查找树,所以先从二叉查找树来了解起。 二叉查找树 二叉查找树又称有序二叉树,具有以下特性:...

  • 二叉查找树

    二叉查找树,又称二叉搜索树 二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质: ...

  • 99-数据结构和算法

    难点:二叉树的遍历 红黑树 图的遍历 二叉查找树二叉查找树(binary search tree),二叉查找树在二...

  • 11-二叉查找树

    二叉查找树 1.什么是二叉查找树? 二叉查找树是一种支持数据动态的插入,删除,查找的数据结构。 2.二叉查找树的设...

  • 17张图带你解析红黑树的原理!保证你能看懂!

    二叉查找树 由于红黑树本质上就是一棵二叉查找树,所以在了解红黑树之前,咱们先来看下二叉查找树。 二叉查找树(Bin...

  • 二叉树 堆 2019-04-17

    二叉树 实现一个二叉查找树,并且支持插入、删除、查找操作 实现查找二叉查找树中某个节点的后继、前驱节点 实现二叉树...

  • 6. 二叉树创建-查找

    1. 递归方式实现二叉树的构建2. 树、二叉树、二叉查找树3. 二叉树排序树的理解4. 二叉查找树5. 二叉树的查找

  • 数据结构中的各种树

    一、二叉树 二、二叉查找树(又称二叉排序树,二叉搜索树) 二叉查找树(Binary Search Tree)它或者...

网友评论

      本文标题:二叉查找树

      本文链接:https://www.haomeiwen.com/subject/rwlcdqtx.html