二叉查找树

一、二叉查找树(BTS)

二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

定义:
一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。

查找

步骤:若根结点的关键字值等于查找的关键字,成功。
否则,若小于根结点的关键字值,递归查左子树。
若大于根结点的关键字值,递归查右子树。
若子树为空,查找不成功。

查找复杂

1、定义节点

class Node {
    //节点值
    int val;
    //左子节点引用
    Node leftChild;
    //右子节点引用
    Node  rightChild;
}

2、插入

首先执行查找算法,找出被插结点的父亲结点。
判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
若二叉树为空。则首先单独生成根结点。

private Node root;

public void insert(int data) {
        Node newNode = new Node();
        newNode.val = data;
        if(root == null) {
            //如果是第一个节点,也就是根节点为null,直接创建一个新的节点即可 
            root = newNode;
        } else {
            Node current = root;
            //current节点的父节点
            Node parent;
            //循环查找插入的位置
            while(true) {
                parent = current;
                //如果插入的值小于当前节点的值,从左子树查找
                if(data < current.val) {
                    current = current.leftChild;
                    //直到当前节点为null
                    if(current == null) {
                        //设置当前节点的父节点的左子节点为新创建的节点
                        parent.leftChild = newNode;
                        return;
                    }
                }
                //如果插入的值大于当前节点的值,从左子树查找
                else if (data > current.val) {
                    current = current.rightChild;
                    //直到当前节点为null
                    if(current == null) {
                        //设置当前节点的父节点的右子节点为新创建的节点
                        parent.rightChild = newNode;
                        return;
                    }
                } else {
                    // 相等
                    return;
                }
            }// end of while(true)
        }
    }

3、查找

public Node find(int value) {
        Node current = root;
        while(current.val != value) {
            if(value < current.val) {
                current = current.leftChild;
            } else {
                current = current.rightChild;
            }
            if(current == null) {
                return null;
            }
        }

        return current;
    }

4、删除

public boolean delete(int value) {

        Node current = root;
        Node parent = root;
        boolean isLeft = false;
        boolean isRight = false;
        //查找所要删除的节点的左子节点还是右子节点
        while(current.val != value) {
            parent = current;
            isLeft = false;
            isRight = false;
            if(value < current.val) {
                current = current.leftChild;
                isLeft = true;
            }
            else {
                current = current.rightChild;
                isRight = true;
            }
        }
        //不存在该值
        if(current == null) {
            return false;
        }
        //是叶子节点,不存在子节点
        if((current.leftChild == null)
                && (current.rightChild == null)) {
            System.out.println("是叶子节点,不存在子节点");
            if(isLeft) {
                //如果是左子节点,设父节点的左子节点为null
                parent.leftChild = null;
            }
            else if(isRight) {
                //如果是右子节点,设父节点的右子节点为null
                parent.rightChild = null;
            }
            return  true;
        }
        //存在左子节点
        else if((current.leftChild != null)
                && (current.rightChild == null)) {
            System.out.println("不是叶子节点,存在左子节点");

            if(isLeft) {
                parent.leftChild = current.leftChild;
            }
            else if(isRight) {
                parent.rightChild = current.leftChild;
            }
            current = null;
            return  true;
        }

        //存在右子节点
        else if((current.leftChild == null)
                && (current.rightChild != null)) {
            System.out.println("不是叶子节点,存在右子节点");
            if(isLeft) {
                parent.leftChild = current.rightChild;

            }
            else if(isRight) {
                parent.rightChild = current.rightChild;
            }
            current = null;
            return  true;
        }
        //左右子节点都存在
        else {
            System.out.println("不是叶子节点,存在左右子节点");

            if(isLeft) {
                parent.leftChild = current.rightChild;

                Node currentLeft = current.rightChild;
                Node parentLeft = currentLeft;
                while(currentLeft != null) {
                    parentLeft = currentLeft;
                    currentLeft = currentLeft.leftChild;
                }
                parentLeft.leftChild = current.leftChild;
                current = null;

            }
            else if(isRight) {
                parent.rightChild = current.rightChild;

                Node currentLeft = current.rightChild;
                Node parentLeft = currentLeft;
                while(currentLeft != null) {
                    parentLeft = currentLeft;
                    currentLeft = currentLeft.leftChild;
                }
                parentLeft.leftChild = current.leftChild;
                current = null;
            }

            return  true;
        }

    }

5、打印

public void printTree(Node head) {
        System.out.println("-----------------\r\nBinary Tree:");
        printInOrder(head, 0, "Root-", 8);
        System.out.println();
    }

    public void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.rightChild, height + 1, "R-", len);
        String val = to + head.val;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val;// + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.leftChild, height + 1, "L-", len);
    }

    public String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

存在的问题

二叉搜索树插入时是按照一定规则进行插入的,因此在中序遍历时获得的数据是有序的,比如下面查找35,只需要比较3次就可以获得结果,因此插入或者查找的效率还是比较高的。

但是存在的一个问题是,如果插入的数据是单调变化的,那就变成了线性链表,最后导致查找效率降低。
因此,也就出现了其他更好的二叉树数据结构,比如红黑树,红黑树是一种平衡的二叉树。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容