【暖*墟】关于{ 树 }的专题

one. 二叉树(Binary Tree)

根结点(root)、左子树(left subtree)和右子树(right subtree)组成,

而左、右子树分别是一棵二叉树。注意在计算机中,树一般是“倒置”的,即根在上,叶子在下。

树(tree)和二叉树类似,区别在于每个结点不一定只有两棵子树。

书的内容也是树状结构,根结点有12棵子树:第1章、第2章、第3章、……、第12章,而第1章又有5棵子树:1.1、1.2、……、1.5。

不管是二叉树还是树,每个非根结点都有一个父亲(father),也称父结点。

1.二叉树的编号

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <sstream>
using namespace std;

/*【小球下落】Uva 679(模拟)
有一棵二叉树,最大深度为D,且所有叶子的深度都相同。
结点从上到下从左到右编号1, 2, 3,…, 2^D-1。在结点1处放一个小球,会下落。
每个内结点上都有一个开关,初始关闭;有小球落到一个开关上时,开关状态改变。
当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,直到走到叶子结点。
一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?
输入叶子深度D和小球个数I,输出第I个小球最后在的叶子编号。D≤20。输入最多包含1000组数据。 */

/* 提示:给定一棵包含2d个结点(其中d为树的高度)的完全二叉树,
如果把结点从上到下从左到右编号为1,2,3……,则结点k的左右子结点编号分别为{2k和2k+1}。 */

int id[1<<20];//2^20
int main(){
    int D,I;
    while(scanf("%d%d",&D,&I)==2){
        memset(id,0,sizeof(id)); //开关全闭合
        int k, n=(1<<D)-1 ; //n是最大节点的编号
        for(int i=0;i<I;i++){
            k=1; while(k<=n){ //枚举节点
            //(因为要找最后一层,所以出界之前 最后一次放大的影响可以用最终除二来消除 )
                id[k]=!id[k];
                k=id[k]? k*2 : k*2+1 ; //每次进行放大处理进入下一层
            }
        }
        printf("%d\n",k/2);
    }
    return 0;
}  

//但,这是一份超时代码qwq

------------以上代码用“while(k<=n)”的方法判断“出界”更具一般性,但运算量太大。-----------------

每个小球都会落在根结点上,因此前两个小球必然是一个在左子树,一个在右子树。

一般地,只需看小球编号的奇偶性,就能知道它是最终在哪棵子树中。对于那些落入根结点左子树的小球来说,只需知道该小球是第几个落在根的左子树里的,就可以知道它下一步往左还是往右了。依此类推,直到小球落到叶子上。

如果使用题目中给出的编号I,则当I是奇数时,它是往左走的第(I+1)/2个小球;当I是偶数时,它是往右走的第I/2个小球。

这样,直接模拟最后一个小球的路线:

while(scanf("%d%d", &D, &I) == 2){
  int k = 1;
  for(int i = 0; i<D-1; i++)
    if(I%2) { k = k*2; I = (I+1)/2; }
    else { k = k*2+1; I /= 2; }
  printf("%d\n", k);
}

这样,程序的运算量就与小球编号无关了,而且节省了一个巨大的id数组。

int main(){  //uva679
    int t,D,I; cin>>t;
    while(t!=-1&&t--){
        scanf("%d%d", &D, &I);
        int k = 1;
        for(int i = 0; i<D-1; i++){
            if(I%2) { k = k*2; I = (I+1)/2; }
            else { k = k*2+1; I /= 2; }
        }
        printf("%d\n", k);
    }
    return 0;
}


2.二叉树的层次遍历

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <sstream>
using namespace std;

/*【树的层次遍历】(UVa 122)//紫书上讲的太难辣qaq,以后再看吧
输入一棵二叉树,结点个数不超过256。按从上到下、从左到右的顺序输出各结点值。
每个结点都按照从根结点到它的移动序列给出(L表示左,R表示右)。
在输入中,每个结点的左括号和右括号之间没有空格,相邻结点之间用一个空格隔开。
每棵树的输入用一对空括号“()”结束(这对括号本身不代表一个结点)。
注意,如果路径上有的结点在输入中{没有给出},或者{给出超过一次},输出-1。 */

/*输入:(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
(3,L) (4,R) ()  输出: 5 4 8 11 13 4 7 2 1  //  -1  */

const int MAXN=10010;
int ans[MAXN],flot,k;
bool failed;
struct Node{
    bool h_v;
    int v;
    Node *L,*R;
    Node():h_v(false),L(NULL),R(NULL){}
}*head;
void addnode(int v,char *s){
    //printf("%s %d\n",s,v);
    Node *cur=head;
    for(int i=0;s[i];i++){
        if(s[i]=='L'){
            if(cur->L==NULL)cur->L=new Node();
            cur=cur->L;
        }
        else if(s[i]=='R'){
            if(cur->R==NULL)cur->R=new Node();
            cur=cur->R;
        }
    }
    if(cur->h_v)failed=true;//注意要加上failed判断没有出现数字的情况;
    cur->v=v;
    cur->h_v=true;
}
void print(){
    queue<Node*>q;
    Node *cur=head;
    q.push(head);
    while(!q.empty()){
        cur=q.front();
        q.pop();
        if(cur->h_v==0)flot=0;
        if(!flot)break;
        ans[k++]=cur->v;
        if(cur->L!=NULL)q.push(cur->L);
        if(cur->R!=NULL)q.push(cur->R);
    }
    if(flot&&!failed)for(int i=0;i<k;i++){
        if(i)printf(" ");
        printf("%d",ans[i]);
    }
    else printf("not complete");
    puts("");
}
void freenode(Node *cur){
    if(cur==NULL)return;
    freenode(cur->L);
    freenode(cur->R);
    free(cur);
}
int main(){
    char s[MAXN];
    head=new Node();
    failed=false;
    while(~scanf("%s",s)){
        if(!strcmp(s,"()")){
            flot=1;
            k=0;
            print();
            freenode(head);
            head=new Node();
            failed=false;
            continue;
        }
        int v;
        sscanf(&s[1],"%d",&v);
        addnode(v,strchr(s,',')+1);
    }
    return 0;
}












猜你喜欢

转载自blog.csdn.net/flora715/article/details/80453440
今日推荐