线索二叉树的特殊遍历方法

这里不知道线索二叉树和其创建方法的可以看我之前的二叉线索树的创建

下面进入正题:

因为线索二叉树的某些左指针和右指针可以指向它的前驱和后继,所以我们可以根据这一特性,来直接找到某些节点的前驱节点和后继节点,从而优化我们找前驱和后继的算法

以中序遍历为例子

注意:中序线索二叉树只有中序遍历时才能用这种特殊算法,其余的先序和后续还是要用普通的方法。(其余的线索二叉树同上)

下面代码仅供参考

//二叉树中第一个被中序遍历到的节点,即最左下角的节点
TreeNode* InFirstNode(TreeNode*root)
{
    TreeNode* node = root;
    while (node->ltag == 0)//注意循环条件发生变化,因为线索二叉树中没有节点指针指向空
    {
        node = node->left;
    }
    return node;
}

//找到后继
TreeNode* InNext(TreeNode*root)
{
    if (root->rtag == 1)//直接找到后继节点
        return root->right;
    else
    {
        //左中右
        //它右子树的最左下角的节点是它的后继,即右子树中第一个被遍历到的节点
        return InFirstNode(root->right);
    }
}

//树中最后一个被中序遍历到的节点
TreeNode* InLastNode(TreeNode* root)
{
    TreeNode* node = root;
    while (node->rtag == 0)//注意循环条件发生变化
        node = node->right;
    return node;
}

//找到前驱
TreeNode* InPrev(TreeNode* root)
{
    if (root->ltag == 1)
        return root->left;
    else
    {
        //左中右
        //它左子树的最右下角的节点是它的前驱,即左子树中最后一个被遍历到的节点
        return InLastNode(root->left);
    }
}

//中序化线索树的中序遍历方法(可以从任意位置开始中序遍历)
void InOrder(TreeNode* root)
{
    //顺序的中序遍历
    for (TreeNode* p = InFirstNode(root); p != NULL; p = InNext(p))
    {
        printf("%d ", p->val);
    }
    printf("\n");
    //逆序的中序遍历
    for (TreeNode* p = InLastNode(root); p != NULL; p = InPrev(p))
    {
        printf("%d ", p->val);
    }
}

这里需要注意:只有中序线索二叉树可以同时拥有 顺-逆-遍历 的能力,原因是中序遍历的节点前驱和后继都在它的子树中,而先序遍历的节点前驱是节点的父节点(ltag=1的节点除外)我们无法直接访问它的父节点,所以先序遍历只能 顺-遍历 ,后序遍历的节点的后继节点是节点的父节点(rtag=1的节点除外)我们无法直接访问它的父节点,所以后序遍历只能 逆-遍历

注意:上面的说法仅限于我们所讲的特殊算法,对于一般的算法是不适用的,还有就是我们可以通过从头开始找的土方法找到节点的父节点,当然如果是三叉树也可以直接访问,但是再次强调我们这里的说法仅限于我们上面以中序遍历为例子的算法!!!一定要谨记,不要混淆!!!

下面是先序遍历的代码

TreeNode* PreNext(TreeNode*root)//找后继节点
{
    if (root->rtag == 1)
        return root->right;
    else
    {
        if (root->ltag == 0)
            return root->left;
        else
            return root->right;
    }
}

void PreOrder(TreeNode* root)//顺-遍历
{
    for (TreeNode* p = root; p != NULL; p = PreNext(p))
    {
        printf("%d ", p->val);
    }
    printf("\n");
}

下面是后序遍历的代码

TreeNode* PostPrev(TreeNode*root)//找前驱节点
{
    if (root->ltag == 1)
        return root->left;
    else
    {
        if (root->rtag == 0)
            return root->right;
        else
            return root->left;
    }
}

void PostOrder(TreeNode*root)
{
    for (TreeNode* p = root; p != NULL; p = PostPrev(p))
    {
        printf("%d ",p->val);
    }
    printf("\n");
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值