AgumentBST---MaxMinBinarySearchTree

MaxMinBinarySearchTree中的每個節(jié)點會存儲以他為根結(jié)點的子樹的最大值最小值耕漱,這樣可以使得之前介紹的findMax,findMin操作時間復(fù)雜度降為O(1)

MaxMinNode 節(jié)點結(jié)構(gòu)如下

/**
 * BST樹的優(yōu)勢在于我們可以在節(jié)點存放一些信息使得一些操作更高效
 * 比如在MaxMinNode中我們可以存放當(dāng)前節(jié)點子樹,包括自己的最大值最小值
 * 這樣可以將findMax/findMin操作的時間復(fù)雜度優(yōu)化到O(1)
 * @author haofan.whf
 * @version $Id: AugmentNode.java, v 0.1 2018年12月11日 下午7:30 haofan.whf Exp $
 */
public class MaxMinNode extends Node{

    private int minValue;

    private int maxValue;

    @Override
    public String toString() {
        return "Node{" +
                (this.getLeft() == null ? "" : "left=" + this.getLeft().getValue()) +
                (this.getRight() == null ? "" : ",right=" + this.getRight().getValue()) +
                (this.getParent() == null ? "" : ",parent=" + this.getParent().getValue()) +
                ", value=" + this.getValue() +
                (this.getList().size() == 0 ? "" : ",list=" + this.getList()) +
                ", minValue=" + this.getMinValue() +
                ", maxValue=" + this.getMaxValue() +
                '}';
    }
}

MaxMinBinarySearchTree覆寫了BinarySearchTree一些修改樹結(jié)構(gòu)的方法,在insert/delete node的時候去更新需要更新的min/max值

/**
 * 需要對原始BST的修改
 * @author haofan.whf
 * @version $Id: MaxMinBinarySearchTree.java, v 0.1 2018年12月11日 下午7:55 haofan.whf Exp $
 */
public class MaxMinBinarySearchTree extends BinarySearchTree{

    /**
     * 查詢最大值
     * T(N) = O(1)
     * @param root
     * @return
     */
    @Override
    public int findMax(Node root){
        return parseNode(root).getMaxValue();
    }

    /**
     * 查詢最小值
     * T(N) = O(1)
     * @param root
     * @return
     */
    @Override
    public int findMin(Node root){
        return parseNode(root).getMinValue();
    }

    @Override
    public Node createNode(){
        return new MaxMinNode();
    }

    @Override
    public void doAfterInsert(Node n){
        MaxMinNode mmn = parseNode(n);
        //重新計算max/min
        //新增肯定是葉子結(jié)點
        mmn.setMaxValue(mmn.getValue());
        mmn.setMinValue(mmn.getValue());
        updateMaxMin(n, 1);
    }

    /**
     * 分幾種情況
     * 1.無父節(jié)點,無需更新
     * 2.被刪除的節(jié)點只有左子樹,并且他是父節(jié)點的右節(jié)點 需要更新父節(jié)點的max
     * 3.被刪除的節(jié)點只有左子樹,并且他是父節(jié)點的左節(jié)點 無需更新
     * 4.被刪除的節(jié)點只有右子樹,并且他是父節(jié)點的左節(jié)點 需要更新父節(jié)點的min
     * 5.被刪除的節(jié)點只有右子樹,并且他是父節(jié)點的右節(jié)點 無需更新
     * 6.被刪除的節(jié)點有左和右子樹 這種情況不存在(會在delete操作前被swap掉)
     * 7.被刪除的節(jié)點是葉子節(jié)點 更新父節(jié)點max or min
     * @param n
     */
    @Override
    public void doBeforeDelete(Node n){
        int leftOrRight = leftOrRight(n);
        if(leftOrRight == 0){
            //沒有父節(jié)點,無需更新
            return;
        }
        if(n.getLeft() != null && n.getRight() == null && leftOrRight == -1){
            //被刪除的節(jié)點只有左子樹,并且他是父節(jié)點的左節(jié)點 無需更新
            return;
        }
        if(n.getLeft() == null && n.getRight() != null && leftOrRight == 1){
            //被刪除的節(jié)點只有右子樹,并且他是父節(jié)點的右節(jié)點 無需更新
            return;
        }
        if(n.getLeft() != null && n.getRight() != null){
            //被刪除的節(jié)點有左和右子樹 這種情況不存在(會在delete操作前被swap掉)
            throw new RuntimeException("impossible");
        }
        MaxMinNode mmnp = parseNode(n.getParent());

        if(n.getLeft() != null && n.getRight() == null && leftOrRight == 1){
            //被刪除的節(jié)點只有左子樹,并且他是父節(jié)點的右節(jié)點 需要更新父節(jié)點的max
            mmnp.setMaxValue(super.findMax(n.getLeft()));
        }
        if(n.getLeft() == null && n.getRight() != null && leftOrRight == -1){
            //被刪除的節(jié)點只有右子樹,并且他是父節(jié)點的左節(jié)點 需要更新父節(jié)點的min
            mmnp.setMinValue(super.findMin(n.getRight()));
        }
        if(n.getLeft() == null && n.getRight() == null){
            if(leftOrRight == 1){
                mmnp.setMaxValue(mmnp.getValue());
            }else{
                mmnp.setMinValue(mmnp.getValue());
            }
        }
        //之后將父節(jié)點當(dāng)作新插入的節(jié)點更新即可
        updateMaxMin(n.getParent(), 0);
    }

    /**
     * 更新該節(jié)點所有父節(jié)點的max or min值
     * @param n
     */
    private void updateMaxMin(Node n, int opt){
        int leftOrRight = leftOrRight(n);
        if(leftOrRight == 0){
            //沒有父節(jié)點,那么當(dāng)前節(jié)點是根節(jié)點,是第一個被插入的元素
            return;
        }
        //當(dāng)前節(jié)點的leftOrRight值
        int currentNodeLOR = leftOrRight;
        //currentNodeLOR * leftOrRight>0則同方向,反之則是zig-zag
        while (n != null && n.getParent() != null && currentNodeLOR * leftOrRight > 0){
            MaxMinNode mmn = parseNode(n);
            MaxMinNode mmnp = parseNode(n.getParent());
            if(leftOrRight == -1){
                //應(yīng)當(dāng)更新父節(jié)點的最小值
                if(opt==1 && mmn.getMinValue() < mmnp.getMinValue()){
                    mmnp.setMinValue(mmn.getMinValue());
                }else if(opt == 0 && mmn.getMinValue() > mmnp.getMinValue()){
                    mmnp.setMinValue(mmn.getMinValue());
                }
            }else if(leftOrRight == 1){
                //應(yīng)當(dāng)更新父節(jié)點的最大值
                if(opt == 1 && mmn.getMaxValue() > mmnp.getMaxValue()){
                    mmnp.setMaxValue(mmn.getMaxValue());
                }else if(opt == 0 && mmn.getMaxValue() < mmnp.getMaxValue()){
                    mmnp.setMaxValue(mmn.getMaxValue());
                }
            }
            currentNodeLOR = leftOrRight(n.getParent());
            n = n.getParent();
        }
    }

    /**
     * throw runtime exception unless node is MaxMinNode
     */
    private MaxMinNode parseNode(Node n){
        if(n instanceof MaxMinNode){
            return (MaxMinNode)n;
        }else{
            throw new RuntimeException("node type not match");
        }
    }

    /**
     * 對MaxMinBST結(jié)構(gòu)進(jìn)行修改后調(diào)用此方法查看結(jié)構(gòu)的完整性
     * T(N) = O(N)
     * 需要遍歷每個節(jié)點與他左右自節(jié)點的大小關(guān)系是否滿足并且節(jié)點中記錄的max/min值符合要求
     * @param root
     */
    public void checkRI(Node root){
        if(root == null){
            return;
        }
        int maxValue = super.findMax(root);
        int minValue = super.findMin(root);
        MaxMinNode mmn = parseNode(root);
        if(maxValue != mmn.getMaxValue() || minValue != mmn.getMinValue()){
            throw new RuntimeException("it's not a max/min bst");
        }
        if(root.getRight() != null){
            if(root.getValue() > root.getRight().getValue()){
                System.err.println(root);
                throw new RuntimeException("it's not a bst");
            }
        }
        if(root.getLeft() != null){
            if(root.getValue() < root.getLeft().getValue()){
                System.err.println(root);
                throw new RuntimeException("it's not a bst");
            }
        }
        checkRI(root.getRight());
        checkRI(root.getLeft());

    }
}

測試用例

public class BSTTest {
    @Test
    public void bstMaxMinAugment(){
        BinarySearchTree bst = new MaxMinBinarySearchTree();

        int[] insertArray = randomArray(1000);
        //insertArray = new int[]{2,5,3,9,6,1,8,4};
        Node root = new MaxMinNode();
        for (int i = 0; i < insertArray.length; i++) {
            bst.insert(root, insertArray[i]);
            bst.checkRI(root);
        }

        int[] deleteArray = randomArray(100);
        //deleteArray = new int[]{3,7,0,4,8};
        for (int i = 0; i < deleteArray.length; i++) {
            bst.delete(root, deleteArray[i]);
            bst.checkRI(root);
        }

    }

    private static int[] randomArray(int size){
        Random random = new Random();
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = random.nextInt(size);
        }
        return array;
    }


}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肚医,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爱致,老刑警劉巖哥放,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異咖摹,居然都是意外死亡评姨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門萤晴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吐句,“玉大人,你說我怎么就攤上這事硫眯≡滩啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵两入,是天一觀的道長净宵。 經(jīng)常有香客問我,道長裹纳,這世上最難降的妖魔是什么择葡? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮剃氧,結(jié)果婚禮上敏储,老公的妹妹穿的比我還像新娘。我一直安慰自己朋鞍,他們只是感情好已添,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滥酥,像睡著了一般更舞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坎吻,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天缆蝉,我揣著相機(jī)與錄音,去河邊找鬼。 笑死刊头,一個胖子當(dāng)著我的面吹牛黍瞧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播原杂,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼印颤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了污尉?” 一聲冷哼從身側(cè)響起膀哲,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎被碗,沒想到半個月后某宪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锐朴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年兴喂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焚志。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡衣迷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酱酬,到底是詐尸還是另有隱情壶谒,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布膳沽,位于F島的核電站汗菜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挑社。R本人自食惡果不足惜陨界,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痛阻。 院中可真熱鬧菌瘪,春花似錦、人聲如沸阱当。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弊添。三九已至动猬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間表箭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留免钻,地道東北人彼水。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像极舔,于是被迫代替她去往敵國和親凤覆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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

  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結(jié)點至多有m個孩子拆魏。 除根結(jié)點和葉子結(jié)點外盯桦,其它每個結(jié)點至少有m...
    文檔隨手記閱讀 13,221評論 0 25
  • 0.目錄 1.優(yōu)先隊列ADT 2.幾種實現(xiàn) 3.二叉堆 4.d-堆 5.左式堆 6.斜堆 7.二項隊列 8.斐波那...
    王偵閱讀 3,093評論 1 2
  • 課程介紹 先修課:概率統(tǒng)計,程序設(shè)計實習(xí)渤刃,集合論與圖論 后續(xù)課:算法分析與設(shè)計拥峦,編譯原理,操作系統(tǒng)卖子,數(shù)據(jù)庫概論略号,人...
    ShellyWhen閱讀 2,290評論 0 3
  • 一起吃三餐的時候,你的歡笑洋闽,我的錯愕玄柠,雖然不在一張桌子上。 一起上班的時候诫舅,你的表情羽利,我的目光,雖然有點距離刊懈。 偶...
    陳家仁閱讀 179評論 0 1
  • 曾經(jīng) 我寧可負(fù)這天下俏讹,負(fù)這滿天神佛 也不愿負(fù)你 而你 卻愿屈于神佛当宴,想要這天下萬物 棄我于水火煉獄 如今 我已成魔...
    哲學(xué)喵醬閱讀 202評論 0 0