【PAT A1020】Tree Traversals、树的存储以及数的遍历

11 篇文章 0 订阅
//9.1.3二叉树的存储结构与基本操作
//1:二叉树的存储结构

#include <iostream>
#include <queue>
#include<cstdio>
using namespace std;
//================基本知识回顾=======================
//1.1:二叉树的存储结构
struct node {
    int data;//数据域
    node* lchild;
    node* rchild;
    int layer;//记录树的层次
};
//1.2:二叉树建立前,根节点不存在,所以一般设为空
//node *root=NULL;
//1.3:新建节点(例如往二叉树中插入节点)
node* newNode(int v) {
    node* NODE = new node;//申请一个节点的地址空间
    NODE->data = v;
    NODE->lchild = NODE->rchild = NULL;
    return NODE;
};
//1.4:查找
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);
}
//1.5:插入
//1.5.1基本框架
void insert(node*& root, int x) {
    if (root == NULL) {//空树,说明查找失败,也即插入的位置
        root = newNode(x);
        return;
    }
    if (二叉树的性质,往左边插入) {
        insert(&root->lchild, x);

    }
    else insert(&root->rchild, x);
}
//1.5.2:使用应用&,与search中没有使用应用进行对比:
//1.5.2:如果函数中要新建节点,即结构做出修改,就需要加引用,如果只是修改当前已有的节点的内容,就不用加引用
//1.6:创建树
node* create(int data[], int n)
{
    node* root = NULL;
    for (int i = 0; i < n; i++)
    {
        insert(root, data[i]);
    }
    return root;
}
//1.6.1:区分*root==NULL与root==NULL
//1.6.1:前者为地址为空,后者表示不存在,为空树

//9.2:遍历
//9.2.1:前序;中序;后序都是递归实现,而层序遍历就是BFS()
//9.2.2:层序遍历的基本思路:
//9.2.2.1将根节点加入队列
//9.2.2.2取出队首元素,访问
//9.2.2.3如果有左孩子,入队
//9.2.2.4如果有右孩子,入队
//9.2.2.5返回9.2.2.2,直到队列为空

//
//================基本知识回顾=======================

int number;//BFS当中也要用,所以设为全局变量
int post[30], in[30];//
//struct node {
//    int data;//数据域
//    node* lchild;
//    node* rchild;
//    int layer;//记录树的层次
//};
//root=NULL;与*root=NULL的区别(节点不存在和节点存在但没有内容)
//前序;中序;后序都是递归实现,而层序遍历就是BFS()
int s = 0;
void layerOrder(node* root)//表示root是node指针型
{
    queue<node*>q;//存放根节点的队列,存的是地址,这样可以达到修改元素的目的
    q.push(root);
    root->layer = 1;//根的节点的层次设为1,并且要在递归的时候要进行处理
    while (!q.empty()) {
        node* now = q.front();//把头节点的信息记录下来
        q.pop();
        if (s < number - 1) { printf("%d ", now->data); s++; }//进行访问
        else printf("%d", now->data);
        //就是要将下一层节点依次入队
        if (now->lchild != NULL) { now->lchild->layer = now->layer + 1; q.push(now->lchild); }
        if (now->rchild != NULL) { now->rchild->layer = now->layer + 1; q.push(now->rchild); }
    }
}
//怎么重建树?至少要知道中序遍历才能区分左右子树
//已知先序和中序的顺序,利用递归,找到递归出口:当区间为0;
//继续找到左右子树的先序和中序的区间就行
node* create(int prel, int prer, int inl, int inr)
{
    //先把递归边界写好
    if (prel > prer)return NULL;
    //找根节点,前序遍历的第一个节点就是根节点
    //不要写成new node();返回这样的一块地址
    node* root = new node;//创建一个新的节点,用来存放根节点
    root->data = post[prer];
    //找左右子树的边界
    int i;
    for (i = inl; i <= inr; i++) {
        if (in[i] == post[prer])break;//找到了中序遍历的根节点
    }
    int numl = i - inl;//中序的左子树的长度
    //递归的建左右子树,只需要传入边界的参数
    //这是后序遍历的数组下标
    root->lchild = create(prel, prel + numl - 1, inl, inr + numl - 1);
    root->rchild = create(prel + numl, prer-1, inl + numl + 1, inr);
    return root;
}
int main()
{
    //给出后序遍历的顺序和中序遍历的顺序,完成层序遍历的输出
    //根据后序和中序进行建树,然后再按BFS进行层序的输出
    cin >> number;
    /*scanf("%d", &number);*/
    int i;
    for (i = 0; i < number; i++)
    {
        cin >> post[i];

      /*  scanf("%d", &post[i]);*/
    }
    for (i = 0; i < number; i++)
    {
        cin >> in[i];
       /* scanf("%d", &in[i]);*/
    }
    //建树;
//    node Tree=new node();//不需要进行创建新的节点,只要创建一个根节点指针
    node* root = create(0, number - 1, 0, number - 1);
    layerOrder(root);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值