紫薯6.3 基本数据结构----树part1 (二叉)

eg题部分

6.3.1 Dropping Balls UVA - 679

在这里插入图片描述
在这里插入图片描述

题意:

有I个球,从一棵二叉树的顶点下落,问最后一颗球,落在哪里。

思路:

当然可以暴力模拟,但是会tle。
这里会发现最后一颗球从根往下走,是取决于前面的情况,更一般的即奇偶性。假如I%2==1,奇数,那么说明这个球往左走;偶数则往右下走。而走到下面又是一个子问题,而且规模被缩小了而已。

tle代码

#include <iostream>
#include <cstring>
#include <cstdio>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const ll maxn=1<<21;
int a[maxn];
int main()
{
    int t,k,n,d,l;
    cin>>t;
    while(t--)
    {
        scanf("%d%d", &d, &l);
        mst(a,0);
        n=(1<<d)-1;//位运算操作要小心
        //cout<<n<<'\n';
        For(i,1,l)
        {
            k=1;
            for(;;)
            {
                a[k]=!a[k];
                k=a[k]?2*k:(2*k+1);
                if(k>n)break;
            }
        }
        cout<<k/2<<"\n";
    }
    cin>>t;
    return 0;
}

AC代码

#include <iostream>
#include <cstring>
#include <cstdio>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t,k,d,l;
    cin>>t;
    while(t--)
    {
        cin>>d>>l;
        //cout<<n<<'\n';
        k=1;
        For(i,1,d-1)
        {
            if(l%2)k=k*2,l=(l+1)/2;
            else k=k*2+1,l=l/2;
        }
        cout<<k<<"\n";
    }
    cin>>t;
    return 0;
}

Trees on the level UVA - 122层次遍历(指针)

在这里插入图片描述
在这里插入图片描述

题意:

给你一个带权的二叉树,要你进行层次遍历。

反思

  1. 二叉树的指针表示法,要掌握哈哈哈。
  2. 这题的格式不允许有行末空格。
  3. 又有一次sscanf(&stirng,“%d”,&int)。(以字符串输入)
  4. strchr(string,‘char’)(在string种查找char)
  5. 切记strcmp(s,t)如果匹配成功,返回值是0.
  6. 本题用了c语言的string可以把“任意指向字符的指针”看成是字符串。

AC

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e3+10;
vector<int>ans;
struct node
{
    bool have_value;
    int v;
    node *left,*right;
    node():have_value(false),left(NULL),right(NULL){}
};
char s[maxn];
node *root;
bool failed=false;
node* newnode(){return new node();}
void addnode(int v, char *s)
{
    int n=strlen(s);
    node* u=root;
    for(int i=0; i<n; i++)
    {
        if(s[i]=='L')
        {
            if(u->left==NULL)u->left=newnode();
            u=u->left;
        }
        else if(s[i]=='R')
        {
            if(u->right==NULL)u->right=newnode();
            u=u->right;
        }
    }
    if(u->have_value)failed=true;
    u->v=v;
    u->have_value=true;
}
bool read_input()//这个函数可以直接放在,while
{
    failed=false;
    remove_tree(root);//这里记得加remove,否则有内存泄漏!!!!!
    root=newnode();
    for(;;)
    {
        if(scanf("%s", s)!=1)return false;//如果到了EOF,说明读取结束了。
        if(!strcmp(s,"()"))break;//字符比较函数
        int v;
        sscanf(&s[1],"%d",&v);
        addnode(v,strchr(s,',')+1);//这里+1,就会从,“,”下一个开始访问了。
    }
    return true;
}
void remove_tree(node*u)
{
    if(u==NULL)return;
    remove_tree(u->left);
    remove_tree(u->right);
    delete u;
}
bool bfs(vector<int>&ans)
{
    queue<node*>q;
    ans.clear();
    q.push(root);
    while(!q.empty())
    {
        node* u =q.front();q.pop();
        if(!u->have_value)return false;
        ans.push_back(u->v);
        if(u->left!=NULL)q.push(u->left);
        if(u->right!=NULL)q.push(u->right);
    }
    return true;
}
int main()
{
    while(read_input())
    {
        if(bfs(ans)&&!failed)
        {
            for(int i=0; i<ans.size(); i++)
            {
                if(i!=0)cout<<' ';//这里注意行末空格
                cout<<ans[i];
            }
            cout<<endl;
        }
        else cout<<"not complete"<<endl;
    }
    return 0;
}

Tree UVA - 548深度遍历(数组)(先序和后序

在这里插入图片描述

题意:

本题给你一个二叉树的中序和后序,要你找到一条由叶子到祖先的最短路。

思路&&反思:

由于每个点的权值是独立唯一的,所以这一道题可以把每个点的权值作为标号。
左子树和右子树的递归很容易搞错。(前序和中序)

AC

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <sstream>
using namespace std;
const int maxn=1e4+10;
int lch[maxn],rch[maxn],in_order[maxn],post_order[maxn],n;
int best_sum,best_u;
bool read_input(int *a)
{
    string line;
    while(!getline(cin,line))return false;
    stringstream ss(line);
    int x;
    n=0;
    while(ss>>x)a[++n]=x;
    return n>0;
}
int build(int l1,int r1,int l2, int r2)
{
    if(l1>r1)return false;
    //cout<<l1<<' '<<r1<<"   "<<l2<<' '<<r2<<endl;
    int root=post_order[r2];
    int p=l1;
    while(in_order[p]!=root)p++;
    int cnt=p-l1;
    lch[root]=build(l1,p-1,l2,l2+cnt-1);//
    rch[root]=build(p+1,r1,l2+cnt,r2-1);//
    return root;
}
void dfs(int u,int sum)
{
    sum+=u;
    if(!lch[u]&&!rch[u])
    {
        if(sum<best_sum||(sum==best_sum&&u<best_u)){best_u=u;best_sum=sum;}
    }
    if(lch[u])dfs(lch[u],sum);
    if(rch[u])dfs(rch[u],sum);
    return ;
}
int main()
{
    while(read_input(in_order))
    {
        read_input(post_order);
        build(1,n,1,n);
        best_sum=best_u=1e9;
        //cout<<"OK"<<endl;
        dfs(post_order[n],0);
        cout<<best_u<<endl;
    }
    return 0;
}
/*
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
*/

二叉树的构建及遍历(这里卡了好久)

反思

函数局部指针变为NULL,不会使上一层指针变为NULL,所以这里要用&。

AC

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
struct node
{
    char v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *root;
node* newnode(){return new node();}
void build(node*&u)//这里debug了半天,函数里的指针要间接引用。
{
    char v;
    scanf("%c",&v);
   // cout<<v<<endl;
    if(v=='#')u=NULL;
    else
    {
        //u=newnode();
        u->v=v;
        u->left=newnode();u->right=newnode();
        //cout<<1<<endl;
        //cout<<u->v<<endl;
        build(u->left);
        build(u->right);
    }
}
void pre_order(node *u)
{
    if(u==NULL)return ;
    cout<<u->v;
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node *u)
{
    if(u==NULL)return;
    in_order(u->left);
    cout<<u->v;
    in_order(u->right);
}
void post_order(node *u)
{
    if(u==NULL)return ;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v;
}
int main()
{
    root=newnode();
  //  cout<<"ok"<<endl;
    build(root);
  //  cout<<root->v<<endl;
    pre_order(root);
    cout<<'\n';
    in_order(root);
    cout<<"\n";
    post_order(root);
    return 0;
}

实现二叉排序树的各种算法

提交次数:2573 通过次数:1472题型: 编程题 语言: G++;GCC
Description 用函数实现如下二叉排序树算法: (1) 插入新结点
(2) 前序、中序、后序遍历二叉树 (3) 中序遍历的非递归算法
(4) 层次遍历二叉树 (5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0)

输入格式
第一行:准备建树的结点个数n
第二行:输入n个整数,用空格分隔
第三行:输入待查找的关键字
第四行:输入待查找的关键字
第五行:输入待插入的关键字

输出格式
第一行:二叉树的先序遍历序列
第二行:二叉树的中序遍历序列
第三行:二叉树的后序遍历序列
第四行:查找结果
第五行:查找结果
第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列
第九行:插入新结点后的二叉树的中序遍历序列(非递归算法)
第十行:插入新结点后的二叉树的层次遍历序列

输入样例
7
40 20 60 18 50 56 90
18
35
30

输出样例
40 20 18 60 50 56 90
18 20 40 50 56 60 90
18 20 56 50 90 60 40
1
0
40 20 18 30 60 50 56 90
18 20 30 40 50 56 60 90
18 30 20 56 50 90 60 40
18 20 30 40 50 56 60 90
40 20 60 18 30 50 90 56

定义:

根大于所有的左子树,小于所有的右子树。

反思

本题就是模拟比较烦点。

AC

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *root;
node *newnode(){return new node();}
void insertion(node *&u,int key)
{
    if(u==NULL)
    {
        u=newnode();
        u->v=key;
    }
    else if(u->v>key)insertion(u->left,key);
    else if(u->v<key)insertion(u->right,key);
}
node* find(node*u,int key)
{
    if(!u||u->v==key)return u;
    if(u->v>key)return find(u->left,key);
    else if(u->v<key)return find(u->right,key);
}
void pre_order(node *u)
{
    if(u==NULL)return ;
    cout<<u->v<<' ';
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node *u)
{
    if(u==NULL)return ;
    in_order(u->left);
    cout<<u->v<<' ';
    in_order(u->right);
}
void post_order(node *u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v<<' ';
}
void no_in_order(node *cur)//这里就是模拟
{
    stack<node*>st;
    while(cur||!st.empty())
    {
        while(cur)
        {
            st.push(cur);
            cur=cur->left;
        }
        node* top=st.top();
        st.pop();
        cout<<top->v<<' ';
        cur=top->right;
    }
}
void bfs(node *u)
{
    queue<node*>q;
    if(root!=NULL)q.push(root);
    while(!q.empty())
    {
        node* top=q.front();q.pop();
        cout<<top->v<<' ';
        if(top->left)q.push(top->left);
        if(top->right)q.push(top->right);
    }
}
int main()
{
    root=NULL;
    int n,x;
    cin>>n;
    For(i,1,n)
    {
        cin>>x;
        insertion(root,x);
    }
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;
    cin>>x;
    if(find(root,x)!=NULL)cout<<1<<endl;
    else cout<<0<<endl;
    cin>>x;
    if(find(root,x)!=NULL)cout<<1<<endl;
    else cout<<0<<endl;
    cin>>x;
    insertion(root,x);
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;//
    no_in_order(root);//in_ordr is increase
    cout<<endl;
    bfs(root);
    cout<<endl;
    return 0;
}

8608 实现二叉排序树的各种算法(2)

时间限制:1000MS 代码长度限制:10KB
提交次数:2559 通过次数:1396题型: 编程题 语言: G++;GCC
Description用函数实现如下二叉排序树算法:
(1) 插入新结点
(2) 前序、中序、后序遍历二叉树
(3) 中序遍历的非递归算法
(4) 层次遍历二叉树
(5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0)
(6) 交换各结点的左右子树
(7) 求二叉树的深度
(8) 叶子结点数

输入格式
第一行:准备建树的结点个数n
第二行:输入n个整数,用空格分隔
第三行:输入待查找的关键字
第四行:输入待查找的关键字
第五行:输入待插入的关键字

输出格式
第一行:二叉树的先序遍历序列
第二行:二叉树的中序遍历序列
第三行:二叉树的后序遍历序列
第四行:查找结果
第五行:查找结果
第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列
第九行:插入新结点后的二叉树的中序遍历序列(非递归算法)
第十行:插入新结点后的二叉树的层次遍历序列
第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列
第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列
第十七行:二叉树的深度
第十八行:叶子结点数

输入样例
7
40 20 60 18 50 56 90
18
35
30

输出样例
40 20 18 60 50 56 90
18 20 40 50 56 60 90
18 20 56 50 90 60 40
1
0
40 20 18 30 60 50 56 90
18 20 30 40 50 56 60 90
18 30 20 56 50 90 60 40
18 20 30 40 50 56 60 90
40 20 60 18 30 50 90 56
40 60 90 50 56 20 30 18
90 60 56 50 40 30 20 18
90 56 50 60 30 18 20 40
40 20 18 30 60 50 56 90
18 20 30 40 50 56 60 90
18 30 20 56 50 90 60 40
4
4

作者 yqm

“二叉排序树”简介

  1. 对于输入,动态的构建一颗二叉树,小于爸爸,往左边放;大于爸爸的,往右边放。
  2. 由于二叉排序树中序遍历,就是该输入的递增序列。

AC

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *root;
node* newnode(){return new node();}
void insertion(node*&u, int key)
{
    if(u==NULL)
    {
        u=newnode();
        u->v=key;
    }
    else if(u->v>key) insertion(u->left,key);
    else if(u->v<key) insertion(u->right,key);
}
node* find(node*u, int key)
{
    if(u==NULL||u->v==key)return u;
    else if(u->v>key) return find(u->left,key);
    else if(u->v<key) return find(u->right,key);
}
void pre_order(node*u)
{
    if(u==NULL)return;
    cout<<u->v<<' ';
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node*u)
{
    if(u==NULL)return;
    in_order(u->left);
    cout<<u->v<<' ';
    in_order(u->right);
}
void post_order(node*u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v<<' ';
}
void no_in_order(node *u)
{
    node *cur=u;
    stack<node*>st;
    while(cur||!st.empty())
    {
        while(cur)
        {
            st.push(cur);
            cur=cur->left;
        }
        node*top=st.top();st.pop();
        cout<<top->v<<' ';
        cur=top->right;
    }
}
void bfs(node *u)
{
    queue<node*>q;
    if(u!=NULL)q.push(u);
    while(!q.empty())
    {
        node *top=q.front();q.pop();
        cout<<top->v<<' ';
        if(top->left)q.push(top->left);
        if(top->right)q.push(top->right);
    }
}
void swap(node *&u)
{
    node* temp;
    if(u==NULL)return;
    temp=u->left;
    u->left=u->right;
    u->right=temp;
    swap(u->left);
    swap(u->right);
}
int depth(node*u)
{
    if(u==NULL)return 0;
    int tot=0;
    tot=max(1+depth(u->left),tot);
    tot=max(1+depth(u->right),tot);
    return tot;
}
void leaf(node *u,int &sum)
{
    if(u==NULL)return ;
    if(u->left==NULL&&u->right==NULL)sum++;
    leaf(u->left,sum);
    leaf(u->right,sum);
}
int main()
{
    int n,x;
    cin>>n;
    For(i,1,n)
    {
        cin>>x;
        insertion(root,x);
    }
    pre_order(root);
    cout<<endl;
    in_order(root);
    cout<<endl;
    post_order(root);
    cout<<endl;
    For(i,1,2)
    {
        cin>>x;
        if(find(root,x)!=NULL)cout<<1<<endl;
        else cout<<0<<endl;
    }
    cin>>x;
    insertion(root,x);//insertion
    pre_order(root);
    cout<<endl;
    in_order(root);
    cout<<endl;
    post_order(root);
    cout<<endl;
    no_in_order(root);//no_in_order
    cout<<endl;
    bfs(root);
    cout<<endl;
    swap(root);//swap
    pre_order(root);
    cout<<endl;
    in_order(root);
    cout<<endl;
    post_order(root);
    cout<<endl;
    swap(root);//swap
    pre_order(root);
    cout<<endl;
    in_order(root);
    cout<<endl;
    post_order(root);
    cout<<endl;
    int sum=0;
    cout<<depth(root)<<endl;//depth
    leaf(root,sum);
    cout<<sum<<endl;//tot
    return 0;
}

8609 哈夫曼树

时间限制:1000MS 代码长度限制:10KB
提交次数:3178 通过次数:1263题型: 编程题 语言: G++;GCC
Description 利用静态链表建立赫夫曼树,建树过程中要求左子树权值小于右子树权值,求各结点的编码。要求:叶子结点的个数n及结点值由键盘录入。本题给出程序代码,要求修改以满足测试要求.
输入格式
第一行:权值个数
第二行:输入n个权值,用空格分隔

输出格式
输出n行
每行表示各权值对应的哈夫曼编码

输入样例
8
5 29 7 8 14 23 3 11

输出样例
0001
10
1110
1111
110
01
0000
001

哈夫曼树简介

  1. 一种贪心思想,每次构建都是权值最小的两棵树。
  2. 如果权值一样,节点少的放在左边。

AC

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#define se second
#define fi first
#define mp make_pair
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int a[10000];
struct node
{
    int v;
    node *left,*right;
    int cnt;
    node():left(NULL),right(NULL),cnt(0) {}
};
typedef pair<int,int>pa;
typedef pair<pa,node*>paa;
priority_queue<paa>q;
map<int,string>ma;
node* newnode()
{
    return new node();
}
node* build()
{
    node *root;
    while(!q.empty())
    {
        node *u=q.top().second;
        q.pop();
        if(q.empty())break;
        node *v=q.top().second;
        q.pop();
        root=newnode();
        root->v=u->v+v->v;
        //cout<<u->v<<' '<<v->v<<endl;
        if(u->v==v->v)
        {
            if((u->cnt)>(v->cnt))root->left=v,root->right=u;
            else root->left=u,root->right=v;
        }
        else root->left=u,root->right=v;
        root->cnt=u->cnt+v->cnt;
        q.push(mp(mp(-(root->v),-(root->cnt)),root));
    }
    //cout<<root->v<<endl;
    return root;
}
void dfs(node *u,string s)
{
    if(u==NULL)return ;
    if(u->cnt==1)
    {
        //cout<<u->v<<' '<<s<<endl;
        ma[u->v]=s;
    }
    dfs(u->left,s+'0');
    dfs(u->right,s+'1');
}
int main()
{
    int n;
    cin>>n;
    For(i,1,n)cin>>a[i];
    For(i,1,n)
    {
        node *u=newnode();
        u->v=a[i];
        u->cnt=1;
        q.push(mp(mp(-a[i],-(u->cnt)),u));
    }
    node *root=newnode();
    root=build();
    string s;
    //cout<<s<<endl;
   // cout<<endl;
    dfs(root,s);
    For(i,1,n)cout<<ma[a[i]]<<endl;
    return 0;
}

18723 FBI树

时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0题型: 编程题 语言: 不限定
Description我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。
FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。一个长度为2^n的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:
1)T的根结点为R,其类型与串S的类型相同;
2)若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给定一个长度为2的n次幂的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历*2序列。

输入格式第一行是一个整数N(0 ≤ N ≤ 10),第二行是一个长度为2^N的“01”串。

输出格式一行,这一行只包含一个字符串,即FBI树的后序遍历序列。

输入样例3
10001011

输出样例IBFBBBFIBFIIIFF

提示两种方法:

(1)二叉树首选算法,二分递归。即建树的同时后序遍历
(2)利用完全二叉树性质存储和构造二叉树,再后序遍历。

AC

#include <iostream>
#include <cstring>
#include <string>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
char s[1024+10];
struct node
{
    char val;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node* newnode(){return new node();}
int n;
void build(node*&u ,int pos,int len)
{
    u=newnode();
    if(len==1)
    {
        if(s[pos]=='1')u->val='I';
        else u->val='B';
        //cout<<u->val<<endl;
        return ;
    }
    build(u->left,pos,len/2);
    build(u->right,pos+len/2,len/2);
    char l=u->left->val,r=u->right->val;
    //cout<<l<<' '<<r<<' '<<pos<<' '<<len<<endl;
    if(l==r)u->val=l;
    else u->val='F';
    return ;
}
void post_order(node*root)
{
    if(root==NULL)return ;
    post_order(root->left);
    post_order(root->right);
    cout<<root->val;
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    cin>>(s+1);
    node*root;//=newnode();
    build(root,1,1<<n);
    //cout<<"ok"<<endl;
    //cout<<root->val<<endl;
   // char l=root->left->val,r=root->right->val;
   // cout<<l<<' '<<r<<endl;
    post_order(root);
    return 0;
}

17121 求二叉树各种节点数

时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0题型: 编程题 语言: G++;GCC
Description构造二叉链表表示的二叉树:按先序次序输入二叉树中结点的值(一个字符),’#'字符表示空树,构造二叉链表表示的二叉树T,并求此二叉树中度为2的节点总数,度为1的节点总数,度为0的节点总数

输入格式
第一行输入先序次序二叉树中结点

输出格式
第一行输出度为2的节点数
第二行输出度为1的节点数
第三行输出度为0的节点数

输入样例
ABC###D##

输出样例
1
1
2

思路&&反思

  1. 本题读入先序可以边读边建树。
  2. 也可以定义一个全局cnt,每读完一个字符cnt++。
#include <iostream>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int len1,len2,len0;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node* newnode(){return new node();}
void build(node*&u)//这里debug了半天,函数里的指针要间接引用。
{
    char v;
    cin>>v;
   // cout<<v<<endl;
    if(v=='#')u=NULL;
    else
    {
        //u=newnode();
        u->left=newnode();u->right=newnode();
        //cout<<1<<endl;
        //cout<<u->v<<endl;
        build(u->left);
        build(u->right);
        if(u->left&&u->right)u->v=2;
        else if(u->left||u->right)u->v=1;
        else u->v=0;
    }
    return ;
}
void dfs(node *root)
{
    if(root==NULL)return ;
    if(root->v==2)len2++;
    else if(root->v==1)len1++;
    else len0++;
    dfs(root->left);
    dfs(root->right);
}
int main()
{
    node *root=newnode();
    build(root);
    dfs(root);
    cout<<len2<<endl;
    cout<<len1<<endl;
    cout<<len0<<endl;
    return 0;
}

17263 计算二叉树的第k层中所有叶子结点个数

时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0题型: 编程题 语言: G++;GCC
Description二叉链表表示的二叉树:按先序次序输入二叉树中结点的值,’#'字符表示空树,构造二叉链表表示的二叉树T(该二叉树中的结点为单个字符并且无值重复的结点),
编写算法完成:计算二叉树的第k层中所有叶子结点个数,根结点为第1层,根结点的孩子结点为第2层,依次类推。

输入格式
第一行输入先序次序二叉树中结点
第二行输入层次k

输出格式
第一行输出该二叉树的第k层中所有叶子结点个数

输入样例
ABC###D##
2

输出样例
1

AC

#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
struct node
{
    node *left, *right;
    node():left(NULL),right(NULL){}
};
node* newnode(){return new node();}
void build(node *&u)
{
    char ch;
    cin>>ch;
    if(ch=='#')u=NULL;
    else
    {
        u->left=newnode();
        u->right=newnode();
        build(u->left);
        build(u->right);
    }
}
int k,ans=0;
void dfs(node *u, int cnt)
{
    if(u==NULL)return ;
    if(cnt==k&&!(u->left||u->right))ans++;
    dfs(u->left,cnt+1);
    dfs(u->right,cnt+1);
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    node *root=newnode();
    build(root);
    cin>>k;
    dfs(root,1);
    cout<<ans<<endl;
    return 0;
}

18724 二叉树的遍历运算(先序和中序

时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0题型: 编程题 语言: 不限定
Description二叉树的三种遍历都可以通过递归实现。
如果我们知道一棵二叉树的先序和中序序列,可以用递归的方法求后序遍历序列。

输入格式
两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串,表示树的中序遍历。树的结点一律用小写字母表示。

输出格式
一个字符串,树的后序序列。

输入样例
abcde
bcade

输出样例
cbeda

AC

#include <iostream>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
char pre[1010],in[1010];
struct node
{
    char val;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node* newnode(){return new node();}
void build(node*&u,int l1,int r1, int l2, int r2)
{
    if(l1>r1)
    {
        u=NULL;//¼ÇµÃÖÃÁã¡£
        return;
    }
    u->val=pre[l1];
    //cout<<u->val<<endl;
    u->left=newnode();
    u->right=newnode();
    int p=l2,cnt=0;
    while(in[p]!=pre[l1])p++;
    cnt=p-l2;
    build(u->left,l1+1,l1+cnt,l2,p-1);
    build(u->right,l1+cnt+1,r1,p+1,r2);
}
void post_order(node *u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->val;
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>pre+1;
    cin>>in+1;
    int len=strlen(pre+1);
    node*root=newnode();
    build(root,1,len,1,len);
 //   cout<<"ok"<<endl;
    post_order(root);
    return 0;
}

二叉排序树的复制

时间限制:1000MS 代码长度限制:10KB
提交次数:672 通过次数:553题型: 编程题 语言: G++;GCC
Description完成二叉排序树复制功能。我们经常对文件或文件夹进行复制和粘贴操作,在这里我们完全复制一棵二叉树。首先创建一棵具有若干结点的二叉排序树Ta,对其进行前、中、后序遍历并输出。复制生成Tb,对其进行前、中、后序遍历,再分别对两个树插入若干数据后遍历。
输入格式
第一行 树的结点个数
第二行 输入上一行指定的整数
第三行 输入一个整数,插入到Tb
第四行 输入一个整数,插入到Ta

输出格式
第一~三行输出前、中、后序遍历二叉树
第四~六行输出前、中、后序遍历二叉树
第七~九行输出前、中、后序遍历二叉树

输入样例
5
50 20 10 80 70
90
5

输出样例
50 20 10 80 70
10 20 50 70 80
10 20 70 80 50
50 20 10 80 70 90
10 20 50 70 80 90
10 20 70 90 80 50
50 20 10 5 80 70
5 10 20 50 70 80
5 10 20 70 80 50

AC

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *newnode(){return new node();}
void insertion(node *&u,int key)
{
    if(u==NULL)
    {
        u=newnode();
        u->v=key;
    }
    else if(u->v>key)insertion(u->left,key);
    else if(u->v<key)insertion(u->right,key);
}
node* find(node*u,int key)
{
    if(!u||u->v==key)return u;
    if(u->v>key)return find(u->left,key);
    else if(u->v<key)return find(u->right,key);
}
void pre_order(node *u)
{
    if(u==NULL)return ;
    cout<<u->v<<' ';
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node *u)
{
    if(u==NULL)return ;
    in_order(u->left);
    cout<<u->v<<' ';
    in_order(u->right);
}
void post_order(node *u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v<<' ';
}
void copy(node *&u, node *&v)
{
    if(u==NULL)return;
    v=newnode();
    v->v=u->v;
    copy(u->left,v->left);
    copy(u->right,v->right);
}
int main()
{
    node *root=NULL,*root2=NULL;
    int n,x;
    cin>>n;
    For(i,1,n)
    {
        cin>>x;
        insertion(root,x);
    }
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;//
    copy(root,root2);//copy the sort treee
//
    cin>>x;
    insertion(root,x);//insert root1
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;//
//
    cin>>x;
    insertion(root2,x);//insert root2
    pre_order(root2);
    cout<<endl;
    in_order(root2);//it is increase
    cout<<endl;
    post_order(root2);
    cout<<endl;//
    return 0;
}

9493 计算二叉排序树的结点个数

时间限制:1000MS 代码长度限制:10KB
提交次数:658 通过次数:513题型: 编程题 语言: G++;GCC
Description构建一个二叉排序树,插入若干数据后,给出树中结点的个数。
输入格式
第一行 输入一组若干个整数用空格分隔,最后输入-1表示结束(-1不作为二叉排序树中的结点)

输出格式
第一~三行 前、中、后序遍历
第四行 树的结点个数

输入样例
50 20 10 80 70 -1

输出样例
50 20 10 80 70
10 20 50 70 80
10 20 70 80 50
5

思路:

层次遍历即可,都不用,输入时cnt就行了.

AC

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int ans=0;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *root;
node *newnode(){return new node();}
void insertion(node *&u,int key)
{
    if(u==NULL)
    {
        u=newnode();
        u->v=key;
    }
    else if(u->v>key)insertion(u->left,key);
    else if(u->v<key)insertion(u->right,key);
}
node* find(node*u,int key)
{
    if(!u||u->v==key)return u;
    if(u->v>key)return find(u->left,key);
    else if(u->v<key)return find(u->right,key);
}
void pre_order(node *u)
{
    if(u==NULL)return ;
    cout<<u->v<<' ';
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node *u)
{
    if(u==NULL)return ;
    in_order(u->left);
    cout<<u->v<<' ';
    in_order(u->right);
}
void post_order(node *u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v<<' ';
}
void bfs(node *u)
{
    queue<node*>q;
    if(root!=NULL)q.push(root);
    while(!q.empty())
    {
        node* top=q.front();q.pop();
      //  cout<<top->v<<' ';
      ans++;
        if(top->left)q.push(top->left);
        if(top->right)q.push(top->right);
    }
}
int main()
{
    root=NULL;
    int x;
    while(cin>>x)
    {
        if(x==-1)break;
        insertion(root,x);
    }
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;
    bfs(root);
    cout<<ans<<endl;
    return 0;
}

9497 利用递归实现查找中序遍历序列中第i个结点

时间限制:1000MS 代码长度限制:10KB
提交次数:815 通过次数:426题型: 编程题 语言: G++;GCC
Description创建一棵具有若干结点的二叉排序树,对其进行前、中、后序遍历并输出。最后查找中序遍历序列中第i个结点。
输入格式
第一行 树的结点个数
第二行 输入上一行指定的整数
第三行 输入一个待查找结点序号
第四行 输入一个待查找结点序号

输出格式
第一~三行输出前、中、后序遍历二叉树
第四行 结点值或相应提示
第五行 结点值或相应提示

输入样例
5
50 20 10 80 70
4
8

输出样例
50 20 10 80 70
10 20 50 70 80
10 20 70 80 50
70
Error

思路:

其实就是找到排完序后的第 i 个(二叉排序树的性质:中序遍历是升序

AC

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
vector<int>ans;
struct node
{
    int v;
    node *left,*right;
    node():left(NULL),right(NULL){}
};
node *root;
node *newnode(){return new node();}
void insertion(node *&u,int key)
{
    if(u==NULL)
    {
        u=newnode();
        u->v=key;
    }
    else if(u->v>key)insertion(u->left,key);
    else if(u->v<key)insertion(u->right,key);
}
void pre_order(node *u)
{
    if(u==NULL)return ;
    cout<<u->v<<' ';
    pre_order(u->left);
    pre_order(u->right);
}
void in_order(node *u)
{
    if(u==NULL)return ;
    in_order(u->left);
    cout<<u->v<<' ';
    ans.push_back(u->v);
    in_order(u->right);
}
void post_order(node *u)
{
    if(u==NULL)return;
    post_order(u->left);
    post_order(u->right);
    cout<<u->v<<' ';
}
int main()
{
    root=NULL;
    int n,x;
    cin>>n;
    For(i,1,n)
    {
        cin>>x;
        insertion(root,x);
    }
    pre_order(root);
    cout<<endl;
    in_order(root);//it is increase
    cout<<endl;
    post_order(root);
    cout<<endl;
    For(i,1,2)
    {
        cin>>x;
        if(x>n)cout<<"Error"<<endl;
        else cout<<ans[x-1]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值