摘要:由于具有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;
}