【數(shù)據(jù)結(jié)構(gòu)與算法】二叉樹遍歷

搜索二叉樹概念

二叉樹是樹的特殊一種,具有如下特點(diǎn):
1、每個結(jié)點(diǎn)最多有兩顆子樹,結(jié)點(diǎn)的度最大為2左刽。
2、左子樹和右子樹是有順序的酌媒,次序不能顛倒欠痴。
3、即使某結(jié)點(diǎn)只有一個子樹秒咨,也要區(qū)分左右子樹喇辽。

搜索二叉樹

遞歸遍歷

前序遍歷

基本思想:先訪問根結(jié)點(diǎn),再先序遍歷左子樹雨席,最后再先序遍歷右子樹即根—左—右菩咨。

public static void preRecDisplay(TreeNode node){
        //前序遍歷
        if (node!=null){
            System.out.println(node.data);
            preRecDisplay(node.leftNode);
            preRecDisplay(node.rightNode);
        }

    }

中序遍歷
基本思想:先中序遍歷左子樹,然后再訪問根結(jié)點(diǎn)陡厘,最后再中序遍歷右子樹即左—根—右旦委。

    public static void midRecDisplay(TreeNode node){
        //中序遍歷
        if (node!=null) {
            midRecDisplay(node.leftNode);
            System.out.println(node.data);
            midRecDisplay(node.rightNode);
        }
    }

后序遍歷
基本思想:先后序遍歷左子樹,然后再后序遍歷右子樹雏亚,最后再訪問根結(jié)點(diǎn)即左—右—根。

    public static void postRecDisplay(TreeNode node){
        //后序遍歷
        if (node!=null) {
            postRecDisplay(node.leftNode);
            postRecDisplay(node.rightNode);
            System.out.println(node.data);
        }
    }

    public static void main(String[] args){
        int datas[] = {1,2,3,4,5,6,7,8,9};
        Tree tree = new Tree(datas);
        postRecDisplay(tree.root);
    }

非遞歸遍歷

前序遍歷

對于任一結(jié)點(diǎn)p:

a. 訪問結(jié)點(diǎn)p摩钙,并將結(jié)點(diǎn)p入棧罢低;

b. 判斷結(jié)點(diǎn)p的左孩子是否為空,若為空胖笛,則取棧頂結(jié)點(diǎn)并進(jìn)行出棧操作网持,并將棧頂結(jié)點(diǎn)的右孩子置為當(dāng)前的結(jié)點(diǎn)p,循環(huán)置a长踊;若不為空功舀,則將p的左孩子置為當(dāng)前結(jié)點(diǎn)p;

c. 直到p為空身弊,并且棧為空辟汰,則遍歷結(jié)束列敲。

 public static void preDisplay(TreeNode node){
        //前序遍歷
        Stack<TreeNode> stack = new Stack<>();
        while (true){
            while (node!=null){
                //輸出就是遍歷的過程,前序遍歷先輸出當(dāng)前節(jié)點(diǎn)
                System.out.println(node.data);
                //最后輸出右節(jié)點(diǎn)帖汞,那就用stack來保存它
                stack.push(node);
                //當(dāng)前節(jié)點(diǎn)置為左節(jié)點(diǎn)戴而,下次循環(huán)就可以輸出左節(jié)點(diǎn)
                node=node.leftNode;
            }

            if (stack.isEmpty()){
                return;
            }
            //當(dāng)前節(jié)點(diǎn)置為右節(jié)點(diǎn)
            node = stack.pop().rightNode;
        }


    }

中序遍歷

根據(jù)中序遍歷的順序,對于任一結(jié)點(diǎn)翩蘸,優(yōu)先訪問其左孩子所意,而左孩子結(jié)點(diǎn)又可以看做一個根結(jié)點(diǎn),然后繼續(xù)訪問其左孩子結(jié)點(diǎn)催首,直到遇到左孩子結(jié)點(diǎn)為空的結(jié)點(diǎn)才停止訪問扶踊,然后按相同的規(guī)則訪問其右子樹。其處理過程如下:

對于任一結(jié)點(diǎn):

a. 若其左孩子不為空郎任,則將p入棧秧耗,并將p的左孩子設(shè)置為當(dāng)前的p,然后對當(dāng)前結(jié)點(diǎn)再進(jìn)行相同的操作涝滴;
b. 若其左孩子為空绣版,則取棧頂元素并進(jìn)行出棧操作,訪問該棧頂結(jié)點(diǎn)歼疮,然后將當(dāng)前的p置為棧頂結(jié)點(diǎn)的右孩子杂抽;
c. 直到p為空并且棧為空,則遍歷結(jié)束韩脏。

    public static void midDisplay(TreeNode node){
        //中序遍歷
        Stack<TreeNode> stack = new Stack<>();
        while (true){
            //循環(huán)截止說明當(dāng)前節(jié)點(diǎn)沒有左節(jié)點(diǎn)了
            while (node!=null){
                //需要先輸出左節(jié)點(diǎn)缩麸,只能講當(dāng)前節(jié)點(diǎn)入棧,暫時不輸出
                stack.push(node);
                //先輸出左節(jié)點(diǎn)
                node=node.leftNode;
            }

            if (stack.isEmpty()){
                return;
            }

            node = stack.pop();
            //當(dāng)前節(jié)點(diǎn)沒有左子樹了赡矢,該輪到它自己輸出了
            System.out.println(node.data);
            //輸出右子樹的過程
            node = node.rightNode;
        }
    }

后序遍歷

后序遍歷的非遞歸實(shí)現(xiàn)是三種遍歷方式中最難的一種杭朱。因為在后序遍歷中,要保證左孩子和右孩子都已被訪問吹散,并且左孩子在右孩子之前訪問才能訪問根結(jié)點(diǎn)弧械,這就為流程控制帶來了難題。

要保證根結(jié)點(diǎn)在左孩子和右孩子訪問之后才能訪問空民,因此對于任一結(jié)點(diǎn)p刃唐,先將其入棧。若p不存在左孩子和右孩子界轩,則可以直接訪問它画饥。當(dāng)前p節(jié)點(diǎn)為左子樹輸出一次,然后重復(fù)入棧過程浊猾,當(dāng)前節(jié)點(diǎn)p為右子樹,那么他的父節(jié)點(diǎn)就必定不能重復(fù)的將右子樹入棧抖甘。則之間循環(huán)輸出即可。
當(dāng)前節(jié)點(diǎn)p有右節(jié)點(diǎn) 葫慎,需要將右節(jié)點(diǎn)放到stack中衔彻,重復(fù)上述過程薇宠。

    public static void postListN(TreeNode node){
        //后序遍歷
        Stack<TreeNode> stack = new Stack<>();
        while (true){
            while (node!=null){
                //最后輸出當(dāng)前節(jié)點(diǎn),所有先入棧保存
                stack.push(node);
                node=node.leftNode;
            }
            if (stack.isEmpty()){
                return;
            }
            //當(dāng)前節(jié)點(diǎn)
            node = stack.lastElement();
            //在這里當(dāng)前節(jié)點(diǎn)有幾種情況
            //1.當(dāng)前節(jié)點(diǎn)沒有右節(jié)點(diǎn)米奸,需要輸出昼接,同時輸出也有幾種情況
                // (1 當(dāng)前節(jié)點(diǎn)為左子樹 輸出一次,然后重復(fù)入棧過程
                // (2 當(dāng)前節(jié)點(diǎn)為右子樹 當(dāng)前節(jié)點(diǎn)已經(jīng)為右子樹悴晰,輸出完畢慢睡,那么他的父節(jié)點(diǎn)就必定不能重復(fù)的將右子樹入棧
            //2.當(dāng)前節(jié)點(diǎn)有右節(jié)點(diǎn)  需要將右節(jié)點(diǎn)放到stack中
            //判斷當(dāng)前節(jié)點(diǎn)有沒有右節(jié)點(diǎn)
            if (node.rightNode==null){
                //沒右節(jié)點(diǎn)
                stack.pop();
                System.out.println(node.data);
                node = node.rightNode;
                //判斷當(dāng)前node是不是右分支
                while (stack.lastElement().rightNode==node){
                    //是右分支
                    TreeNode root = stack.pop();
                    System.out.println(root.data);
                    if (stack.isEmpty()){
                        break;
                    }
                }
            }
            //判斷棧是否為空
            if (!stack.isEmpty()){
                //將當(dāng)前節(jié)點(diǎn)置為右節(jié)點(diǎn)
                node=stack.lastElement().rightNode;
            }else{
                node=null;
            }
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铡溪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棕硫,老刑警劉巖髓涯,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哈扮,居然都是意外死亡纬纪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門滑肉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來包各,“玉大人,你說我怎么就攤上這事靶庙∥食” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵六荒,是天一觀的道長护姆。 經(jīng)常有香客問我,道長掏击,這世上最難降的妖魔是什么卵皂? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮砚亭,結(jié)果婚禮上渐裂,老公的妹妹穿的比我還像新娘。我一直安慰自己钠惩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布族阅。 她就那樣靜靜地躺著篓跛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坦刀。 梳的紋絲不亂的頭發(fā)上愧沟,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天蔬咬,我揣著相機(jī)與錄音,去河邊找鬼沐寺。 笑死林艘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的混坞。 我是一名探鬼主播狐援,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼究孕!你這毒婦竟也來了啥酱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤厨诸,失蹤者是張志新(化名)和其女友劉穎镶殷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體微酬,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绘趋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颗管。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陷遮。...
    茶點(diǎn)故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖忙上,靈堂內(nèi)的尸體忽然破棺而出拷呆,到底是詐尸還是另有隱情,我是刑警寧澤疫粥,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布茬斧,位于F島的核電站,受9級特大地震影響梗逮,放射性物質(zhì)發(fā)生泄漏项秉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一慷彤、第九天 我趴在偏房一處隱蔽的房頂上張望娄蔼。 院中可真熱鬧,春花似錦底哗、人聲如沸岁诉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涕癣。三九已至,卻和暖如春前标,著一層夾襖步出監(jiān)牢的瞬間坠韩,已是汗流浹背距潘。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留只搁,地道東北人音比。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像氢惋,于是被迫代替她去往敵國和親洞翩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評論 2 354

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