线索二叉树

小甲鱼课程笔记

为什么需要线索二叉树呢?
二叉树存在比较严重的空间的浪费,设一共有n个结点,那么有一个孩子结点的结点就会有一个空间的浪费,而叶子结点就会有两个空间的浪费,那么每个二叉树都会有 n + 1 n+1 n+1个空间的浪费!

那么此时就需要线索二叉树
而中序遍历可以解决这种麻烦。

引用自小甲鱼数据结构课程

在这里插入图片描述
上图的二叉树经过中序遍历之后的结果就会是:
HDIBEAFCG
我们发现换色的结点就是刚才空的地方浪费的结点,利用中序遍历刚好他们能处于字符中间,可以很好的利用这个空间来存放前驱和后继的指针。

A B C D F G E

但是对于上图的二叉树中序遍历过后的结果是: FDGBACE
黄色部分说明是只有一个空指针位粗体部分才右两个指针位。此时就需要扩容,用两个个bool类型的数字表示左右指针是否已经右了孩子结点。
代码:

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

typedef char ElemType;


//线索存储表值位
// Link(0):表示指向左右孩子的指针
// Thread(1):表示指向前驱后继的线索
typedef enum {Link,Thread} PointerTag;

typedef struct BiThrNode{
    char data;
    struct BiThrNode *lchild,*rchild;
    PointerTag ltag;
    PointerTag rtag;
}BiThrNode , *BiThrTree;



// 全局变量,始种指向刚刚访问过的结点
BiThrTree pre;

//创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
//前序输入例如输入ABC  D  E F
//中序遍历:CBDAEF
void CreateBiThrTree( BiThrTree *T){
    char c;
    scanf("%c",&c);
    if(' '==c){
        *T = NULL;
    }else{
        *T = (BiThrNode *)malloc(sizeof(BiThrNode));
        (*T)->data = c;
        (*T)->ltag = Link;
        (*T)->rtag = Link;

        CreateBiThrTree(&(*T)->lchild);
        CreateBiThrTree(&(*T)->rchild);
    }
}

//中序遍历线索化
InThreading(BiThrTree T){
    if(T){
        InThreading( T-> lchild );//递归左孩子线索化

        //结点处理
        if( !T->lchild ){ //如果该结点没有左孩子,设置ltag为Thread,并把lchild指向刚刚访问的结点。
            T->ltag = Thread;
            T->lchild = pre;
        }

        if( !pre->rchild){
            pre->rtag = Thread;
            pre->rchild = T;

        }

        pre = T;

        InThreading( T-> rchild );//递归右孩子线索化
    }
}

InOrderThreading( BiThrTree *p ,BiThrTree T){//创建前置指针
    *p = (BiThrTree)malloc(sizeof(BiThrNode));//初始化
    (*p)->ltag = Link;
    (*p)->rtag = Thread;
    (*p)->rchild = *p;
    if(!T){
        (*p)->lchild = *p;//如果T是空树,就连回自己
    }else{
        (*p)->lchild = T;
        pre = *p;
        InThreading(T);//线索化
        pre->rchild = *p; //把指针连到和*P相连,构成循环
        pre->rtag = Thread;
        (*p)->rchild = pre;
    }

}

void visit(char c){
    printf("%c",c);
}

//中序遍历二叉树,非递归
void InOrderTraverse( BiThrTree T){
    BiThrTree p;
    p = T->lchild;

    while( p!=T ){
        while( p->ltag == Link){
            p = p->lchild;
        }
        visit(p->data);

        while(p->rtag == Thread && p->rchild != T){
            p = p->rchild;
            visit(p->data);
        }

        p = p->rchild;
    }
}

int main()
{
    BiThrTree P , T = NULL;

    CreateBiThrTree( &T );

    InOrderThreading(&P,T);

    printf("中序遍历输出结果为:");

    InOrderTraverse( P );

    printf("\n");

    return 0;
}

``

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值