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