zoukankan      html  css  js  c++  java
  • PAT Advanced 1110 Complete Binary Tree (25) [完全⼆叉树]

    题目

    Given a tree, you are supposed to tell if it is a complete binary tree.
    Input Specification:
    Each input file contains one test case. For each case, the first line gives a positive integer N (<=20) 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, 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 case, print in one line “YES” and the index of the last node if the tree is a complete binary tree, or “NO” and the index of the root if not. There must be exactly one space separating the word and the number.
    Sample Input 1:
    9
    7 8
    – –
    – –
    – –
    0 1
    2 3
    4 5
    – –
    – –
    Sample Output 1:
    YES 8
    Sample Output 2:
    8
    – –
    4 5
    0 6
    – –
    2 3
    – 7
    – –
    – –
    Sample Output 2:
    NO 1

    题目分析

    已知树所有节点的子节点信息,判断是否是完全二叉树,是打印YES+最后一个节点,否打印NO+根节点

    解题思路

    1. 深度遍历树,将树中节点存储与数组中,根节点index=0,其左右子节点index分别为2i+1,2i+2
    2. 判断是否为完全二叉树
      2.1 方式一:判断前后节点index是否相差1(若使用数组存储判断数组中有没有浪费的空闲位置,因为完全二叉树使用数组存储时中间没有空闲位置)
      2.2 方式二:最大index==结点数n-1,若相等即为二叉树
      2.3 方式三:BFS借助队列层级遍历树,完全二叉树中间不会遇到NULL

    Code

    Code 01

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int maxn = 30;
    bool isRoot[maxn];  // 结点是否是根结点
    struct Node {
        int left, right;    // 左孩子和右孩子的下标
    } node[maxn];   // 二叉树结点静态数组
    // input函数输入数据
    int input() {
        char id[3];
        scanf("%s", id);    // 输入结点编号
        if(id[0] == '-') {
            return -1;      // 如果是'-',说明是空结点,返回-1
        } else {
            if(strlen(id) == 1) return id[0] - '0';     // 编号小于10
            else return (id[0] - '0') * 10 + (id[1] - '0');     // 编号大于等于10
        }
    }
    // findRoot函数找到根结点编号
    int findRoot(int n) {
        for(int i = 0; i < n; i++) {
            if(isRoot[i]) {     // isRoot为true时直接返回根结点编号i
                return i;
            }
        }
    }
    // BFS函数判断完全二叉树,root为根结点编号,last是最后一个结点编号(注意引用),n为结点个数
    bool BFS(int root, int &last, int n) {
        queue<int> q;       // 定义队列
        q.push(root);       // 根结点入队
        while(n) {      // 只要n不为0,即还没有访问完全部非空结点
            int front = q.front();      // 队首结点front
            q.pop();        // 弹出队首结点
            if(front == -1) return false;   // 访问到空结点,一定是非完全二叉树
            n--;    // 已访问的非空结点减少1
            last = front;   // 记录最后一个非空结点编号
            q.push(node[front].left);       // 左孩子入队(包括空结点)
            q.push(node[front].right);      // 右孩子入队(包括空结点)
        }
        return true;    // 已经访问完所有非空结点,还没有碰到空结点,一定是完全二叉树
    }
    int main() {
        int n;
        scanf("%d", &n);    // 输入结点个数
        memset(isRoot, true, sizeof(isRoot));       //初始化所有结点都是根结点
        for(int i = 0; i < n; i++) {        // 对每一个结点
            int left = input(), right = input();    // 输入左右孩子编号
            isRoot[left] = isRoot[right] = false;   // 这两个编号一定不是根结点
            node[i].left = left;        // 记录左孩子
            node[i].right = right;      // 记录右孩子
        }
        int root = findRoot(n), last;       // 寻找根结点root,定义最后一个结点last
        bool isCompleteTree = BFS(root, last, n);      // 判断完全二叉树,同时记录最后一个结点last
        if(isCompleteTree) {        // 如果是完全二叉树
            printf("YES %d
    ", last);   // 输出最后一个结点编号
        } else {
            printf("NO %d
    ", root);    // 否则输出根结点编号
        }
        return 0;
    }
    

    Code 02

    #include <iostream>
    #include <queue>
    using namespace std;
    const int maxn=20;
    int last=-1;
    int flag[maxn];
    struct node {
    	int d;
    	int left=-1;
    	int right=-1;
    } nds[maxn];
    bool bfs(int r) {
    	queue<int> q;
    	q.push(r);
    	while(!q.empty()) {
    		int now = q.front();
    		q.pop();
    		if(now!=-1) { // 非空节点 
    			last = now;
    			q.push(nds[now].left); 
    			q.push(nds[now].right);
    		} else { // 空节点 
    			//检验后面是否还有非-1的数
    			while(!q.empty()) {
    				int nw = q.front();
    				q.pop();
    				if(nw!=-1)return false; //如果NULL后有非NULL节点,非完全二叉树 
    			}
    		}
    	}
    	return true;
    }
    int main(int argc,char * argv[]) {
    	int n;
    	scanf("%d",&n);
    	string f,r;
    	for(int i=0; i<n; i++) {
    		cin>>f>>r;
    		nds[i].d=i;
    		if(f!="-") {
    			nds[i].left=stoi(f);
    			flag[nds[i].left]=1;
    		}
    		if(r!="-") {
    			nds[i].right=stoi(r);
    			flag[nds[i].right]=1;
    		}
    	}
    	//find root;
    	int k=0;
    	while(k<n&&flag[k]==1)k++;
    	bool ff = bfs(k);
    	if(ff) {
    		printf("%s %d","YES",last);
    	} else {
    		printf("%s %d","NO",k);
    	}
    
    	return 0;
    }
    

    Code 03

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=20;
    int flag[maxn];
    struct node {
    	int data;
    	int index;
    	int left=-1;
    	int right=-1;
    } nds[maxn];
    void dfs(int root,int index) {
    	if(root==-1)return;
    	nds[root].index=index;
    	dfs(nds[root].left,2*index+1);
    	dfs(nds[root].right,2*index+2);
    }
    bool cmp(node &n1,node &n2){
    	return n1.index<n2.index;
    }
    int main(int argc,char * argv[]) {
    	int n;
    	scanf("%d",&n);
    	string f,r;
    	for(int i=0; i<n; i++) {
    		cin>>f>>r;
    		nds[i].data=i; 
    		if(f!="-") {
    			nds[i].left=stoi(f);
    			flag[nds[i].left]=1;
    		}
    		if(r!="-") {
    			nds[i].right=stoi(r);
    			flag[nds[i].right]=1;
    		}
    	}
    	//find root;
    	int k=0;
    	while(k<n&&flag[k]==1)k++;
    	dfs(k,0);
    	sort(nds,nds+n,cmp);
    	/**
    		判断当前树是否为完全二叉树:
    		方式一:遍历所有节点,前后节点index相差1
    		方式二:完全二叉树的所有节点最大index为n 
    	*/
    	bool iscbt=true;
    	for(int i=1; i<n; i++) {
    		if(nds[i].index-nds[i-1].index!=1) {
    			iscbt=false;
    		}
    	}
    	if(iscbt)printf("YES %d",nds[n-1].data);
    	else printf("NO %d", nds[0].data);
    	return 0;
    }
    

    Code 04

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=20;
    int flag[maxn];
    struct node {
    	int left=-1;
    	int right=-1;
    } nds[maxn];
    int max_n,max_i;
    void dfs(int root,int index) {
    	if(root==-1)return;
    	if(max_i<index) {
    		max_i=index;
    		max_n=root;
    	}
    	dfs(nds[root].left,2*index+1);
    	dfs(nds[root].right,2*index+2);
    }
    int main(int argc,char * argv[]) {
    	int n;
    	scanf("%d",&n);
    	string f,r;
    	for(int i=0; i<n; i++) {
    		cin>>f>>r;
    		if(f!="-") {
    			nds[i].left=stoi(f);
    			flag[nds[i].left]=1;
    		}
    		if(r!="-") {
    			nds[i].right=stoi(r);
    			flag[nds[i].right]=1;
    		}
    	}
    	//find root;
    	int k=0;
    	while(k<n&&flag[k]==1)k++;
    	dfs(k,0);
    	/**
    		判断当前树是否为完全二叉树:
    		方式一:遍历所有节点,前后节点index相差1
    		方式二:完全二叉树的所有节点最大index为n
    	*/
    	if(max_i==n-1)printf("YES %d",max_n);
    	else printf("NO %d", k);
    	return 0;
    }
    
  • 相关阅读:
    大话GridView—(1) 编辑、删除、查看详情、分页
    『协议』XMLRPC 协议规格说明
    『ExtJS』01 009. ExtJS 4 方法重载
    [SQL2005触发器学习]3、Instead Of触发器
    [SQL2005触发器学习]1、初识触发器
    禁止.NET程序多开
    面试遇到的面试题分析
    关于Page,Master,UserControl的初始化及加载顺序
    ASP.NET 下关于ACCESS连接字符串的配置
    [SQL2005触发器学习]2、After触发器
  • 原文地址:https://www.cnblogs.com/houzm/p/12335893.html
Copyright © 2011-2022 走看看