数据结构:线索树之基本例程(1)

线索树通过在二叉查找树的NULL指针处添加线索,提高搜索效率。文章介绍了线索树的基本概念,如何标识左、右线索,以及在搜索节点前驱时的注意事项,防止进入死循环。此外,还讨论了插入节点时如何处理线索信息,避免死循环,并确保节点指针信息的准确性。

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

摘要:由于具有N个节点的二叉树具有N+1个NULL指针,因此在二叉查找中有一半的空间被浪费掉了.假设节点x有一个左NULL指针,则将NULL指针指向它的中缀前驱,若有一个右NULL指针,则将其指向中缀后继,这就叫线索树.
(1)使用两个个变量区分该节点的指针是否是左、右线索(注意线索也可能没有后继或前驱,也可能指向NULL).
(2)搜索一个节点的前驱:基本思路:
[1]进行一次中序遍历(左中右/右中左),遇到第一个大于或者小于所求元素x的节点就是前驱.
[2]需要注意的细节是:在搜寻时要注意不要进入线索指针,否则容易进入死循环.在搜寻到第一个节点后要快速退出递归(利用goto或者其他标记变量),否则会覆盖掉真正前驱.
(3)插入节点:基本思路与普通二叉树一致,需要注意几点:
【1】在递归降至某个节点之前,要确保该节点不是由线索指向,否则陷入死循环,一种较好的做法是让该节点的线索指针指向NULL,并且改变标志线索的信息,然后再递归的插入.
[2]要确保节点的指针指向信息准确,这就需要在插入新节点后,立刻寻找前驱,后继,然后连接在节点的NULL指针上,检测该节点的指针情况,从而确定是否有前驱,后继(注意不是每个节点都有前驱,后继的,要处理最大,最小,以及只有一单个节点的特殊情况)
`

#include "stdafx.h"
#include "stdlib.h"
#include "malloc.h"
#define Empty 0
#define thread 1

typedef struct threadtree *Position;
#define Empty 0
//定义若前继为空,则线索指向NULL
struct threadtree
{
    int Element;
    int Leftisthread;
    int Rightisthread;
    Position Left;
    Position Right;
};

Position init()
{
    Position T;
    T = (Position)malloc(sizeof(threadtree));
    T->Leftisthread = Empty;
    T->Rightisthread = Empty;
    T->Left = NULL;
    T->Right = NULL;
    return T;
}
Position Findpre(Position T,Position &Last,Position Maybepre,int x)
{
    if (T==NULL)
        return NULL;
    if(T->Rightisthread == Empty)//防止误将线索当成子节点进入死循环
    Maybepre = Findpre(T->Right,Last,NULL,x);

    if(Maybepre != NULL)//不需要继续递归
    goto end;
    if(T->Element !=x)
    Last = T;//记录可能的前继
     if (T->Element < x)//找到前继(第一个比x小的值)
     {
    Maybepre = Last;
    return Maybepre;
     }
    if(T->Leftisthread == Empty)
    Maybepre = Findpre(T->Left,Last,NULL,x);
    end:
    return Maybepre;
}
Position Findnext(Position T,Position &Last,Position Maybenext,int x)
{
    if (T==NULL)
        return NULL;
    if(T->Leftisthread==Empty)
    Maybenext = Findnext(T->Left,Last,NULL,x);
    if(Maybenext != NULL)
    goto end;

    if(T->Element != x)
    Last = T;//记录可能的后继
    if (T->Element > x)//找到后继
    {
    Maybenext = Last;
    return Maybenext;
    }
    if(Maybenext == NULL&&T->Rightisthread == Empty)
    Maybenext = Findnext(T->Right,Last,NULL,x);
    end:
    return Maybenext;
}
Position Insert(Position T,Position Parent,int x)
{
    static Position root = T;
    Position Last = NULL;
    if(T==NULL)
    {
        T = init();//创建新节点
        T->Element = x;
        T->Left = Findpre(root,Last,NULL,x);
        T->Right = Findnext(root,Last,NULL,x);
            //确定isthread的值,指向前、后或者都有(四种情况)
        if(T->Left!=NULL)
            T->Leftisthread = thread;
        if(T->Right !=NULL)
            T->Rightisthread = thread;
            return T;
    }
    //正在递归
    if(x>T->Element)
    {
        if (T->Rightisthread == thread)
        {
            T->Right = NULL;
            T->Rightisthread = Empty;
        }
        T->Right = Insert(T->Right,T,x);

    }
    else //x<T->Element
    {
        if (T->Leftisthread == thread)
        {
            T->Left = NULL;
            T->Leftisthread = Empty;
        }
        T->Left = Insert(T->Left,T,x);
    }   
    return T;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值