先序中序数组推后序数组
二叉樹遍歷
所謂遍歷(Traversal)是指沿著某條搜索路線,依次對樹中每個結點均做一次且僅做一次訪問。訪問結點所做的操作依賴于具體的應用問 題。 遍歷是二叉樹上最重要的運算之一,是二叉樹上進行其它運算之基礎。
?
從二叉樹的遞歸定義可知,一棵非空的二叉樹由根結點及左、右子樹這三個基本部分組成。因此,在任一給定結點上,可以按某種次序執行三個操作:
⑴訪問結點本身(N),
⑵遍歷該結點的左子樹(L),
⑶遍歷該結點的右子樹(R)。
以上三種操作有六種執行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
注意:
前三種次序與后三種次序對稱,故只討論先左后右的前三種次序。
遍歷命名
根據訪問結點操作發生位置命名:
① NLR:前序遍歷(Preorder Traversal 亦稱(先序遍歷))
——訪問根結點的操作發生在遍歷其左右子樹之前。
② LNR:中序遍歷(Inorder Traversal)
——訪問根結點的操作發生在遍歷其左右子樹之中(間)。
③ LRN:后序遍歷(Postorder Traversal)
——訪問根結點的操作發生在遍歷其左右子樹之后。
注意:
由于被訪問的結點必是某子樹的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解釋為根、根的左子樹和根的右子樹。NLR、LNR和LRN分別又稱為先根遍歷、中根遍歷和后根遍歷。
?
給出某棵樹的先序遍歷結果和中序遍歷結果(無重復值),求后序遍歷結果。
比如
先序序列為:1,2,4,5,3,6,7,8,9
中序序列為:4,2,5,1,6,3,7,9,8
方法1:我們可以重建整棵樹:
https://blog.csdn.net/hebtu666/article/details/84322113
建議好好看這個網址,對理解這個方法有幫助。
?
如圖
然后后序遍歷得出后序序列。
?
方法2:我們可以不用重建,直接得出:
過程:
1)根據當前先序數組,設置后序數組最右邊的值
2)劃分出左子樹的先序、中序數組和右子樹的先序、中序數組
3)對右子樹重復同樣的過程
4)對左子樹重復同樣的過程
?
原因:我們的后序遍歷是左右中的,也就是先左子樹,再右子樹,再根
舉個例子:
比如這是待填充序列:
我們確定了根,并且根據根和中序序列劃分出了左右子樹,黃色部分為左子樹:
:
先處理右子樹(其實左右中反過來就是中右左,順著填就好了):
我們又確定了右子樹的右子樹為黑色區域,然后接著填右子樹的右子樹的根(N)即可。
?
?
舉例說明:
a[]先序序列為:1,2,4,5,3,6,7,8,9
b[]中序序列為:4,2,5,1,6,3,7,9,8
c[]后序序列為:0,0,0,0,0,0,0,0,0(0代表未確定)
我們根據先序序列,知道根一定是1,所以后序序列:0,0,0,0,0,0,0,0,1
從b[]中找到1,并劃分數組:
? ? ? ? ? 左子樹的先序:2,4,5,
? ? ? ? ? 中序:4,2,5
? ? ? ? ? 右子樹的先序:3,6,7,8,9,
? ? ? ? ? 中序:6,3,7,9,8
?
我們繼續對右子樹重復相同的過程:
(圖示為當前操作的樹,我們是不知道這棵樹的樣子的,我是為了方便敘述,圖片表達一下當前處理的位置)
當前樹的根一定為先序序列的第一個元素,3,所以我們知道后序序列:0,0,0,0,0,0,0,3,1
我們繼續對左右子樹進行劃分,中序序列為6,3,7,9,8,我們在序列中找到2,并劃分為左右子樹:
左子樹:
先序序列:6
中序序列:6
右子樹:
先序序列:7,8,9
中序序列:7,9,8
我們繼續對右子樹重復相同的過程,也就是如圖所示的這棵樹:
現在我們的后序序列為0,0,0,0,0,0,0,3,1
這時我們繼續取當前的根(先序第一個元素)放在下一個后序位置:0,0,0,0,0,0,7,3,1
劃分左右子樹:
左子樹:空,也就是它
右子樹:先序8,9,中序9,8,也就是這個樹
我們繼續處理右子樹:先序序列為8,9,所以根為8,我們繼續填后序數組0,0,0,0,0,8,7,3,1
然后劃分左右子樹:
左子樹:先序:9,中序:9
右子樹:空
對于左子樹,一樣,我們取頭填后序數組0,0,0,0,9,8,7,3,1,然后發現左右子樹都為空.
我們就把這個小框框處理完了
然后這棵樹的右子樹就處理完了,處理左子樹,發現為空。這棵樹也處理完了。
這一堆就完了。我們處理以3為根的二叉樹的左子樹。繼續填后序數組:
0,0,0,6,9,8,7,3,1
整棵樹的右子樹處理完了,左子樹同樣重復這個過程。
最后4,5,2,6,9,8,7,3,1
?
好累啊。。。。。。挺簡單個事寫了這么多。
回憶一下過程:
1)根據當前先序數組,設置后序數組最右邊的值
2)劃分出左子樹的先序、中序數組和右子樹的先序、中序數組
3)對右子樹重復同樣的過程
4)對左子樹重復同樣的過程
就這么簡單
?
先填右子樹是為了數組連續填充,容易理解,先處理左子樹也可以。
最后放上代碼吧
a=[1,2,4,5,3,6,7,8,9] b=[4,2,5,1,6,3,7,9,8] l=[0,0,0,0,0,0,0,0,0]def f(pre,tin,x,y):#x,y為樹在后序數組中對應的范圍if pre==[]:returnl[y]=pre[0]#根pos=tin.index(pre[0])#左子樹元素個數f(pre[pos+1:],tin[pos+1:],x+pos,y-1)#處理右子樹f(pre[1:pos+1],tin[:pos],x,x+pos-1)#處理左子樹f(a,b,0,len(l)-1) print(l)?
總結
以上是生活随笔為你收集整理的先序中序数组推后序数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java编程规约(OOP)
- 下一篇: Map集合知识点(炸窝)