1127 ZigZagging on a Tree (30分)
Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences. And it is a simple standard routine to print the numbers in level-order. However, if you think the problem is too simple, then you are too naive. This time you are supposed to print the numbers in “zigzagging order” – that is, starting from the root, print the numbers level-by-level, alternating between left to right and right to left. For example, for the following tree you must output: 1 11 5 8 17 12 20 15.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the inorder sequence and the third line gives the postorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the zigzagging sequence of the tree in a line. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:
8
12 11 20 17 1 15 8 5
12 20 17 11 15 8 5 1
Sample Output:
1 11 5 8 17 12 20 15
本質就是中序 後序構造二叉樹,然後用隊列進行層序遍歷
主要考慮的有以下幾點
- 在遞歸構造的時候儘量保持少的參數,之前做過這個題,檢結果其他人的代碼,感覺參數少了比較不容易出錯,而且可以把需要的其他變量當場算出來,也方便調試,我就使用了num, 第一列數組的起始位置,第二列數組的起始位置,三個參數
- 在遞歸時候如何構造二叉樹,我是先判斷子樹的結點大於0,就先new一個結點當做子樹的根節點,然後把new的結點當做變量進行遞歸
中序後序確定二叉樹結構的過程應該是
- 先根據第二個數列(後序遍歷的數列)得到當前子樹的根節點
- 根據根節點的KEY 在數列1 中進行查找得到了根節點在數列1中的位置記爲rootPos
- 知道了當前子樹根節點的位置,也就知道了當前數列構成子樹誰在左子樹 誰在右子樹了
- 關鍵就是一些參數的操作,要小心點,很容易出錯
#include <iostream>
#include <algorithm>
using namespace std;
#include <vector>
#include <queue>
struct node
{
int data;
node* lchild,*rchild;
node():lchild(NULL),rchild(NULL) {}//所有new的node結點的左右孩子都是NULL
};
int N;
int sn1[40];
int sn2[40];
void df(node* root,int num,int s1LeftPos,int s2LeftPos)
{
int rootNumber=sn2[s2LeftPos+num-1];//根據後序遍歷確定根節點的數字
root->data=rootNumber;//找到了根節點的key,就把key賦值到我們傳入的根節點中
int rootPos=s1LeftPos;//查找該根節點數字在中序遍歷裏面的位置
while(sn1[rootPos]!=rootNumber)
rootPos++;
int leftNum=rootPos-s1LeftPos;//左子樹結點的個數
if(leftNum>0)
{
node *p=new node();
root->lchild=p;
df(p,leftNum,s1LeftPos,s2LeftPos);
}
int rightNum=num-leftNum-1;//減去1是因爲根節點的存在。這裏容易出錯,我上次寫就是這次出錯了
//寫成了num-rootPos-1; 哎 無奈
if(rightNum>0)
{
node *p=new node();
root->rchild=p;
df(p,rightNum,rootPos+1,s2LeftPos+leftNum);//這裏也容易出錯,
}
}
int main()
{
cin>>N;
for(int i=0; i<N; i++)
{
cin>>sn1[i];
}
for(int i=0; i<N; i++)
{
cin>>sn2[i];
}
node *root=new node();//先生成一個根節點,然後把結點傳入遞歸裏面
df(root,N,0,0);
queue<node*> que;
que.push(root);//構造隊列用於層序遍歷
cout<<root->data;
int leftToRight=1;
while(!que.empty())
{
queue<node*> get;
vector<int> vec;
while(!que.empty())
{
node *p=que.front();
int data=p->data;
if(p->lchild!=NULL)
{
get.push(p->lchild);
vec.push_back(p->lchild->data);
}
if(p->rchild!=NULL)
{
get.push(p->rchild);
vec.push_back(p->rchild->data);
}
que.pop();
}
if(leftToRight==1){
for(int i=0; i<vec.size(); i++)
{
cout<<' '<<vec[i];
}
leftToRight=0;
}
else{
for(int i=vec.size()-1; i>=0;i--)
{
cout<<' '<<vec[i];
}
leftToRight=1;
}
que=get;
}
return 0;
}