二叉查找樹的簡單實現(xiàn)

查找二叉樹首先也是個二叉樹,符合二叉樹的一切特點。

原文地址:http://blog.csdn.net/qq_25806863/article/details/74638590

簡單介紹

但是查找二叉樹要求對樹中的每個節(jié)點,這個節(jié)點的左子樹中所有的值要小于自己丧失,右子樹中所有的值要大于自己腿堤。

下面是兩個的區(qū)別:

查找二叉樹:

查找二叉樹

不是查找二叉樹:

不是查找二叉樹

簡單實現(xiàn)

主要是查詢,插入和刪除的方法

public class MySearchTree<E extends Comparable<E>> {

    private BinaryNode<E> root;

    public MySearchTree() {
        root = null;
    }

    public void makeEmpty() {
        root = null;
    }

    public boolean isEmpty() {
        return root == null;
    }

    public boolean contains(E x) {
        return contains(x, root);
    }

    public E findMin() {
        return findMin(root).element;
    }

    public E findMax() {
        return findMax(root).element;
    }

    public void insert(E x) {
        root =  insert(x, root);
    }

    public void remove(E x) {
        remove(x, root);
    }

    public void printTree() {
        printTree(root);
    }


    /**
     * 如果這個樹上的值就是要查找的x厅克,返回true
     * 如果樹為空,說明不存在這個值橙依,返回false
     * 如果x小于這個樹上的值证舟,就在這個樹的左子樹上遞歸查找
     * 如果x大于這個樹上的值,就在這個樹的右子樹上遞歸查找
     */
    private boolean contains(E x, BinaryNode<E> tree) {
        if (tree == null) {
            return false;
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            return contains(x, tree.left);
        } else if (compareResult > 0) {
            return contains(x, tree.right);
        } else {
            return true;
        }
    }


    /**
     * 只要有左子樹就一直往左找窗骑,左子樹為空說明這個就是最小值
     */
    private BinaryNode<E> findMin(BinaryNode<E> tree) {
        if (tree == null) {
            return null;
        } else if (tree.left == null) {
            return tree;
        } else {
            return findMin(tree.left);
        }

    }

    /**
     * 只要有右子樹就一直往左找女责,右子樹為空說明這個就是最大值
     */
    private BinaryNode<E> findMax(BinaryNode<E> tree) {
        if (tree == null) {
            return null;
        } else if (tree.right == null) {
            return tree;
        } else {
            return findMax(tree.right);
        }
    }

    /**
     * 如果要插入的樹是null,說明這個就是要插入的值該放的位置创译,new一個子樹抵知,綁定到對應(yīng)的父親上
     * 如果樹不為null,說明這個樹上有值软族,拿x和這個值進(jìn)行比較
     * 如果兩個值相等刷喜,說明已經(jīng)有這個值了,可以進(jìn)行一些處理
     * 如果x小于樹上的值立砸,就往該樹的左子樹上遞歸插入
     * 如果x大于樹上的值掖疮,就往該樹的右子樹上遞歸插入
     */
    private BinaryNode<E> insert(E x, BinaryNode<E> tree) {
        if (tree == null) {
            return new BinaryNode<E>(x, null, null);
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            tree.left= insert(x, tree.left);
        } else if (compareResult > 0) {
            tree.right =  insert(x, tree.right);
        } else {
            //說明已經(jīng)有這個值了。
            System.out.println("已經(jīng)有這個值了");
        }
        return tree;
    }


    /**
     * 比較x和樹的值
     * 如果x小于樹的值颗祝,在樹的左子樹中遞歸刪除
     * 如果x大于樹的值浊闪,在樹的右子樹中遞歸刪除
     * 如果x等于樹的值,那么這個值就是要刪除的值螺戳。
     * 因為刪除一個值就要對樹進(jìn)行重新排列搁宾,所以這個位置上不能空。
     * 如果這個樹只有一個子樹倔幼,那么就直接把這個子樹放在這個位置上
     * 如果這個樹有兩個子樹盖腿,那么需要找到右子樹的最小值,將這個最小值賦值在要刪除的位置上凤藏,
     * 然后遞歸調(diào)用從右子樹中刪除剛剛找到的這個最小值
     */
    private BinaryNode<E> remove(E x, BinaryNode<E> tree) {
        if (tree == null) {
            //沒有這個樹
            return tree;
        }
        int compareResult = x.compareTo(tree.element);
        if (compareResult < 0) {
            tree.left = remove(x, tree.left);
        } else if (compareResult > 0) {
            tree.right = remove(x, tree.right);
        } else if (tree.left != null && tree.right != null) {
            tree.element = findMin(tree.right).element;
            tree.right = remove(tree.element, tree.right);
        } else {
            tree = (tree.left != null) ? tree.left : tree.right;
        }
        return tree;

    }

    private void printTree(BinaryNode<E> tree) {
        if (tree == null) {
            return;
        }
        System.out.print(tree.element+" ");
        printTree(tree.left);
        printTree(tree.right);

    }

    public static class BinaryNode<E> {
        E element;
        BinaryNode<E> left;
        BinaryNode<E> right;

        public BinaryNode(E element) {
            this(element, null, null);
        }

        public BinaryNode(E element, BinaryNode<E> left, BinaryNode<E> right) {
            this.element = element;
            this.left = left;
            this.right = right;
        }
    }
}

實現(xiàn)的缺點

在代碼中奸忽,注意remove方法中的一段代碼:

else if (tree.left != null && tree.right != null) {
    tree.element = findMin(tree.right).element;
    tree.right = remove(tree.element, tree.right);

這里對刪除的處理是,找到右子樹中的最小值揖庄,把這個最小值放在當(dāng)前節(jié)點上栗菜,然后從右子樹中刪除這個值。

而在insert的時候蹄梢,是根據(jù)比較而隨機(jī)的插入在左右子樹上的疙筹。

所以如果交叉調(diào)用insert和remove很多次的話富俄,這個二叉樹會變得很不平衡,即左右子樹的高度差很大而咆。

這種平衡的查找二叉樹叫平衡查找樹霍比。

一個最古老的平衡查找樹是AVL樹

參考《數(shù)據(jù)結(jié)構(gòu)與算法分析java版》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末暴备,一起剝皮案震驚了整個濱河市悠瞬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涯捻,老刑警劉巖浅妆,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異障癌,居然都是意外死亡凌外,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進(jìn)店門涛浙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來康辑,“玉大人,你說我怎么就攤上這事轿亮〈保” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵哀托,是天一觀的道長惦辛。 經(jīng)常有香客問我劳秋,道長仓手,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任玻淑,我火速辦了婚禮嗽冒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘补履。我一直安慰自己添坊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布箫锤。 她就那樣靜靜地躺著贬蛙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谚攒。 梳的紋絲不亂的頭發(fā)上阳准,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天,我揣著相機(jī)與錄音馏臭,去河邊找鬼野蝇。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绕沈。 我是一名探鬼主播锐想,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乍狐!你這毒婦竟也來了赠摇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤浅蚪,失蹤者是張志新(化名)和其女友劉穎蝉稳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掘鄙,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡耘戚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了操漠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片收津。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖浊伙,靈堂內(nèi)的尸體忽然破棺而出撞秋,到底是詐尸還是另有隱情,我是刑警寧澤嚣鄙,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布吻贿,位于F島的核電站,受9級特大地震影響哑子,放射性物質(zhì)發(fā)生泄漏舅列。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一卧蜓、第九天 我趴在偏房一處隱蔽的房頂上張望帐要。 院中可真熱鬧,春花似錦弥奸、人聲如沸榨惠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赠橙。三九已至,卻和暖如春愤炸,著一層夾襖步出監(jiān)牢的瞬間期揪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工摇幻, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留横侦,地道東北人挥萌。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像枉侧,于是被迫代替她去往敵國和親引瀑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容