二叉树问题综合求解

6 玩转二叉树   (25分)

给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N\le30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
1 2 3 4 5 6 7
4 1 3 2 6 5 7

输出样例:

4 6 1 7 5 3 2
#include "iostream"
#include "queue"
#include "stdio.h"
using namespace std;
#define Max 51

int Pre[Max],Mid[Max],N;
struct Node
{
   int Data;
   Node *Left;
   Node *Right;
   Node ()
   {
   	  Left=NULL;
   	  Right=NULL;
   }
};
void CreatTree(int PreLeft,int MidLeft,int Len,Node *&p)
{
      if(Len<=0)
      {
      	return ;
      }
      p=new Node;
      p->Data=Pre[PreLeft];  
      int len,i=MidLeft;
      while(Pre[PreLeft]!=Mid[i])	
      i++;   
      len=i-MidLeft;
      CreatTree(PreLeft+1,MidLeft,len,p->Left);
      CreatTree(PreLeft+len+1,i+1,Len-len-1,p->Right);
}
void Output(Node *p)
{
      
     
        cout<<p->Data;
    
        queue<Node *> Q;
         if(p->Left!=NULL)
	    {
	    	Q.push(p->Left);
	    }
	    if(p->Right!=NULL)
	    {
	    	 Q.push(p->Right);
	    }
    
      
      
     while(!Q.empty())
     {
        Node *s=Q.front();
        Q.pop();
	    cout<<" "<<s->Data ;
	    if(s->Left!=NULL)
	    {
	    	Q.push(s->Left);
	    }
	    if(s->Right!=NULL)
	    {
	    	 Q.push(s->Right);
	    }
	
    }
	  	   
}
void Swap(Node *p )
{   
    if(p==NULL) return;
	Swap(p->Left);
	Swap(p->Right); 
	Node *s;
    s=p->Left;
    p->Left=p->Right;
    p->Right=s;
}



int main()
{
	
	 //freopen("1.txt","r",stdin);
	cin>>N;
	Node *Tree;
	Tree=NULL;
	int i,j;
	for(i=1;i<=N;i++)
	{
		cin>>Mid[i];
	}
	for(j=1;j<=N;j++)
	{
		cin>>Pre[j];
	}
	CreatTree(1,1,N,Tree);
	Swap(Tree);
	Output(Tree);
	cout<<endl;
	
	
	return 0;
}

L3-010. 是否完全二叉搜索树

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。

输入格式:

输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。

输出格式:

将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出“YES”,如果该树是完全二叉树;否则输出“NO”。

输入样例1:
9
38 45 42 24 58 30 67 12 51
输出样例1:
38 45 24 58 42 30 12 67 51
YES
输入样例2:
8
38 24 12 45 58 67 42 51
输出样例2:
38 45 24 58 42 12 67 51
NO
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
int tree[200],le[200],ri[200],cnt=0,path[200],p=0,idd[200];
bool flag;
//建树
void insert(int x,int v,int id)
{
    if(tree[x]==0)
	{
		tree[x]=v;
		idd[x]=id;
		cnt++;
	}
	else
	{
		if(v>tree[x])
		{
			if(le[x]==0)
			  le[x]=cnt+1;
			insert(le[x],v,id*2);
		}
		else
		{
           if(ri[x]==0)
			   ri[x]=cnt+1;
		   insert(ri[x],v,id*2+1);
		}
	}
}
//层序遍历
void solve()
{
	int cur;
	queue <int> qe;
	qe.push(0);
	while(!qe.empty())
	{
       cur=qe.front();
	   qe.pop();
	   //是否是完全二叉树的判断
	   if(p+1<idd[cur])
		   flag=0;
	   path[p++]=tree[cur];
	   if(le[cur]&&ri[cur])
	   {
		   qe.push(le[cur]);
		   qe.push(ri[cur]);
	   }
	   else if(le[cur]||ri[cur])
	   {
		   if(le[cur])
		     qe.push(le[cur]);
           else
			 qe.push(ri[cur]);
	   }
	}
}
int main()
{
	int n,tmp;
	scanf("%d",&n);
    for(int i=1;i<=n;i++)
	{
		scanf("%d",&tmp);
		insert(0,tmp,1);
	}
	flag=1;
	solve();
	printf("%d",path[0]);
	for(int i=1;i<p;i++)
	{
		printf(" %d",path[i]);
	}
	printf("\n");
	if(flag)
		printf("YES\n");
	else
		printf("NO\n");
	return 0;
}
另一种方法处理

    
    
#include <stdio.h> #include <algorithm> #include <string.h> #include <queue> #include <iostream>
using namespace std;
typedef long long ll; const int N = 25;
typedef struct Tree {     Tree *left;     Tree *right;     int val; }Tree;
Tree *root; int seq[N], cnt, n;
Tree *creat(int num) {     Tree *node = (Tree*)malloc(sizeof(Tree));     node->left = NULL;     node->right = NULL;     node->val = num;     return node; }
Tree *insertt(Tree *node, int num) {     if(node == NULL)     {         node = creat(num);     }     else     {         if(num > node->val) node->left = insertt(node->left, num);         else if (num < node->val) node->right = insertt(node->right, num);     }     return node; }
void levelorder(Tree *cur) {     queue<Tree*>que;     while(!que.empty()) que.pop();     que.push(cur);     Tree *node;     int flag = 0, vis = 0;//flag判断是否是完全二叉树,vis判断是否访问过     while(!que.empty())     {         node = que.front();         que.pop();
        //判断完全二叉树         if(!vis)         {             if((node->left==NULL && node->right==NULL) || (node->left!=NULL && node->right==NULL))             {                 flag = 1;                 vis = 1;             }             else if(node->left==NULL && node->right!=NULL)             {                 flag = 0;                 vis = 1;             }         }         else         {             if(node->left!=NULL || node->right!=NULL) flag = 0;         }
        if(cnt == n-1) printf("%d\n", node->val);         else         {             printf("%d ", node->val);             cnt++;         }         if(node->left != NULL) que.push(node->left);         if(node->right != NULL) que.push(node->right);     }     if(flag) printf("YES\n");     else printf("NO\n"); }
void build() {     root = NULL;     cnt = 0;     for(int i = 0; i < n; i++)     {         int num = seq[i];         root = insertt(root, num);     } }
int main() {   //  freopen("in.txt", "r", stdin);     while(~scanf("%d", &n))     {         for(int i = 0; i < n; i++)             scanf("%d", &seq[i]);         build();         levelorder(root);     } }

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

  • x is the rootx是根结点;
  • x and y are siblingsxy是兄弟结点;
  • x is the parent of yxy的父结点;
  • x is a child of yxy的一个子结点。

输入格式:

每组测试第1行包含2个正整数N\le 1000)和M\le 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[-10000, 10000][10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出T,否则输出F

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>

using namespace std;

int n, a[1005];

//建树的 “模板”
void up( int son )
{
    int t = a[son];
    int tson = son;
    while( (tson > 1)&&( a[tson/2] > t))
    {
        a[tson] = a[tson/2];
        tson = tson/2;
    }
    a[tson] = t;
}

void charu( int  t)
{
    a[ ++n ] = t;
    up( n );
}


int main ()
{
    int k, m, x, y;;
    map <int, int> index; //记录下标
    string s;
    cin >> k >> m;
    n=0;
    //建树
    for(int i=0; i<k; i++)
    {
        cin >> x;
        charu(x);
    }
    //给map赋值
    for(int i=1; i<=n; i++)
    {
        index[a[i]] = i;
    }
    for(int i=0; i<m; i++)
    {
        cin >> x;
        cin >> s;
        int index_x = index[x]; 
        int index_y;
        if(s[0] == 'a')
        {
            cin >> y;
            getline(cin, s);  //这个函数可以输入一个带空格的字符串
            index_y = index[y];
            if(index_x/2 == index_y/2)
                puts("T");
            else
                puts("F");
        }
        else
        {
            cin >> s;
            cin >> s;
            if(s[0] == 'r')
            {
                if(index_x == 1)
                    puts("T");
                else
                    puts("F");
            }
            else if(s[0] == 'p')
            {
                cin >> s;
                cin >> y;
                index_y = index[y];
                if(index_y/2 == index_x)
                    puts("T");
                else
                    puts("F");

            }
            else
            {
                cin >> s;
                cin >> y;
                index_y = index[y];
                if(index_x/2 == index_y)
                    puts("T");
                else
                    puts("F");
            }
        }
    }

    return 0;
}

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

  • 其左子树中所有结点的键值小于该结点的键值;
  • 其右子树中所有结点的键值大于等于该结点的键值;
  • 其左右子树都是二叉搜索树。

所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

typedef struct node
{
    int data;
    struct node *l;
    struct node *r;
}Node;
int s[1010];
int v[1010];
int tmp;
void create1(Node *root,int x)//构造原二叉树
{
    Node *p;
    if(x<root->data)
    {
        if(root->l==NULL)
        {
            p = new Node;
            p->data = x;
            p->l = NULL;
            p->r = NULL;
            root->l = p;
            return;
        }
        else
            create1(root->l,x);
    }
    else
    {
        if(root->r==NULL)
        {
            p = new Node;
            p->data = x;
            p->l = NULL;
            p->r = NULL;
            root->r = p;
            return;
        }
        else
            create1(root->r,x);
    }
}
void create2(Node *root,int x)//构造镜像二叉树
{
    Node *p;
    if(x>=root->data)
    {
        if(root->l==NULL)
        {
            p = new Node;
            p->data = x;
            p->l = NULL;
            p->r = NULL;
            root->l = p;
            return;
        }
        else
            create2(root->l,x);
    }
    else
    {
        if(root->r==NULL)
        {
            p = new Node;
            p->data = x;
            p->l = NULL;
            p->r = NULL;
            root->r = p;
            return;
        }
        else
            create2(root->r,x);
    }
}
void firstvisit(Node *p)
{
    if(p!=NULL)
    {
        v[tmp++] = p->data;
        firstvisit(p->l);
        firstvisit(p->r);
    }
}
void lastvisit(Node *p)
{
    if(p!=NULL)
    {
        lastvisit(p->l);
        lastvisit(p->r);
        v[tmp++] = p->data;
    }
}
int main()
{
    int n,flag;
    Node *root,*toor;
    root = NULL;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&s[i]);
        if(i==0)//构造根节点
        {
            root = new Node;
            root->data = s[i];
            root->l = NULL;
            root->r = NULL;
            toor = new Node;
            toor->data = s[i];
            toor->l = NULL;
            toor->r = NULL;
        }
        else
        {
            create1(root,s[i]);
            create2(toor,s[i]);
        }
    }
    tmp = 0;
    flag = 1;
    firstvisit(root);
    for(int i=0;i<n;i++)
    {
        if(s[i]!=v[i])
        {
            flag = 0;break;
        }
    }
    if(flag==1)
    {
        printf("YES\n");
        tmp=0;
        lastvisit(root);
        for(int i=0;i<n;i++)
        {
            printf("%d",v[i]);
            if(i!=n-1)
                printf(" ");
        }
    }
    else
    {
        tmp=0;
        flag =1;
        firstvisit(toor);
        for(int i=0;i<n;i++)
        {
            if(s[i]!=v[i])
            {
                flag=0;break;
            }
        }
        if(flag==1)
        {
            printf("YES\n");
            tmp=0;
            lastvisit(toor);
            for(int i=0;i<n;i++)
            {
                printf("%d",v[i]);
                if(i!=n-1)
                    printf(" ");
            }
        }
        else
            printf("NO");
    }
    return 0;
}


给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

  1. #include <iostream>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <stdlib.h>  
  5. #define SizeMax 105  
  6. using namespace std;  
  7. typedef struct Node  
  8. {  
  9.     int data;  
  10.     Node* lchild;  
  11.     Node* rchild;  
  12. } Node;  
  13. Node *CreateBT2(int *post,int *in,int n)  
  14. {  
  15.     Node *b;  
  16.     int r,*p,k;  
  17.     if(n<=0)return NULL;  
  18.     r=*(post+n-1);  
  19.     b=(Node*)malloc(sizeof(Node));  
  20.     b->data=r;  
  21.     for(p=in; p<in+n; p++)  
  22.         if(*p==r)break;  
  23.     k=p-in;  
  24.     b->lchild=CreateBT2(post,in,k);  
  25.     b->rchild=CreateBT2(post+k,p+1,n-k-1);  
  26.     return b;  
  27. }  
  28. void Print(Node *r)  
  29. {  
  30.     Node *p;  
  31.     Node *pr[SizeMax];  
  32.     int rear=-1,front=-1;  
  33.     rear++;  
  34.     pr[rear]=r;  
  35.     while(rear!=front)  
  36.     {  
  37.         front=(front+1)%SizeMax;  
  38.         p=pr[front];  
  39.         printf("%d ",p->data);  
  40.         if(p->lchild!=NULL)  
  41.         {  
  42.             rear=(rear+1)%SizeMax;  
  43.             pr[rear]=p->lchild;  
  44.         }  
  45.         if(p->rchild!=NULL)  
  46.         {  
  47.             rear=(rear+1)%SizeMax;  
  48.             pr[rear]=p->rchild;  
  49.         }  
  50.     }  
  51. }  
  52. int main()  
  53. {  
  54.     int N;  
  55.     scanf("%d",&N);  
  56.     int a[N],b[N];  
  57.     for(int i=0; i<N; i++)  
  58.         scanf("%d",a+i);  
  59.     for(int i=0; i<N; i++)  
  60.         scanf("%d",b+i);  
  61.     Node* result=CreateBT2(a,b,N);  
  62.     Print(result);  
  63.     return 0;  
  64. }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值