王道书 P150 T18(在中序线索二叉树里找指定节点在后序的前驱节点)+ 拓展(在中序线索二叉树里找指定节点在先序的后继节点)

目录

 在中序线索二叉树里找指定节点在后序的前驱节点

 在中序线索二叉树里找指定节点在先序的后继节点


 在中序线索二叉树里找指定节点在后序的前驱节点

/**
 * 用二叉树链式存储实现 王道 P150 T18

 * ①算法思想
 * ①在中序线索二叉树里找指定节点在后序的前驱节点
 * ②在中序线索二叉树里找指定节点在先序的后继
 * 关于①:
 * 如果p有右孩子,那么p的右孩子就是p的前驱。
 * 如果p没有右孩子,但是有左孩子,那么p的左孩子就是p的前驱。
 * 但如果p是叶子节点:
 * 如果p是一个偏左行为的节点(想象成左下角的一个),那么它一定是第一个遍历的,他就不会有前驱。
 * 如果p是一个偏右行为的节点(想象成右下角的一个),那么它有可能有前驱,也有可能没有,得在这个节点的左边找一找。
 * 关于②:
 * 如果p有左孩子,那么p的左孩子就是p的后继。
 * 如果p没有左孩子,但是有右孩子,那么p的右孩子就是p的后继。
 * 但如果p是叶子节点:
 * 如果p是一个偏右行为的节点(想象成右下角的一个),那么它一定是最后一个遍历的,他就不会有后继。
 * 如果p是一个偏左行为的节点(想象成左下角的一个),那么它有可能有后继,也有可能没有,得在这个节点的右边找一找。
 *
 *
 * ②算法设计
 */


#include <stdio.h>
#include <iostream>
#define MaxSize 100

typedef struct ThreadBiTreeNode{
    int data;
    struct ThreadBiTreeNode *lchild,*rchild,*parent;//parent域指向双亲结点
    int ltag,rtag;
    int weight;//如果给叶子节点赋权值的话会用到
}ThreadBiTreeNode,*ThreadBiTree;


//P150 T18
//①在中序线索二叉树里找指定节点在后序的前驱节点
ThreadBiTree InFindNodePostPre(ThreadBiTree p){
    if(p -> rtag == 0){//说明p一定有右孩子,那么p的前驱就是右孩子
        return p -> rchild;
    }else if(p -> ltag == 0){//如果p没有右孩子,但是有左孩子,那么p的前驱就是p的左孩子
        return p -> lchild;
    }else{//如果p是叶子节点:((注意为什么后序找前驱不用考虑这个情况?
        //因为不需要考虑到,要是在后序中p是叶子结点的话就可以直接return p -> ltag了。
        //这也正是在先序中找某个节点在后序中的前驱的麻烦之处。))
        //①如果p是一个偏左行为的节点(想象成左下角的一个),那么它一定是第一个遍历的,他就不会有前驱。
        if(p -> lchild == NULL)//p现在是叶子节点,所以p -> lchild == NULL 相当于p在中序序列中没有前驱,那么p在后序序列中也没有前驱
            return NULL;
        //②如果p是一个偏右行为的节点(想象成右下角的一个或者是右子树中的一个),那么它有可能有前驱,也有可能没有,得在这个节点的左边找一找。
        while(p -> lchild != NULL && p -> ltag == 1){//一直向上找直到找到一个点有左孩子
            //因为p是叶子节点,所以p -> lchild就是它在~中序~中的前驱,
            //这是一个一直向上找的过程,如果向上找的时候遇到某个节点他有左孩子,那么这个左孩子就是p在后序中的前驱
            p = p -> lchild;//一直在向上找
        }
        if(p -> ltag == 0)//说明是因为p->ltag!=1结束循环的,说明向上找到了一个节点,这个节点有左孩子,那么这个左孩子就是p的前驱。
            return p -> lchild;
        else//说明是因为p -> lchild == NULL 结束while的,那么这就是一个单支树,p就不会有前驱。
            return NULL;
    }
}

 

 

 在中序线索二叉树里找指定节点在先序的后继节点

/**
 * 用二叉树链式存储实现 王道 P150 T18

 * ①算法思想
 * ①在中序线索二叉树里找指定节点在后序的前驱节点
 * ②在中序线索二叉树里找指定节点在先序的后继
 * 关于①:
 * 如果p有右孩子,那么p的右孩子就是p的前驱。
 * 如果p没有右孩子,但是有左孩子,那么p的左孩子就是p的前驱。
 * 但如果p是叶子节点:
 * 如果p是一个偏左行为的节点(想象成左下角的一个),那么它一定是第一个遍历的,他就不会有前驱。
 * 如果p是一个偏右行为的节点(想象成右下角的一个),那么它有可能有前驱,也有可能没有,得在这个节点的左边找一找。
 * 关于②:
 * 如果p有左孩子,那么p的左孩子就是p的后继。
 * 如果p没有左孩子,但是有右孩子,那么p的右孩子就是p的后继。
 * 但如果p是叶子节点:
 * 如果p是一个偏右行为的节点(想象成右下角的一个),那么它一定是最后一个遍历的,他就不会有后继。
 * 如果p是一个偏左行为的节点(想象成左下角的一个),那么它有可能有后继,也有可能没有,得在这个节点的右边找一找。
 *
 *
 * ②算法设计
 */


#include <stdio.h>
#include <iostream>
#define MaxSize 100

typedef struct ThreadBiTreeNode{
    int data;
    struct ThreadBiTreeNode *lchild,*rchild,*parent;//parent域指向双亲结点
    int ltag,rtag;
    int weight;//如果给叶子节点赋权值的话会用到
}ThreadBiTreeNode,*ThreadBiTree;


//②在中序线索二叉树里找指定节点在先序的后继
ThreadBiTree InFindNodePrePost(ThreadBiTree p){
    if(p -> ltag == 0){//说明p一定有左孩子,那么p的后继就是右孩子
        return p -> lchild;
    }else if(p -> rtag == 0){//如果p没有左孩子,但是有右孩子,那么p的后继就是p的右孩子
        return p -> rchild;
    }else{//如果p是叶子节点:
        //①如果p是一个偏右行为的节点(想象成右下角的一个),那么它一定是最后一个遍历的,他就不会有后继。
        if(p -> rchild == NULL)//p现在是叶子节点,所以p -> rchild == NULL 相当于p在中序序列中没有后继,那么p在先序序列中也没有后继
            return NULL;
        //②如果p是一个偏左行为的节点(想象成左下角的一个或者是左子树中的一个),那么它有可能有后继,也有可能没有,得在这个节点的右边找一找。
        while(p -> rchild != NULL && p -> rtag == 1){//一直向上找直到找到一个点有右孩子
            //因为p是叶子节点,所以p -> rchild就是它在~中序~中的后继,
            //这是一个一直向上找的过程,如果向上找的时候遇到某个节点他有右孩子,那么这个右孩子就是p在先序中的后继
            p = p -> rchild;//一直在向上找
        }
        if(p -> ltag == 0)//说明是因为p->ltag!=1结束循环的,说明向上找到了一个节点,这个节点有右孩子,那么这个右孩子就是p的后继。
            return p -> rchild;
        else//说明是因为p -> rchild == NULL 结束while的,那么这就是一个单支树,p就不会有后继。
            return NULL;
    }
}

 

 

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值