2024王道408数据结构 P143 T6

2024王道408数据结构 P143 T6

程序能一直循环,为什么人不能循环呆在自己喜欢的时间里

思考过程

  1. 首先明确题目然后我们做什么,给我们一个先序遍历和中序遍历,让我们把整个树的二叉链表求出来,也就是把这个树给建立起来。那么我们先要学会怎么用先序遍历和中序遍历来构建一个树。
  • 肉眼思考通过先序遍历和中序遍历构建树

    1. 假设先序遍历为DLR:ABDECF,中序遍历为LDR:DBEAFC,首先能明确A是树的根结点,因为先序遍历的第一个元素就是根结点,其次在中序遍历里观察,A的左边DBE就是A的左子树,FC就是A的右子树,所以我们能基本判断树长这个样子请添加图片描述
    2. 之后再看先序遍历,能判断出来B就是左子树的根结点,再看中序遍历也能判断D是B的左孩子,E是B的右孩子。请添加图片描述
    3. ABDE都确定了再看先序遍历,能判断C是根结点,再看中序遍历就能得出F是C的左孩子,自己推一遍就明白了。请添加图片描述
  1. 想明白这点后回到题目中,首先我们需要一个范围,也就是题目中数组的大小,我们设定start和end,start初始化为1,end为结点个数。建立函数时不仅把先序遍历和中序遍历传进去,还要把start和end传进去。
  2. 首先确保s<=e才进行后续的操作,我们先给根结点root开一个空间的大小,struct TreeNode *root = (struct TreeNode*)malloc(sizeof(struct TreeNode);就按上面这个例子来看,给他的data赋值为A,这里要注意赋值如果是root->data=A[0],如果是这样赋值的话显然不符合我们的预期,如果这样写那他的左右子树以后都赋值为A了,所以我们要建立一个pos变量,先给他初始化为0,赋值完之后让pos++,这样就考虑到了他的左右子树的赋值,接下来就开始创建他的左右子树了。
  3. 我们先用for循环用变量i去遍历中序遍历,从start开始,一直到end结束。当i遍历到A时停止循环,if(B[i] == root->data) break;表示此时我们遍历到的东西都是A的左子树,这跟我们上面用肉眼去构建二叉树一样。此时i是指向A的,之后我们只需要递归建立root的左右子树,root->lchild = bulid(A, B, s, i-1)注意这里要从start开始,从i-1结束,也就是图中的DBE,请添加图片描述右子树也是一样root->rchild = build(A, B, i+1, e)从i+1开始,从end结束。一直这样递归我们这题就算做完了。

举个例子

  1. 我们就用上面root->lchild = build(A,B,s, i-1)来举例子好了,程序运行到这里时再次调用自己来构建A的左子树,给root根结点开空间,开完空间去赋值,还记得上面我们说过不能给树的根结点直接赋值A[0]吗,我们用了一个pos遍历,此时的pos时指向B的,root就被赋值成了B,然后再pos++。
  2. 再用for循环用i去遍历中序遍历,当遍历到结点B时就停止,if (B[i] == root->data) break;表示当前我们遍历过的东西就是B的左子树,此时i是指向B的请添加图片描述就继续用递归去构建B的左子树和右子树,root->lchild(A,B,s,i-1)这里也要注意从s开始和到i-1结束,root->rchild = build(A,B,i+1,e)从i+1开始,到e结束。B的右子树也同理。

完整代码

//
// Created by 黎圣  on 2023/8/11.
//
#include "iostream"
struct TreeNode
{
    char data;
    struct TreeNode *lchild, *rchild;
};
//pos是全局变量
int pos = 0;
struct TreeNode *build(char A[], char B[], int s, int e)
{
    if (s <= e)
    {
        struct TreeNode *root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
        root->data = A[pos];
        int i = 0;
        for (i = s; i <= e; i++)
            if (B[i] == root->data)
                break;
        pos++;
        root->lchild = build(A, B, s, i - 1);
        root->rchild = build(A, B, i + 1, e);
        return root;
    }
    return NULL;
}
//把后序遍历序列打印出来方便观察,写题目时不用写出来。
void display(struct TreeNode *&t)
{
    if (t)
    {
        display(t->lchild);
        display(t->rchild);
        printf("%c ", t->data);
    }
}
int main()
{
    struct TreeNode *t;
    //因为题目上范围是从1开始,所以这里我们把下标为0的地方空出来了,保证跟题目一致
    char A[] = {' ','A','B','D','E','C','F'};
    char B[] = {' ','D','B','E','A','F','C'};
    t = build(A, B, 1, 6);
    display(t);
    return 0;
}

这题比较容易忘的就是pos++,最后感谢b站up主@吸血小金鱼。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值