推斷二叉樹(進階)

某朝發表於2024-10-18

Description

給出一棵二叉樹的中序遍歷和每個節點的父節點,求這棵二叉樹的先序和後 序遍歷。

Input

輸入第一行為一個正整數 n 表示二叉樹的節點數目, 節點編號從 1 到 n,其中 1 為根節點。
第 2 行有 n 個數字, 第 i 個數字表示 i 的父親節點。( 1 的父親節點為 0, 表示無)
第 3 行為中序遍歷。
30%的資料: n<=20;
60%的資料: n<=1000;
100%的資料: n<=10000;

Output

輸出 2 行, 第一行為先序遍歷,第二行為後序遍歷。

Sample Input

10
0 7 2 2 9 1 8 1 6 8
9 5 6 1 10 8 7 3 2 4

Sample Output

1 6 9 5 8 10 7 2 3 4
5 9 6 10 3 4 2 7 8 1

思路

存下每個節點的左右兒子,然後根據中序遍歷判斷誰是左兒子,誰是右兒子,建完樹,跑一下先序遍歷和後序遍歷

#include<iostream>
using namespace std;
const int N = 10010;
int lson[N], rson[N];//存結點x的左右兒子
int last[N];

void PreOrder(int x)
{
	//題目給定1為根
	if (x != 1) cout << " ";
	cout << x;
	if (lson[x]) PreOrder(lson[x]);
	if (rson[x])PreOrder(rson[x]);
}

bool flag = true;
void PostOrder(int x)
{
	if (lson[x]) PostOrder(lson[x]);
	if (rson[x])PostOrder(rson[x]);
	if (flag) cout << x;
	else cout<<" " << x;

	flag = false;
}


int main() {
	int n;
	cin >> n;
	int tmp;
	//先預設存左,左存了就存右
	for (int i = 1; i <= n; i++)
	{	
		cin >> tmp;
		if (!tmp)continue;
		if (!lson[tmp]) lson[tmp] = i;
		else rson[tmp] = i;
	}

	//last存tmp出現的先後,i表示先後
	for (int i = 1; i <= n; i++)
	{
		cin >> tmp;
		last[tmp] = i;
	}

	for (int i = 1; i <= n; i++)
	{
		if (lson[i] && rson[i])
		{
			//左根右
			if (last[rson[i]] < last[lson[i]])
			{
				swap(lson[i], rson[i]);
			}
		}
		//左根右 如果rson[i](只是個值)在根前, 那就是右兒子
		else if (!lson[i] && rson[i])
		{
			if (last[rson[i]] < last[i])
			{
				lson[i] = rson[i];
				rson[i] = 0;
			}
		}
		else if (lson[i] && !rson[i])
		{
			if (last[lson[i]] > last[i])
			{
				rson[i] = lson[i];
				lson[i] = 0;
			}
		}
	}

	PreOrder(1); cout << endl;
	PostOrder(1); cout << endl;

}

相關文章