二叉查找樹

簡(jiǎn)介

二叉查找樹(Binary Search Tree),又被成為二叉搜索樹卢鹦。
它是特殊的二叉樹:對(duì)于二叉樹臀脏,假設(shè)x為二叉樹中的任意一個(gè)節(jié)點(diǎn),x節(jié)點(diǎn)包含關(guān)鍵字key,節(jié)點(diǎn)x的key值記為key[x]揉稚。如果y是x的左子樹中的一個(gè)節(jié)點(diǎn)秒啦,則key[y]<key[x];如果y是x的右子樹的一個(gè)節(jié)點(diǎn),則key[y]>key[x]窃植。那么帝蒿,這棵樹就是二叉查找樹。如圖


image.png

在二叉查找樹中:

  1. 若任意節(jié)點(diǎn)的左子樹不空巷怜,則左子樹上所有節(jié)點(diǎn)的值均小于他的根節(jié)點(diǎn)的值葛超;
  2. 若任意節(jié)點(diǎn)的右子樹不空,則右子樹上所有節(jié)點(diǎn)的值均大于它的根節(jié)點(diǎn)的值延塑;
  3. 任意節(jié)點(diǎn)的左绣张、右子樹也分別為二叉查找樹;
  4. 沒有鍵值相等的節(jié)點(diǎn)关带。

遍歷

這里講解前序遍歷侥涵、中序遍歷和后續(xù)遍歷3中方式。

  1. 前序遍歷
    若二叉樹非空宋雏,則執(zhí)行以下操作:
  • 訪問根節(jié)點(diǎn)
  • 先序遍歷左子樹
  • 先序遍歷右子樹
  1. 中序遍歷
    若二叉樹非空芜飘,則執(zhí)行以下操作:
  • 中序遍歷左子樹
  • 訪問根節(jié)點(diǎn)
  • 中序遍歷右子樹
  1. 后序遍歷
    若二叉樹非空,則執(zhí)行以下操作:
  • 后序遍歷左子樹
  • 后序遍歷右子樹
  • 訪問根節(jié)點(diǎn)
public class Node {

    public int key;
    public int value;
    public Node leftChild;
    public Node rightChild;

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

public class Tree {

    private Node root; //保存樹的根

    /**
     * 查找指定節(jié)點(diǎn)
     */
    public Node find(int key) {
        Node currentNode = root;
        while (null != currentNode && currentNode.key != key) {
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
            } else {
                currentNode = currentNode.rigthChild;
            }
        }
        return currentNode;
    }

    /**
     * 插入節(jié)點(diǎn)
     */
    public void insert(int key, int value) {
        if (null == root) {
            root = new Node(key, value);
            return;
        }

        Node currentNode = root;
        Node parentNode = root;
        boolean isLeftChild = true;
        while (currentNode != null) {
            parentNode = currentNode;
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
                isLeftChild = true;
            } else {
                currentNode = currentNode.rigthChild;
                isLeftChild = false;
            }
        }

        Node newNode = new Node(key, value);
        if (isLeftChild) {
            parentNode.leftChild = newNode;
        } else {
            parentNode.rigthChild = newNode;
        }
    }

    /**
     * 刪除指定節(jié)點(diǎn)
     */
    public boolean delete(int key) {
        Node currentNode = root;
        Node parentNode = root;
        boolean isLeftChild = true;
        while (null != currentNode && currentNode.key != key) {
            parentNode = currentNode;
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
                isLeftChild = true;
            } else {
                currentNode = currentNode.rigthChild;
                isLeftChild = false;
            }
        }

        if (currentNode == null) {
            return false;
        }

        if (currentNode.leftChild == null && currentNode.rigthChild == null) {
            if (currentNode == root) { //要?jiǎng)h除的節(jié)點(diǎn)為葉子節(jié)點(diǎn)
                root = null;
            } else if (isLeftChild) {
                parentNode.leftChild = null;
            } else {
                parentNode.rigthChild = null;
            }
        } else if (currentNode.rigthChild == null) { //要?jiǎng)h除的節(jié)點(diǎn)只有左孩子
            if (currentNode == root) {
                root = currentNode.leftChild;
            } else if (isLeftChild) {
                parentNode.leftChild = currentNode.leftChild;
            } else {
                parentNode.rigthChild = currentNode.leftChild;
            }
        } else if (currentNode.leftChild == null) {
            if (currentNode == root) {
                root = currentNode.rigthChild;
            } else if (isLeftChild) {
                parentNode.leftChild = currentNode.rigthChild;
            } else {
                parentNode.rigthChild = currentNode.leftChild;
            }
        } else {
            //要?jiǎng)h除的節(jié)點(diǎn)既有左孩子又有有孩子
            //思路:用待刪除節(jié)點(diǎn)右子樹中的key值最小的節(jié)點(diǎn)的值來替代要?jiǎng)h除的節(jié)點(diǎn)的值,然后刪除右子樹中key值最小的節(jié)點(diǎn)
            //右子樹key最小的節(jié)點(diǎn)一定不含左子樹,所以刪除這個(gè)key最小的節(jié)點(diǎn)一定是屬于葉子節(jié)點(diǎn)或者只有右子樹的節(jié)點(diǎn)
            Node directPostNode = getDirectPostNode(currentNode);
            currentNode.key = directPostNode.key;
            currentNode.value = directPostNode.value;
        }
        return true;
    }

    /**
     * 得到待刪除節(jié)點(diǎn)的直接后繼節(jié)點(diǎn)
     */
    private Node getDirectPostNode(Node delNode) {
        Node parentNode = delNode;//用來保存待刪除節(jié)點(diǎn)的直接后繼節(jié)點(diǎn)的父親節(jié)點(diǎn)
        Node directPostNode = delNode; //用來保存待刪除節(jié)點(diǎn)的直接后繼節(jié)點(diǎn)
        Node currentNode = delNode.rigthChild;
        while (currentNode != null) {
            parentNode = directPostNode;
            directPostNode = currentNode;
            currentNode = currentNode.leftChild;
        }

        if (directPostNode != delNode.rigthChild) { //從樹中刪除此直接后繼節(jié)點(diǎn)
            parentNode.leftChild = directPostNode.rigthChild;
            directPostNode.rigthChild = null;
        }
        return directPostNode;
    }

    /**
     * 先序遍歷樹
     */
    public void preOrder(Node rootNode) {
        if (null != rootNode) {
            System.out.println(rootNode.key + " " + rootNode.value);
            preOrder(rootNode.leftChild);
            preOrder(rootNode.rigthChild);
        }
    }

    /**
     * 中序遍歷樹
     */
    public void inOrder(Node rootNode) {
        if (null != rootNode) {
            inOrder(rootNode.leftChild);
            System.out.println(rootNode.key + " " + rootNode.value);
            inOrder(rootNode.rigthChild);
        }
    }

    /**
     * 后序遍歷樹
     */
    public void postOrder(Node rootNode) {
        if (null != rootNode) {
            postOrder(rootNode.leftChild);
            postOrder(rootNode.rigthChild);
            System.out.println(rootNode.key + " " + rootNode.value);
        }
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末磨总,一起剝皮案震驚了整個(gè)濱河市嗦明,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚪燕,老刑警劉巖娶牌,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馆纳,居然都是意外死亡诗良,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門鲁驶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鉴裹,“玉大人,你說我怎么就攤上這事钥弯∫挤#” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵寿羞,是天一觀的道長(zhǎng)猖凛。 經(jīng)常有香客問我,道長(zhǎng)绪穆,這世上最難降的妖魔是什么辨泳? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任虱岂,我火速辦了婚禮,結(jié)果婚禮上菠红,老公的妹妹穿的比我還像新娘第岖。我一直安慰自己,他們只是感情好试溯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布蔑滓。 她就那樣靜靜地躺著,像睡著了一般遇绞。 火紅的嫁衣襯著肌膚如雪键袱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天摹闽,我揣著相機(jī)與錄音蹄咖,去河邊找鬼。 笑死付鹿,一個(gè)胖子當(dāng)著我的面吹牛澜汤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播舵匾,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼俊抵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了坐梯?” 一聲冷哼從身側(cè)響起徽诲,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烛缔,沒想到半個(gè)月后馏段,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轩拨,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡践瓷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亡蓉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晕翠。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖砍濒,靈堂內(nèi)的尸體忽然破棺而出淋肾,到底是詐尸還是另有隱情,我是刑警寧澤爸邢,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布樊卓,位于F島的核電站,受9級(jí)特大地震影響杠河,放射性物質(zhì)發(fā)生泄漏碌尔。R本人自食惡果不足惜浇辜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唾戚。 院中可真熱鬧柳洋,春花似錦、人聲如沸叹坦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)募书。三九已至绪囱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锐膜,已是汗流浹背毕箍。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留道盏,地道東北人而柑。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像荷逞,于是被迫代替她去往敵國(guó)和親媒咳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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