ltx_zero

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

二叉树,可以用指针来存也可以用数组来存,使用数组的时候应该是完全二叉树。

在数组存储的方式中(认为根节点是1),当前节点是x,左子孩子是2*x,到第n层有2^n-1个节点。要判断为空,就是下标大于节点总个数,判断有无子树就用2*x和n判断。

在指针存储的时候,记得初始化root为node*root=NULL,所有的新节点左右子树都是NULL

root=NULL,root->lchild=NULL,root->rchild=NULL,代表的是他们没有指向。

定义的时候是指针,在修改其指向的内容的时候正常修改就行(一直指向A,A里面元素被改了),如果修改其内容(就是修改指针指向的对象,由指向A变成指向B)要使用引用

里面的change(node*&root),要这种格式,别忘了还是指针,要有*,在调用的时候直接change(root)就可以。

#include<stdio.h>
struct node{
    int data;
    node*lchild;
    node*rchild;
};
node*root=NULL;//建树之前不存在,初始为空
node*newNode(int v)
{
    node*Node=new node;
    Node->data=v;
    Node->lchild=NULL;
    Node->rchild=NULL;
    return Node;
}//新建节点
void search(node*root,int x,int newdata)
{
    if(root==NULL)
        return ;
    if(root->data==x)
        root->data=newdata;
    search(root->lchild,x,newdata);
    search(root->rchild,x,newdata);
}
void insert(node*&root,int x)
{
    if(root==NULL)
    {
        root=newNode(x);
        return;
    }
    if(root->data==1)//什么条件在左子树插入
        insert(root->lchild,x);
    else
        insert(root->rchild,x);
}
node*Create(int data[],int n)
{
    node*root=NULL;
    for(int i=0;i<n;i++)
        insert(root,data[i]);
    return root;
}
View Code

指针中几个常用的操作代码如上。

先中后序还有层次遍历递归实现代码如下

#include<stdio.h>
#include<queue>
using namespace std;
struct node{
    int data;
    node*lchild;
    node*rchild;
};
node*newNode(int v)
{
    node*Node=new node;
    Node->data=v;
    Node->lchild=NULL;
    Node->rchild=NULL;
    return Node;
}
void preOrder(node*root)
{
    if(root==NULL)
        return;
    printf("%d",root->data);
    preOrder(root->lchild);
    preOrder(root->rchild);
}
void inOrder(node*root)
{
    if(root==NULL)
        return;
    inOrder(root->lchild);
    printf("%d",root->data);
    inOrder(root->rchild);
}
void postOrder(node*root)
{
    if(root==NULL)
        return;
    postOrder(root->lchild);
    postOrder(root->rchild);
    printf("%d",root->data);
}
void LayerOrder(node*root)
{
    queue<node*>q;
    q.push(root);
    node*temp=q.front();
    while(!q.empty())
    {
        node*temp=q.front();
        q.pop();
        if(temp->lchild!=NULL)
            q.push(temp->lchild);
        if(temp->rchild!=NULL)
            q.push(temp->rchild);
        printf("%d",temp->data);
    }
}
int main()
{
    node *root=newNode(1);
    root->lchild=newNode(2);
    root->rchild=newNode(3);
    root->lchild->lchild=newNode(4);
    root->lchild->rchild=newNode(5);
    root->rchild->rchild=newNode(6);
    preOrder(root);
    printf("\n");
    inOrder(root);
    printf("\n");
    postOrder(root);
    printf("\n");
    LayerOrder(root);
    printf("\n");
    return 0;
}
View Code

注意,给定中序遍历和先后层次中任意一个,可以确定二叉树,给后面中的两个是不能确定的。中序用于确定左右子树,后面三个任一个都可以确定根节点。

这里面的生成条件,需要子树里面的data没有重复的元素。

PAT A1020给定后序中序生成二叉树,并以层次遍历输出

这个需要注意,要求结尾没有多余空格,加个判断就行。

具体思路就是,每次最尾的是根节点,根节点在中序中判断左右子树以后,求出左右子树的节点数目,再划分出后序里面哪些属于左右,前转中同理。

#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
int n;
int in[35];
int post[35];
struct node
{
    int data;
    node*lchild;
    node*rchild;
};
void level(node*root)
{
    queue<node*>q;
    q.push(root);
    while(!q.empty())
    {
        node*temp=q.front();
        q.pop();
        if(temp->lchild!=NULL)
            q.push(temp->lchild);
        if(temp->rchild!=NULL)
            q.push(temp->rchild);
        if(!q.empty())
            printf("%d ",temp->data);
        else
            printf("%d",temp->data);
    }
}
node* change(int inl1,int inr1,int post1,int post2)
{
    if(inl1>inr1) return NULL;
    node*root=new node;
    root->data=post[post2];
    //printf("here:%d\n",root->data);
    int temp=-1;
    for(int i=inl1;i<=inr1;i++)
    {
        if(in[i]==post[post2])
        {
            temp=i;
            break;
        }
    }
    if(temp!=-1)
    {
        root->lchild=change(inl1,temp-1,post1,post1+temp-inl1-1);
        root->rchild=change(temp+1,inr1,post1+temp-inl1,post2-1);
    }
    return root;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&post[i]);
    for(int i=0;i<n;i++)
        scanf("%d",&in[i]);
    level(change(0,n-1,0,n-1));
    return 0;
}
View Code

如果题目考察层次遍历和中序,那么是选中根节点,划分左右子树以后,使用vector,然后判断中序中左右出现的节点和层次中相同,(根据其在层次遍历中的顺序)加入左或者右对应的数组,再进行下一轮递归。

posted on 2020-02-20 13:33  ltx_zero  阅读(137)  评论(0编辑  收藏  举报