資料結構——3.3 二叉樹的遍歷及樹的同構
一、二叉樹的遍歷
1、先序遍歷
遍歷過程為:
1)訪問根結點
2)先序遍歷其左子樹
3)先序遍歷其右子樹
這樣的一種遍歷過程,其實也是一種遞迴的思想。
A(BDFE)(CGHI),先序遍歷=> ABDFECGHI
2、中序遍歷
遍歷過程為:
1)中序遍歷其左子樹
2)訪問根結點
3)中序遍歷其右子樹
對根結點A來講,BDFE是左邊,CGIH是右邊,所以中序遍歷的整個過程是先要把左邊的給print出來,然後再print根結點A,最後print右邊。而print左邊的時候,也是同樣的規則,先print左邊的,再print右邊的
(DBEF)A(GHCI)中序遍歷=> DBEF A GHCI
3、後序遍歷
遍歷過程為:
1)中序遍歷其左子樹
2)中序遍歷其右子樹
3)訪問根結點
對根結點A來講,BDFE是左子樹,CGIH是右子樹,所以先把左子樹遍歷完,然後遍歷右子樹,最後輸出根結點。B的左邊遍歷完了,然後遍歷B的右邊,又繼續,最後輸出左子樹的根結點B
(DEFB)(HGIC)A,後序遍歷=>DEFBHGICA
總結
1)先序、中序和後序遍歷過程:遍歷過程中經過結點的路線一樣,只是訪問各個結點的時機不同
2)圖中在從入口到出口的曲線上用×,※和△三種符號分別標記出了先序、中序和後序遍歷訪問各結點的時刻,每個結點都有三次碰到它的機會,第一次碰到的時候就叫先序,第二次碰到並輸出就叫中序,第三次碰到就叫後序遍歷。
二、二叉樹的非遞迴遍歷
遞迴的根本方法其實用的是遞迴。
1、中序遍歷的非遞迴遍歷演算法
基本思路:使用堆疊
1)遇到一個結點,就把它壓棧,並去遍歷它的左子樹
2)當左子樹遍歷結束後,從棧頂彈出這個結點並訪問它
3)然後按其右指標再去中序遍歷該結點的右子樹
2、先序遍歷的非遞迴遍歷演算法
3、後序遍歷的非遞迴遍歷演算法
https://www.cnblogs.com/SHERO-Vae/p/5800363.html
總結的很好。其實二叉樹遍歷的核心問題,就是二維結構的線性化,即產生一個序列,而這個序列是一維的線性結構
4、層序遍歷
佇列實現
遍歷從根結點開始,首先將根結點入隊
得到的序列有這樣的特徵:**它是一層一層訪問的,先是A,然後是BC,然後再到下一層
步驟
1)從佇列中取出一個元素
2)訪問該元素所指結點
3)若該元素所指結點的左右孩子結點非空,則將其左右孩子的指標順序入隊
三、遍歷二叉樹的應用
1、輸出二叉樹中的葉子結點
可以在二叉樹的遍歷演算法中增加檢測結點的“左右子樹是否都為空”這一條件
2、求二叉樹的高度
思路:求左右子樹的最大高度,然後加1
3、二元運算表示式樹及其遍歷
表示式樹:葉結點代表運算數,非葉結點是運算子號。如下面的是想把A的左子樹和右子樹加起來
三種遍歷可以得到三種不同的訪問結果:
先序遍歷:++a*bc*+*defg
中序遍歷:a+b*c+d*e+f*g
後序遍歷:abc*+de*f+g*+
先序遍歷對應字首表示式,
中序遍歷對應中綴表示式(會受到運算子優先順序的影響),那怎麼解決呢?答案是當你輸出左子樹的時候,先輸出一個左括號,左子樹結束的時候,加一個右括號。
字尾遍歷對應字尾表示式。
4、由兩種遍歷序列確定二叉樹
特殊地:由前序和後序遍歷 ,不能唯一地確定一棵二叉樹,一定要有中序遍歷才可以。舉例:
先序和中序遍歷序列確定一棵二叉樹
1)根據先序遍歷序列第一個結點確定**根結點
2)根據根結點在中序遍歷序列中分割出左右兩個子序列
3)對左子樹和右子樹分別遞迴使用相同的方法繼續分解
四、樹的同構
給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。現給定兩棵樹,判斷它們是否同構。
求解思路
1、二叉樹表示
1)方式1:連結串列表示
2)方式2:陣列表示(把一般二叉樹變成完全二叉樹)
3)方式3:結構陣列表示(靜態連結串列)
看A,出現了1,看B,出現了2和3。那麼說明0沒有出現,所以A是根結點
2、程式框架搭建
1)如何建二叉樹
找根結點的方法:
把每個結點遍歷一遍,看有沒有哪個結點不存在其他結點指向它
2)如何判別兩個二叉樹是同構的