zoukankan      html  css  js  c++  java
  • PAT Advanced 1102 Invert a Binary Tree (25) [树的遍历]

    题目

    The following is from Max Howell @twitter:
    Google: 90% of our engineers use the sofware you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck of. Now it’s your turn to prove that YOU CAN invert a binary tree!
    Input Specification:
    Each input file contains one test case. For each case, the first line gives a positive integer N (<=10) which is the total number of nodes in the tree — and hence the nodes are numbered from 0 to N-1. Then N lines follow, each corresponds to a node from 0 to N-1, and gives the indices of the lef and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.
    Output Specification:
    For each test case, print in the first line the level-order, and then in the second line the in-order traversal sequences of the inverted tree. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.
    Sample Input:
    8
    1 –
    – –
    0 –
    2 7
    – –
    – –
    5 –
    4 6
    Sample Output:
    3 7 2 6 4 0 5 1
    6 5 7 4 3 2 0 1

    题目分析

    已知所有节点的左右子节点,求反转二叉树的中序和后序序列

    解题思路

    思路 01

    1. 输入时,将左右子节点对换,即可完成反转
    2. bfs广度优先遍历,输出层序序列
    3. 递归输出中序序列

    思路 02

    1. 将节点关系按照输入保存
    2. 使用后序遍历递归进行二叉树反转(也可使用前序遍历递归进行二叉树反转)
    3. bfs广度优先遍历,输出层序序列
    4. 递归输出中序序列

    Code

    Code 01(最优)

    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
    const int maxn = 10;
    int nds[maxn][2];
    int n,cnt;
    bool flag[maxn];
    void bfs(int root) {
    	queue<int> q;
    	q.push(root);
    	while(!q.empty()) {
    		int now = q.front();
    		q.pop();
    		printf("%d",now);
    		if(++cnt<n)printf(" ");
    		if(nds[now][0]!=-1)q.push(nds[now][0]);
    		if(nds[now][1]!=-1)q.push(nds[now][1]);
    	}
    }
    void inOrder(int nd){
    	if(nd==-1){//nds[nd][0]==-1&&nds[nd][1]==-1
    		return;
    	}
    	inOrder(nds[nd][0]);
    	printf("%d",nd);
    	if(++cnt<n)printf(" ");
    	inOrder(nds[nd][1]);
    }
    int main(int argc,char * argv[]) {
    	char f,r;
    	scanf("%d",&n);
    	for(int i=0; i<n; i++) {
    		scanf("%*c%c %c",&r,&f);
    		if(f=='-')nds[i][0]=-1;
    		else {
    			nds[i][0]=f-'0';
    			flag[nds[i][0]]=true;
    		}
    		if(r=='-')nds[i][1]=-1;
    		else {
    			nds[i][1]=r-'0';
    			flag[nds[i][1]]=true;
    		}
    
    	}
    	//find root
    	int k=0;
    	while(k<n&&flag[k])k++;
    	bfs(k);
    	printf("
    ");
    	cnt=0;
    	inOrder(k);
    	return 0;
    }
    

    Code 02

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int maxn = 10;
    struct node {    // 二叉树的静态写法
        int lchild, rchild;
    } Node[maxn];
    bool notRoot[maxn] = {false};    // 记录是否不是根结点,初始均是根结点
    int n, num = 0;    // n为结点个数,num为当前已经输出的结点个数
    // print函数输出结点id的编号
    void print(int id) {
        printf("%d", id);    // 输出id
        num++;    // 已经输出的结点个数加1
        if(num < n) printf(" ");    // 最后一个结点不输出空格
        else printf("
    ");
    }
    // 中序遍历
    void inOrder(int root) {
        if(root == -1) {
            return;
        }
        inOrder(Node[root].lchild);
        print(root);
        inOrder(Node[root].rchild);
    }
    // 层序遍历
    void BFS(int root) {
        queue<int> q;  //注意队列里是存地址
        q.push(root);  //将根结点地址入队
        while(!q.empty()) {
            int now = q.front();  //取出队首元素
            q.pop();
            print(now);
            if(Node[now].lchild != -1) q.push(Node[now].lchild);  //左子树非空
            if(Node[now].rchild != -1) q.push(Node[now].rchild);  //右子树非空
        }
    }
    // 后序遍历,用以反转二叉树
    //void postOrder(int root) {
    //    if(root == -1) {
    //        return;
    //    }
    //    postOrder(Node[root].lchild);
    //    postOrder(Node[root].rchild);
    //    swap(Node[root].lchild, Node[root].rchild);    // 交换左右孩子
    //}
    // 前序遍历,用以反转二叉树
    void preOrder(int root) {
        if(root == -1) {
            return;
        }
        swap(Node[root].lchild, Node[root].rchild);    // 交换左右孩子
        preOrder(Node[root].lchild);
        preOrder(Node[root].rchild);
    }
    // 将输入的字符转换为-1或者结点编号
    int strToNum(char c) {
        if(c == '-') return -1;    // “-”表示没有孩子结点,记为-1
        else {
            notRoot[c - '0'] = true;    // 标记c不是根结点
            return c - '0';    // 返回结点编号
        }
    }
    // 寻找根结点编号
    int findRoot() {
        for(int i = 0; i < n; i++) {
            if(notRoot[i] == false) {
                return i;    // 是根结点,返回i
            }
        }
    }
    int main() {
        char lchild, rchild;
        scanf("%d", &n);    // 结点个数
        for(int i = 0; i < n; i++) {
            scanf("%*c%c %c", &lchild, &rchild);    // 左右孩子
            Node[i].lchild = strToNum(lchild);
            Node[i].rchild = strToNum(rchild);
        }
        int root = findRoot();    // 获得根结点编号
    //    postOrder(root);    // 后序遍历,反转二叉树
        preOrder(root);    // 前序遍历,反转二叉树
        BFS(root);    // 输出层序遍历序列
        num = 0;    // 已输出的结点个数置0
        inOrder(root);    // 输出中序遍历序列
        return 0;
    }
    
  • 相关阅读:
    [测试题]钦点
    香港记者
    【模板】三维偏序
    C. Journey
    B. Game of the Rows
    A. Arya and Bran
    D. Statistics of Recompressing Videos
    人们对Python在企业级开发中的10大误解
    各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT
    WPF.UIShell UIFramework之自定义窗口的深度技术
  • 原文地址:https://www.cnblogs.com/houzm/p/12329111.html
Copyright © 2011-2022 走看看