05 二叉树前序/中序/后序线索化和找前驱、后继

1. 线索化代码

线索化需要先序/中序/后续遍历的过程,多了访问到节点时指针指向的问题

二叉树形状和运行结果

在这里插入图片描述
在这里插入图片描述

主函数
#include "func.h"

// 二叉树线索化(便于找前驱和后继节点)
// 1. 二叉树先序线索化
// 2. 二叉树中序线索化
// 3. 二叉树后序线索化

// 中序线索化
// 需要有一个前驱节点指针
// 1. 进行中序序遍历,当访问到某节点时,进行判断:
//       (1) 如果左子树为空,则让左孩子指向pre
//       (2) 如果pre的右子树为空,则让右孩子指向当前访问的节点
// 2. 让pre指向当前节点,进入下一次遍历

BiNode *pre = NULL;   // 全局变量

void InThread(BiTree &tree){
    if (tree!=NULL){
        InThread(tree->left);
        if(tree->left == NULL){
            tree->ltag = 1;
            tree->left = pre;
            if (pre==NULL) printf("\n%c.pre --> NULL\n",tree->data.value);
            else printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre != NULL && pre->right == NULL){
            pre->right = tree;
            pre->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
        InThread(tree->right);
    }
}

// 先序线索化
// 需要注意的是,当把节点左孩子链接为该节点前驱,那么再使用tree->left访问左孩子就造成访问错误,需要额外加ltag判断

void PreThread(BiTree &tree){
    if(tree!=NULL){
        if(tree->left == NULL){
            tree->left = pre;
            tree->ltag = 1;
            printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre!=NULL && pre->right == NULL){
            tree->right = pre;
            tree->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
        if (tree->ltag == 0) PreThread(tree->left);
        PreThread(tree->right);
    }
}

void PostThread(BiTree &tree){
    if(tree!=NULL){
        PostThread(tree->left);
        PostThread(tree->right);
        if(tree->left == NULL){
            tree->left = pre;
            tree->ltag = 1;
            if (pre==NULL) printf("\n%c.pre --> NULL\n",tree->data.value);
            else printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre!=NULL && pre->right == NULL){
            tree->right = pre;
            tree->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
    }
}




// Demo:
//                  A
//              B       C
//           D    E  NULL   F
// 中序遍历:DBEACF
// 线索化: D.pre->NULL; D.post=B; E.pre->B; E.post->A; C.pre->A; F.pre->C
// 先序遍历: ABDECF
// 线索化: D.pre->B; E->pre=D; D->post=E; C->pre=E; C->post=C
int main() {
    printf("---------------------\n");
    BiTree tree;
    getDemo(tree);
    InOrder(tree);
    InThread(tree);
    pre=NULL;
    printf("---------------------\n");
    BiTree tree2;
    getDemo(tree2);
    PreOrder(tree2);
    printf("\n");
    PreThread(tree2);
    printf("---------------------\n");
    pre = NULL;
    BiTree tree3;
    getDemo(tree3);
    PostOrder(tree3);
    PostThread(tree3);
    return 0;
}
头文件和其它源文件
#include "func.h"

void init(BiTree &tree){
    tree = (BiNode*) malloc(sizeof(BiNode));
    tree->left = NULL;
    tree->right = NULL;
    tree->ltag = tree->rtag = 0;
}

BiNode* create_node(Element elem){
    BiNode *p_node = (BiNode*) malloc(sizeof(BiNode));
    p_node->data = elem;
    p_node->left = p_node->right = NULL;
    p_node->ltag = p_node->rtag = 0;
    return p_node;
}

BiTree getDemo(BiTree &tree){
    // Demo:
    //                  A
    //              B       C
    //           D    E  NULL   F
    //
    init(tree);
    Element A,B,C,D,E,F;
    A.value = 'A';
    B.value = 'B';
    C.value = 'C';
    D.value = 'D';
    E.value = 'E';
    F.value = 'F';
    BiNode *pb = create_node(B);
    BiNode *pc = create_node(C);
    BiNode *pd = create_node(D);
    BiNode *pe = create_node(E);
    BiNode *pf = create_node(F);
    tree->data = A;
    tree->left = pb;
    tree->right = pc;
    pb -> left = pd;
    pb->right = pe;
    pc->right = pf;
}


void visit(BiNode *node){
    printf("%c\t",node->data);
}

void PreOrder(BiTree tree){
    if (tree != NULL){
        visit(tree);
        PreOrder(tree->left);
        PreOrder(tree->right);
    }
}

void InOrder(BiTree tree){
    if (tree != NULL){
        InOrder(tree->left);
        visit(tree);
        InOrder(tree->right);
    }
}

void PostOrder(BiTree tree){
    if (tree != NULL){
        PostOrder(tree->left);
        PostOrder(tree->right);
        visit(tree);
    }
}



//
// Created by 64516 on 2023/1/25.
//

#ifndef ORDER_01_FUNC_H
#define ORDER_01_FUNC_H


#include <stdio.h>
#include <stdlib.h>



typedef struct Element{
    char value;
};

typedef struct BiNode{
    Element data;
    BiNode *left,*right;  // 可以将节点左右指针初始化为NULL吗?
    bool ltag,rtag;
}BiNode,*BiTree;

BiTree getDemo(BiTree &tree);
void visit(BiNode *node);
void PreOrder(BiTree tree);
void InOrder(BiTree tree);
void PostOrder(BiTree tree);

#endif //ORDER_01_FUNC_H

2. 在二叉树线索化后找节点前驱/后继

中序线索二叉树

中序线索二叉树找中序前驱
如果ltag=0,则子树有左孩子,前驱为左子树最右的节点
>

中序线索二叉树找中序后继
如果rtag=0,则节点有右孩子,后继为子树最左的节点在这里插入图片描述

先序线索二叉树

先序线索二叉树找先序前驱
若ltag=1可以直接找到,若ltag=0,节点有左孩子,该节点在向下子树是第一个被访问的节点,无法找到该节点的前驱,除非该二叉树为三叉链表可以链接到父节点
先序线索二叉树找先序后继
若rtag=0则有右孩子,此时节点有左孩子则左孩子为后继,没有左孩子则右孩子为后继

后序线索二叉树

后续线索二叉树找后续前驱
若ltag=0则有左孩子,此时没有右孩子则左孩子为前驱,有右孩子则右孩子为前驱
后续线索二叉树找后续后继
若rtag=1可以直接找到,若rtag=0则节点有右孩子,该节点在向下子树内是最后访问的,无法找到该节点的后继,除非该二叉树为三叉链表。

三叉链表时的补充:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值