2024王道408数据结构 P144 T12

2024王道408数据结构 P144 T12

思考过程

  1. 首先看清楚题目的意思,题目要我们查找值为x的结点的所有祖先,我们用一个辅助栈来帮我们实现后序遍历。
  2. 我们需要一个tag值,用来判断这个结点是否遍历了左右子树,如果tag=0的话就说明该结点的左子树已经访问过,如果tag=1的话说明该结点的右子树已经访问过。
  3. 每遍历完该结点的左子树后就把tag值赋为0,把该结点入栈,然后开始判断该结点的值是否等于x,不等于的话继续遍历左子树。
  4. 当我们把所有左子树遍历完后发现值仍不为x,再开始遍历右子树。

举个例子

  1. 假设二叉树长这个样子请添加图片描述然后我们再设立一个辅助栈来帮我们实现后序遍历。
  2. 那既然是后序遍历首先就要从根结点开始沿着左子树一路入栈,入栈的同时把这些元素的tag值都赋为0,表示这些结点的左子树都已经访问过了。
  3. 就拿上面这颗二叉树来举例子,假设我们要找的结点x是G。先把根结点A入栈,s[++top].t = t;top指针指向栈顶元素,把A都tag值赋为0,s[top].tag=0;然后开始判断
    • 如果此时t->data==x就说明我们已经找到了题目所说的x结点,我们就把此时栈中的元素依次输出,printf("%c",t->data);
    • 如果此时t的data值不为x,那就继续遍历该结点的左子树,在例子中也就是Bt = t->lchild;,并把B也入栈,把它的tag值也赋为0,然后再判断,发现不等于x把D也入栈。然后发现D没有左子树,就退出循环。请添加图片描述
  4. 当我们把左子树全部遍历完后发现栈顶元素还不等于x,那我们就开始把右子树也入栈t=s[top].t->rchild;然后要记得遍历完该结点的右子树后把它的tag值赋为1,表示已经遍历完该结点的右子树。在例子中先判断D的右子树是否存在,这里发现D没有右子树,我们就把D的tag值赋为1。
  5. 此时top指针指向栈顶元素D,发现D的tag值为1,我们就把D给出栈。出栈后top指向B,就去判断B有无右子树,例子中发现B有右子树为E,我们就把E入栈,此时B的tag值也赋为1。
  6. 然后发现E没有左右子树,把E的tag值赋为1,我们就把E出栈,发现B的tag值也为1,就把B也出栈,然后去判断A的右子树,以此类推。请添加图片描述
  7. 当我们找到目标x值G时,此时栈中元素为CA,我们就把栈中的元素给输出就好了,这题就做完了。

完整代码

//
// Created by 黎圣  on 2023/8/19.
//
#include "iostream"
#define MAX 15
typedef struct TreeNode
{
    char data;
    struct TreeNode *lchild, *rchild;
}*tree;
struct Stack
{
    struct TreeNode *t;
    int tag;//tag=0左孩子已将访问过,tag=1表示右孩子已经访问过
};
void CreateTree(tree &t)
{
    char ch = getchar();
    if (ch == '#')
        t = NULL;
    else
    {
        t = (struct TreeNode*)malloc(sizeof(struct TreeNode));
        t->data = ch;
        t->lchild = NULL;
        t->rchild = NULL;
        CreateTree(t->lchild);
        CreateTree(t->rchild);
    }
}
void print_parent(tree t, char x)
{
    Stack s[10];
    int top = 0;
    while (t != NULL || top > 0)
    {
        //从根结点开始向左延伸压入栈中 井且 结点的值不为x
        while (t != NULL && t->data != x)
        {
            s[++top].t = t;
            s[top].tag = 0;
            t = t->lchild;
        }
        //如果找到了值为x的结点 将栈中的结点值输出
        if (t != NULL && t->data == x)
        {
            for (int i = 1; i <= top; i++)
                printf("%c", s[i].t->data);
            break;
        }
        //判断当前栈顶的结点的tag值为1的活 依次退桟
        while (top != 0 && s[top].tag == 1)
        {
            top--;
        }
        //当前栈顶不为0 将栈顶的taq值赋值为1 结点指向该结点的右孩子
        if (top != 0)
        {
            s[top].tag = 1;
            t = s[top].t->rchild;
        }
    }
}
int main()
{
    tree t;
    CreateTree(t);
    //ABD##E##CF##G##
    print_x(t, 'G');
    return 0;
}

这题好难☹️,最后感谢b站up主@吸血小金鱼

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值