基于后序遍历(非递归)的一些应用(输出最长路径上的结点,求 p,q最近的公共结点,在二叉树中查找值为x的结点,打印x结点的祖先等)

本文详细介绍了二叉树的后序遍历非递归算法,使用tag标记实现,包括查找特定节点及其祖先、求两个节点的最近公共祖先及输出最长路径上的节点。这些算法在计算机科学和数据结构领域有着广泛的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int maxSize = 1000;
//这个是重点
//后序遍历非递归,tag标记实现
void postOrderTraverse_non_recursion3(Tree T)
{
    int top = 0;
    int tag[maxSize];//tag标记该结点右分支是否被访问过,只有当该节点的右分支访问过了才能访问根节点
    Tree p = T;
    Tree S[maxSize];//S作为栈

    while(p!=NULL||top>0)
    {
        while(p!=NULL)//沿左分支遍历
        {

            S[++top] = p;//入栈
            tag[top] = 0;
            p = p->lchild;

        }//end while

        while(top>0&&tag[top] == 1)//该节点的右分支访问过了,则可以访问该节点
        {

            Visit(S[top]);
            top--;

        }

        if(top>0)//沿右分支遍历
        {

            tag[top] = 1;//标记该右分支已遍历
            p = S[top]->rchild;

        }
    }//end while

}//end postOrderTraverse_non_recursion3



//基于后序非递归(tag标记)的题目
//在二叉树中查找值为x的结点,打印x结点的祖先
/*
    基本思想,后序遍历找到该节点,栈中存放的就是该节点的到根节点的路径
    tag[]标记实现

*/


void serch(Tree T,int x)
{
    int top =0;
    int tag[maxSize];//基于后序非递归(tag标记)的题目
//求 p,q最近的公共结点

    Tree p = T;
    Tree S[maxSize];

    while(p!=NULL&&top>0)
    {
        while(p!=NULL)//沿左分支寻找
        {
            S[++top] = p;
            tag[top] = 0;
            p = p->lchild;
        }
        while(top>0&&tag[top] == 1)//右分支访问过了
        {
            if(p->data == x)//找到该节点,则栈中的结点就是其祖先
                for(int i=1; i<=top; i++)
                    Visit(S[i]);

            top--;//访问则出栈
        }

        if(top>0)//沿右分支寻找
        {
            tag[top] = 1;
            p = S[top]->rchild;
        }
    }//end while
}//end search




//基于后序非递归(tag标记)的题目
//求 p,q最近的公共结点

/*

    基本思想:
    1.后序遍历到p时则栈内的结点都是p的祖先
    2.将其复制到另外一个栈中继续遍历到q
    3.比较2栈的结点,第一个相同的结点即为最近公共结点

*/
Tree findAncestor(Tree T,Tree p,Tree q)
{

    int top1,top2;
    int tag1[maxSize],tag2[maxSize];

    Tree S1[maxSize],S2[maxSize];

    Tree pT =T;

    while(pT!=NULL||top1>0)
    {
        while(pT!=NULL)
        {

            S1[++top1] = pT;
            tag1[top1] = 0;

            pT = pT->lchild;

        }

        while(top1>0&&tag1[top1] == 1)//右分支访问过了
        {
            if(S1[top1] == p) //将S1复制给S2
            {
                for(int i=1; i<=top1; i++)
                    S2[i] = S1[i];

                top2 = top1;
            }

            if(S1[top1] == q)//找到q,则对比2栈内的结点,第一个相同的结点就是最近公共结点
            {
                for(int i=top1;i>0;i--)
                    for(int j=top2;j>0;j--)
                        if(S1[i] == S2[j])
                            return S1[i];//找到公共结点
            }

            top1--;//访问出栈
        }//end while

        if(top1>0)
        {
            tag1[top1] = 1;
            pT = S1[top1]->rchild;
        }

    }//end while

    return NULL;
}

//输出最长路径上的结点(考过多年)(重点)

/*
    基本思想:
    后序非递归(tag标记实现方法)
    1.当该=遍历到该结点没有左右孩子结点的时候,记录当前路径长度并于最长路径长度比较
    2.最后输出最长路径
*/
void longPath(Tree T)
{
    int top =0;
    int longSet = 0;//初始化最长路径长度

    int tag[maxSize];

    Tree p = T,S[maxSize],Temp[maxSize];//S为存放最长路径上的结点,Temp为临时存放

    while(p!=NULL||top>0)
    {
        while(p!=NULL)//沿着左分支寻找
        {
            S[++top] = p;
            tag[top] = 0;

            p = p->lchild;

        }//end while

        while(top>0&&tag[top] == 1)
        {
            //当该结点没有左右孩子结点的时候记录路径长度,并于最长路径长度进行比较来更新最长路径长度
            if(S[top]->lchild == NULL &&S[top]->rchild == NULL)
                if(top>longSet)//更新最长路径
                {
                    for(int i=1;i<=top;i++)
                        Temp[i] = S[i];

                    longSet =top;
                }

            top--;
        }//end while

        if(top>0)
        {
            tag[top] = 1;
            p = S[top]->rchild;
        }
    }//end while
}//end longPath

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值