先序中序后序两两结合重建二叉树
遍歷是對(duì)樹(shù)的一種最基本的運(yùn)算,所謂遍歷二叉樹(shù),就是按一定的規(guī)則和順序走遍二叉樹(shù)的所有結(jié)點(diǎn),使每一個(gè)結(jié)點(diǎn)都被訪問(wèn)一次,而且只被訪問(wèn)一次。由于二叉樹(shù)是非線性結(jié)構(gòu),因此,樹(shù)的遍歷實(shí)質(zhì)上是將二叉樹(shù)的各個(gè)結(jié)點(diǎn)轉(zhuǎn)換成為一個(gè)線性序列來(lái)表示。
設(shè)L、D、R分別表示遍歷左子樹(shù)、訪問(wèn)根結(jié)點(diǎn)和遍歷右子樹(shù), 則對(duì)一棵二叉樹(shù)的遍歷有三種情況:DLR(稱(chēng)為先根次序遍歷),LDR(稱(chēng)為中根次序遍歷),LRD (稱(chēng)為后根次序遍歷)。
先序遍歷
首先訪問(wèn)根,再先序遍歷左(右)子樹(shù),最后先序遍歷右(左)子樹(shù),C語(yǔ)言代碼如下:
| 1 2 3 4 5 6 7 | void?XXBL(tree?*root){ ????//DoSomethingwithroot ????if(root->lchild!=NULL) ????????XXBL(root->lchild); ????if(root->rchild!=NULL) ????????XXBL(root->rchild); } |
中序遍歷
首先中序遍歷左(右)子樹(shù),再訪問(wèn)根,最后中序遍歷右(左)子樹(shù),C語(yǔ)言代碼如下
| 1 2 3 4 5 6 7 8 | void?ZXBL(tree?*root) { ????if(root->lchild!=NULL) ????????ZXBL(root->lchild); ????????//Do?something?with?root ????if(root->rchild!=NULL) ????????ZXBL(root->rchild); } |
后序遍歷
首先后序遍歷左(右)子樹(shù),再后序遍歷右(左)子樹(shù),最后訪問(wèn)根,C語(yǔ)言代碼如下
| 1 2 3 4 5 6 7 | void?HXBL(tree?*root){ ????if(root->lchild!=NULL) ????????HXBL(root->lchild); ????if(root->rchild!=NULL) ????????HXBL(root->rchild); ????????//Do?something?with?root } |
層次遍歷
即按照層次訪問(wèn),通常用隊(duì)列來(lái)做。訪問(wèn)根,訪問(wèn)子女,再訪問(wèn)子女的子女(越往后的層次越低)(兩個(gè)子女的級(jí)別相同)
?
輸入某二叉樹(shù)的前序遍歷和中序遍歷的結(jié)果,請(qǐng)重建出該二叉樹(shù)。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹(shù)并返回。
?
我們首先找到根結(jié)點(diǎn):一定是先序遍歷序列的第一個(gè)元素:1
然后,在中序序列尋找根,把中序序列分為兩個(gè)序列左子樹(shù)4,7,2和右子樹(shù)5,3,8,6
把先序序列也分為兩個(gè):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?左子樹(shù)2,4,7和右子樹(shù)3,5,6,8
對(duì)左右重復(fù)同樣的過(guò)程:
先看左子樹(shù):先序序列4,7,2,說(shuō)明4一定是左子樹(shù)的根
把2,4,7分為2和7兩個(gè)序列,再重復(fù)過(guò)程,左邊確定完畢。
右子樹(shù)同樣:中序序列為5,3,8,6,先序序列為:3,5,6,8
取先序頭,3.一定是根
把中序序列分為? ? ?5和8,6兩個(gè)序列
對(duì)應(yīng)的先序序列為 5和6,8兩個(gè)序列
?
然后確定了5是3的左孩子
對(duì)于先序序列6,8和中序序列8,6
還是先取先序的頭,6
?
現(xiàn)在只有8,中序序列8在左邊,是左孩子。
結(jié)束。
我們總結(jié)一下這種方法的過(guò)程:
1、根據(jù)先序序列確定當(dāng)前樹(shù)的根(第一個(gè)元素)。
2、在中序序列中找到根,并以根為分界分為兩個(gè)序列。
3、這樣,確定了左子樹(shù)元素個(gè)數(shù),把先序序列也分為兩個(gè)。
對(duì)左右子樹(shù)(對(duì)應(yīng)的序列)重復(fù)相同的過(guò)程。
?
我們把思路用代碼實(shí)現(xiàn):
# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution:# 返回構(gòu)造的TreeNode根節(jié)點(diǎn)def reConstructBinaryTree(self, pre, tin):# write code here/#pre-先序數(shù)組 tin->中序數(shù)組if len(pre) == 0:return Noneroot = TreeNode(pre[0])//第一個(gè)元素為根pos = tin.index(pre[0])//劃分左右子樹(shù)root.left = self.reConstructBinaryTree( pre[1:1+pos], tin[:pos])root.right = self.reConstructBinaryTree( pre[pos+1:], tin[pos+1:])return root輸入某二叉樹(shù)的后序遍歷和中序遍歷的結(jié)果,請(qǐng)重建出該二叉樹(shù)。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字
?
思路是類(lèi)似的,只是我們確定根的時(shí)候,取后序序列的最后一個(gè)元素即可。
?
輸入某二叉樹(shù)的后序遍歷和先序遍歷的結(jié)果,請(qǐng)重建出該二叉樹(shù)。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字
?
我們直白的表述一下,前序是中左右,后序是左右中。
所以,我們憑先序和后序序列其實(shí)是無(wú)法判斷根的孩子到底是左孩子還是右孩子。
比如先序序列1,5,后序序列是5,1
我們只知道1是這棵樹(shù)的根,但是我們不知道5是1的左孩子還是右孩子。
我們的中序序列是左中右,才可以明確的劃分出左右子樹(shù),而先序后序不可以。
?
綜上,只有,只含葉子結(jié)點(diǎn)或者同時(shí)有左右孩子的結(jié)點(diǎn)的樹(shù),才可以被先序序列后序序列確定唯一一棵樹(shù)。
最后不斷劃分先序和后序序列完成重建。
總結(jié)
以上是生活随笔為你收集整理的先序中序后序两两结合重建二叉树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 215. 数组中的第K个最大元素 BFP
- 下一篇: ffmpeg优化mp4以及hls参数设置