第六章-树(4)线索二叉树

本文介绍了一种二叉树的存储结构——中序线索二叉树,通过添加线索指针来提高遍历效率,避免了使用额外栈空间。文章详细讲解了中序线索二叉树的构建过程,并给出了具体的实现代码。

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

1、三张图片展览:          

            

                                               

            


以这种结点结构构成的二叉树链表作为二叉树的存储结构,叫做线索链表,其中指向结点前驱后后继的指针,叫做线索。加上线索的二叉树称之为线索二叉树。

可知,在中序线索二叉树上遍历二叉树,岁则时间复杂度亦为 O(n),但常数因子要比之前讨论的算法小,且不需要设栈。因此,若在某程序中所用二叉树需经常遍历或查找结点在遍历所得线索序列中的前驱和后继,则采用线索链表作存储结构。


--------------------------------------------------------------------------------------------------------------------------------

为了方便起见,仿照线性表的存储结构,在二叉树的线索链表上也添加一个头结点,并令其 lchild 域的指针指向二叉树的根结点,其 rchild 域指针指向中序遍历时访问的最后一个节点。反之,令二叉树中序序列中的最后一个结点的 lchild域指针和最后一个结点 rchild 域的指针均指向头结点。就像建立了一个双向线索链表,既可以从第一个结点起顺后继进行遍历,也可以从最后一个结点起顺前驱进行遍历

//-------二叉树的二叉线索存储表示--------
typedef enum PointerTag{
	Link,Thread                 //Link==0:指针,  Thread==1:  线索
};

typedef struct BiThrNode{
	TElemType data;
	struct BiThrNode *lchild,*rchild;    //左右孩子指针
	PointerTag LTag,RTag;          //左右标志
}BiThrNode,*BiThrTree;

--------------------------------------------------------------------------------------------------------------------------------

代码部分:

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

//宏定义
#define ERROR 0
#define OK 1
typedef char TElemType;

//-------二叉树的二叉线索存储表示--------
typedef enum PointerTag{
	Link,Thread                 //Link==0:指针,  Thread==1:  线索
};

typedef struct BiThrNode{
	TElemType data;
	struct BiThrNode *lchild,*rchild;    //左右孩子指针
	PointerTag LTag,RTag;          //左右标志
}BiThrNode,*BiThrTree;

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

//前序创建二叉树
void CreateTree(BiThrTree *T){
	char ch;
	ch=getchar();
	if(ch=='#'){
		*T=NULL;
	}
	else{
		(*T)=(BiThrTree)malloc(sizeof(BiThrNode));
		if((*T) == NULL)  
        {  
            return;  
        }  
        (*T)->data = ch;  
        CreateTree(&((*T)->lchild));  
        CreateTree(&((*T)->rchild));  
	}
}

//T指向头结点,头结点左孩子 lchild 指向根结点,头结点右孩子 rchild 指向中序遍历的最后一个结点
int InOrderThraverse_Thr(BiThrTree T)  
{  
    BiThrTree p;     //Link==0:指针;  Thread==1:线索
    p = T->lchild;           //p指向根结点  
    while(p != T)      //空树或遍历结束时 ,p==T
    {  
        while(p->LTag==Link)   //当 Thread==1:线索  时循环到中序序列的第一个结点  
        {  
            p = p->lchild;  
        }  
        printf("%c ", p->data);  //显示结点数据,可以更改为其他对结点的操作  
        while(p->RTag==Thread && p->rchild!=T)  
        {  
            p = p->rchild;             //访问后继结点
            printf("%c ", p->data);  
        }  
   
        p = p->rchild;           //p进入其右子树  
    }
    return OK;  
}  

//中序遍历进行中序线索化  
void InThreading(BiThrTree p)  
{  
    if(p)  
    {  
        InThreading(p->lchild);              //左孩子线索化

        if(!p->lchild)                       //没有左孩子  
        {  
            p->LTag=Thread;                //前驱线索  
            p->lchild = pre;             //左孩子指针指向前驱 
        }  
        if(!pre->rchild)                 //没有右孩子  
        {  
            pre->RTag=Thread;              //后继线索  
            pre->rchild = p;             //前驱右孩子指针指向后继(当前结点p)  
        }    
        pre = p;               //保持pre指向p的前驱
        InThreading(p->rchild);              //右孩子线索化
    }  
}  

//建立头结点,中序线索二叉树  
int InOrderThread_Head(BiThrTree *h,BiThrTree t)  
{  
    (*h) = (BiThrTree)malloc(sizeof(BiThrNode));  
    if((*h) == NULL)  
    {  
        return ERROR;  
    }  
   
    (*h)->rchild = *h;     //右指针回指
    (*h)->RTag = Link;  
   
    if(!t)      //如果为NULL  ,则右指针回指
    {  
        (*h)->lchild = *h;  
        (*h)->LTag= Link;  
    }  
    else  
    {  
        pre = *h;  
        (*h)->lchild = t;        //第一步  
        (*h)->LTag= Link;  
        InThreading(t);         //中序遍历进行中序线索化
        pre->rchild = *h;     
        pre->RTag= Thread;    //最后一个结点线索化
        (*h)->rchild = pre;  
    }  
}  

void main(){
	BiThrTree T;
	BiThrTree temp;
	printf("请输入先序二叉树的内容:\n");
	CreateTree(&T);
	InOrderThread_Head(&temp, T);       //加入头结点,并线索化  
    printf("输出中序二叉树的内容:\n");  
    InOrderThraverse_Thr(temp);  
       
    printf("\n");  

}
借鉴自:http://blog.youkuaiyun.com/u014492609/article/details/40477795
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值