1. 程式人生 > >分別根據前中序遍歷和後中序遍歷來推二叉樹的結構

分別根據前中序遍歷和後中序遍歷來推二叉樹的結構

1、理論分析:

資料結構的基礎知識中重要的一點就是能否根據兩種不同遍歷序列的組合(有三種:先序+中序,先序+後序,中序+後序),唯一的確定一棵二叉樹。然後就是根據二叉樹的不同遍歷序列(先序、中序、後序),重構二叉樹。顯然,這三種組合並不是都能唯一確定二叉樹的,其中先序+後序就不能唯一確定一棵二叉樹。這裡我就不證明了。舉個反例:

反例:任何結點只有左子樹的二叉樹和任何結點只有右子樹的二叉樹,其前序序列相同,後序序列相同,但卻是兩棵不同的二叉樹。


2、構造思路:


(1)根據先序遍歷序列和中序遍歷序列構建二叉樹:
先序:ABCDEFG

中序:CBEDFAG

step1、先序遍歷的第一個結點總是根結點。如上圖中的二叉樹,根結點為A,也是先序遍歷的第一個值。先序遍歷時父親結點總是在孩子結點之前遍歷。

step2、可以觀察到在中序遍歷中,A是第5個值(從0開始算起)。由於中序遍歷順序為:左子樹,根結點,右子樹。所以A左邊的{CBEDF} 這四個結點屬於左子樹,而根結點A右邊的{G}屬於右子樹。

step3、可以從上面的結論很輕鬆的得到遞迴式。在構建了根結點A後,我們可以根據中序遍歷{CBEDF} 和{G}分別構建它的左子樹和右子樹。我們同時需要相應的先序遍歷結果用於發現規律。我們可以由先序遍歷知道左右子樹的先序遍歷分別是{CBEDF}和{G}。左右子樹也分別為二叉樹,由此可以遞迴來解決問題。

補充進我之前寫的二叉樹類中(class BinTree)

int Creat_VLR_LVR(T VLR[],T LVR[],int len)
	{
		return Creat_VLR_LVR(root,VLR,VLR+len-1,LVR,LVR+len-1);
	}
//VLR:根左右---------------前序遍歷
	//LVR:左根右---------------中序遍歷
	int Creat_VLR_LVR(BinTreeNode<T> *&p,T *VLRh,T *VLRt,T *LVRh,T *LVRt)//////////////////////////////////////////////////////////////////////
	{
		T *valuepre = VLRh;//先取出前序遍歷的第一個值來作為根節點
		T *valuein = LVRh;   //去中序陣列的指標
		p = new BinTreeNode<T>((*valuepre));
		if(*VLRh == *VLRt||*LVRh == *LVRt)
		{
			return OK;
		}
		if(*valuepre == '\0'&&*valuein == '\0')
		{
			return OK;
		}
		while((*valuein) != '\0'&& (*valuein) != *valuepre)
			++valuein;
		int leftlen = valuein - LVRh;
		T *leftVLR = VLRh + leftlen;
		if(leftlen > 0)
		{
			Creat_VLR_LVR(p->left,VLRh+1,VLRt,LVRh,valuein-1);
		}
		if(leftlen < VLRt-VLRh)
		{
			Creat_VLR_LVR(p->right,leftVLR+1,VLRt,valuein+1,LVRt);
		}
		return OK;
	}

(2)根後序遍歷序列和中序遍歷序列構建二叉樹:
後序:CEFDBGA

中序:CBEDFAG

step1、後序遍歷的最後一個結點總是“根結點”。如上圖中的二叉樹,根結點為A,也是後序遍歷的最後一個值。

step2、在中序遍歷中找到“根節點”,但是這裡要先建立右子樹,因為後序遍歷後面的是右子樹的根節點,(這裡唯一跟前序遍歷不一樣的是後序遍歷是從後往前一個一個退的)。從中序遍歷中我們可以看到{G}是A的右子樹,所以先建立。

step3、後序遍歷再往前退,到B,那麼B是A的左子樹......

根據以上的結論,通過遞迴好實現的。

	int Creat_LRV_LVR(T LRV[],T LVR[],int len)
	{
		return Creat_LRV_LVR(root,LRV,LRV+len-1,LVR,LVR+len-1);
	}
	//LRV:左右根---------------後序遍歷
	//LVR:左根右---------------中序遍歷
	int Creat_LRV_LVR(BinTreeNode<T> *&p,T *LRVh,T *LRVt,T *LVRh,T *LVRt)
	{
		T *valuepost = LRVt;
		T *valuein = LVRh;
		p = new BinTreeNode<T>((*valuepost));
		if(*LRVh == *LRVt||*LVRh == *LVRt)
			return OK;
		if(*valuein == '\0')
			return OK;
		while((*valuein) != '\0'&& (*valuein) != *valuepost)
			++valuein;
		int rightlen = LVRt-valuein; //中序遍歷右子樹的長度
		T *rightLRV = LRVt - rightlen;//後序遍歷
		if(rightlen > 0)
		{
			Creat_LRV_LVR(p->right,LRVh,LRVt-1,valuein+1,LVRt);//除錯的時候要注意看好這裡的引數
		}
		if(rightlen < LRVt-LRVh)
		{
			Creat_LRV_LVR(p->left,LRVh,LRVt-rightlen-1,LVRh,valuein-1);//除錯的時候要注意看好這裡的引數
		}
		return OK;
	}







相關推薦

分別根據歷來結構

1、理論分析: 資料結構的基礎知識中重要的一點就是能否根據兩種不同遍歷序列的組合(有三種:先序+中序,先序+後序,中序+後序),唯一的確定一棵二叉樹。然後就是根據二叉樹的不同遍歷序列(先序、中序、後序

輸入某的結果,請重建出該(java實現並測試)

假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 package ssp; class TreeNode { int val; TreeNod

輸入某的結果,請重建出該。假設輸入的的結果都不含重複的數字。例如輸入序列{1,2,4,7,3,5,6,8}序列{4,7,2,1,5

思路:前序遍歷的第一個元素就是根節點,在中序遍歷中找到根節點的位置,根節點前面的元素就二叉樹的左子樹,根節點後面的元素就是二叉樹中的右子樹,在找出左子樹和右子樹的前序遍歷和中序遍歷,然後遞迴呼叫,再找根節點和左子樹、右子樹  /** * Definition for bi

n個節點能夠形成的所有

幫師兄做的一個問題,就是求對n個不同節點能夠形成所有的二叉樹的形式,不考慮旋轉對稱性和同構。 問題描述:給定n個節點,檢視能夠有多少種不同的二叉樹形成,並輸出出來 演算法描述:使用最基本的“分治法“(Divide and Conquer)思想,任選一個節點作為根節點,將剩餘

什麼是? 四種是什麼? 2.遞迴的實現

自從livecoding.tv上線以來,我們很開心看到越來越多直播者加入我們的平臺。為了肯定大家對我們網站的支援和貢獻,我們將從十月份開始,每個月評選出在直播上具有最出色表現的直播者一名,並會送出精美禮品。此外,我們還會在電子信中向我們的訂閱讀者介紹獲獎者。 如果你想成為“

根據構造

eno build 中序遍歷樹 oot post rsa uil cnblogs 找到 根據中序遍歷和後序遍歷樹構造二叉樹 樣例: 給出樹的中序遍歷: [1,2,3] 和後序遍歷: [1,3,2] 返回如下的樹: 2 / \ 1 3 借鑒上一篇《前序遍歷和中序遍

數據結構35:

tdi 代碼 nod 完成 循環 同時 reat pan 設置 遞歸算法底層的實現使用的是棧存儲結構,所以可以直接使用棧寫出相應的非遞歸算法。 先序遍歷的非遞歸算法 從樹的根結點出發,遍歷左孩子的同時,先將每個結點的右孩子壓棧。當遇到結點沒有左孩子的時候,取棧頂的右

線索的建立、線索化

線索二叉樹的概念 線索二叉樹的原理:線索二叉樹是將普通二叉樹左右孩子中的空鏈域利用起來,將左孩子空鏈域指向當前節點的線性遍歷前驅,將右孩子空鏈域指向當前節點的線性遍歷後繼,指向該線性序列中的前驅或後繼

java編寫以及

/** * 實現二叉樹的建立、前序遍歷、中序遍歷和後序遍歷 **/ package DataStructure; /** * Copyright 2014 by Ruiqin Sun * All right reserved * created on 2014

根據重建

二叉樹的重建 二叉樹的重建方法: 一、根據前序加中序遍歷重建二叉樹 構造該二叉樹的過程如下: 1. 根據前序序列的第一個元素建立根結點; 2. 在中序序列中找到該元素,確定根結點的左右子樹的中序序列;

(python實現)

# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # sel

二叉樹 com size 基本 html 後序 href col spa 轉自:https://www.cnblogs.com/polly333/p/4740355.html 基本思想>>   先序遍歷:根——>左——>右   先序遍歷:左——>

72 構造

實的 dong scrip size turn -c -h red 左右子樹 原題網址:https://www.lintcode.com/problem/construct-binary-tree-from-inorder-and-postorder-traversal/d

求類層

PTA-ZigZagging on a Tree (25 分) Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determin

根據或者來確定結構(附例題)

根據中序和前序後序中的任意一種結構就可以確定二叉樹的結構。 因為中序是按照左中右的順序來遍歷的。而前序是按照中左右的順序來確定的,我們可以通過按照前序順序來構建二叉樹,通過中序來確定二叉樹的左子樹和右子樹。後序和中序組合也是這樣,只不過後序需要從後面開始找。 這裡給出兩個例題: 1.前序

之先

例圖:                   1.先序遍歷   先序遍歷也叫做先跟遍歷、前序遍歷。先序遍歷步驟為:訪問根結點然後遍歷左子樹,最後遍歷右子樹。在遍歷左、右子樹時,仍然先訪問根結點,然後遍歷左子樹,最後遍歷右子樹。即根左右。   如上圖1,先序遍歷的序列為:

已知或者結構的演算法

二叉樹中的前序遍歷是先訪問根結點,再訪問左子樹,右子樹。 中序遍歷是先訪問左子樹,再是根結點,最後是右子樹。 後序遍歷是先訪問左子樹,再是右子樹,最後是根結點。 演算法思路是先根據前序遍歷的第一個結點或者後序遍歷的最後一個結點,查詢對應在中序遍歷中的位置,就可以確定左子樹包

LintCode(72)構造

題目  中序遍歷和後序遍歷樹構造二叉樹 根據中序遍歷和後序遍歷樹構造二叉樹 樣例 給出樹的中序遍歷: [1,2,3] 和後序遍歷: [1,3,2] 返回如下的樹:   2  /  

為什麼不能唯一地確定一棵

以前大學學資料結果的時候,我們就知道,根據一棵樹的先序遍歷和中序遍歷,或者後序遍歷和中序遍歷序列,都可以唯一地確定一棵樹。 樹中的節點,分為度為0,1,2的結點。如果樹中只有一個節點,那麼可以唯一確定一棵樹,即只有一個節點的樹。 當樹中結點個數大於等於2的情況,樹中的

jsjquery

1.map() 方法返回一個由原陣列中的每個元素呼叫一個指定方法後的返回值組成的新陣列。 使用例項: var ary = [12,23,24,42,1]; var res = ary.map(function (item,index,input) { retur