1. 程式人生 > >【天梯賽】L2-006. 樹的遍歷(層次遍歷)

【天梯賽】L2-006. 樹的遍歷(層次遍歷)

題目描述:

給定一棵二叉樹的後序遍歷和中序遍歷,請你輸出其層序遍歷的序列。這裡假設鍵值都是互不相等的正整數。

輸入格式:

輸入第一行給出一個正整數N(<=30),是二叉樹中結點的個數。第二行給出其後序遍歷序列。第三行給出其中序遍歷序列。數字間以空格分隔。

輸出格式:

在一行中輸出該樹的層序遍歷的序列。數字間以1個空格分隔,行首尾不得有多餘空格。

輸入樣例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
輸出樣例:
4 1 6 3 5 7 2

題目思路:

如果題目說,給出後序遍歷和中序遍歷,求先序遍歷,那麼你一定會做(如果不會做,可以先學會如何通過中序+後序,求先序,然後再來學習本題)。現在題目的前提條件不變,但是求的是層次遍歷。當然你可以通過後序和中序建樹,然後用BFS輸出層次遍歷的結果。這裡我採用的是在遞迴函式中新增一個引數index來表示當前遞迴層次中根節點應該在樹中的座標(層次遍歷的座標)。

題目中給出的資料的二叉樹如圖所示。

遞迴的過程如圖所示:


我們可以看出每次遞迴左子樹的時候,左子樹的根節點在層次遍歷中的座標是2*index+1,(我們假設左子樹根節點的父親結點的座標是index。如:圖中權值為1的結點和權值為4的結點的關係)。同理右子樹在層次遍歷中的座標是2*index+2。因此我們可以新開闢一個數組在遞迴的過程中,每個結點在層次遍歷中的位置,最後輸出該陣列即可。需要注意的是,如果二叉樹的結點有n個,那麼最多有n層,最少有log2(n+1)層,因此陣列最大需要開2^30-1個。如果給定7個結點,那麼他最多有七層,顯示,我們在輸出心宣告的陣列的時候,不能只輸出前7個的值,因為最後一個結點的座標是2^7-2。

題目程式碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 10000
using namespace std;

int s1[MAXN], s2[MAXN], s3[MAXN];
int n;
/*
	p1 p2 q1 a2 表示兩種遍歷結果的起始位置
	index表示當前根節點在二叉樹中的位置(層次遍歷) 
*/
void f(int p1, int p2, int q1, int q2, int index)
{
	if(p1>p2 || q1>q2) return ;
	
	int i = p1 ;
	while(s1[i] != s2[q2]) i++;
	s3[index] = s1[i];
	//left
	f(p1, i-1, q1, q1+i-1-p1, 2*index+1);
	//right
 	f(i+1, p2, q1+i-p1, q2-1, 2*index+2);
	
}

int main()
{
	cin>>n;
	for(int i=0; i<n; i++) cin>>s2[i];
	for(int i=0; i<n; i++) cin>>s1[i];
	memset(s3,0,sizeof(s3));
	f(0, n-1, 0, n-1, 0);
	//cnt用來記錄有效數字的個數 
	int cnt = 0; 
	for(int i=0; i<=100000; i++) {
		if(cnt==n)break;
		if(s3[i]){
			cnt++;
			if(i)cout<<" ";
			cout<<s3[i];
		}
	}
	return 0;
}