PAT甲級1127 ZigZagging on a Tree (30分) 中序 後序構造二叉樹,之前就寫錯過,這次又寫錯了。。。。*******

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.

zigzag.jpg

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的結點當做變量進行遞歸

中序後序確定二叉樹結構的過程應該是

  1. 先根據第二個數列(後序遍歷的數列)得到當前子樹的根節點
  2. 根據根節點的KEY 在數列1 中進行查找得到了根節點在數列1中的位置記爲rootPos
  3. 知道了當前子樹根節點的位置,也就知道了當前數列構成子樹誰在左子樹 誰在右子樹了
  4. 關鍵就是一些參數的操作,要小心點,很容易出錯
#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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章