线索二叉树的概念
线索二叉树的原理:线索二叉树是将普通二叉树左右孩子中的空链域利用起来,将左孩子空链域指向当前节点的线性遍历前驱,将右孩子空链域指向当前节点的线性遍历后继,指向该线性序列中的前驱或后继被称为“线索”。由于在线索链表中添加了遍历中得到的“前驱”和“后继”的信息,从而简化了遍历的算法。
线索二叉树的结构
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#define END '#'
typedef char ElemType;
typedef enum{Link = 0,Thread = 1}PointTag;
typedef struct ThrBiTreeNode
{
PointTag ltag,rtag;
struct ThrBiTreeNode *lchild;
struct ThrBiTreeNode *rchild;
ElemType data;
}ThrBiTreeNode,*ThrBiTree;
中序线索二叉树的创建和遍历
线索二叉树结点的申请和释放
ThrBiTreeNode * BuyNode()
{
ThrBiTreeNode * node = (ThrBiTreeNode *)malloc(sizeof(ThrBiTreeNode));
assert(NULL != node);
memset(node,0,sizeof(node));
return node;
}
void FreeNode(ThrBiTreeNode *ptr)
{
assert(ptr != NULL);
free(ptr);
}
线索二叉树的创建
ThrBiTreeNode * CreateThrBiTree(ElemType *&str)
{
ThrBiTreeNode *node = NULL;
if (str != NULL && *str != END)
{
node = BuyNode();
node->ltag = Link;
node->rtag = Link;
node->data = *str;
node->lchild = CreateThrBiTree(++str);
node->rchild = CreateThrBiTree(++str);
}
return node;
}
中序线索化二叉树
方法1
//中序线索化二叉树
ThrBiTreeNode *pre = NULL;
void MakeThreadBiTree(ThrBiTreeNode *ptr)
{
if(ptr != NULL)
{
MakeThreadBiTree(ptr->lchild);
if(ptr->lchild == NULL)
{
ptr->lchild = pre;
ptr->ltag = Thread;
}
if (pre != NULL && pre->rchild == NULL)
{
pre->rchild = ptr;
pre->rtag = Thread;
}
pre = ptr;
if (pre->rchild == NULL && pre->rtag == Link)
{
pre->rtag = Thread;
}
MakeThreadBiTree(ptr->rchild);
}
}
方法2(带头结点的线索二叉树)
// 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
void InOrderThreading(ThrBiTree *Thrt,ThrBiTree T)
{
*Thrt = (ThrBiTree)malloc(sizeof(ThrBiTreeNode));
if(!*Thrt)
exit(OVERFLOW);
(*Thrt)->ltag=Link; /* 建头结点 */
(*Thrt)->rtag=Thread;
(*Thrt)->rchild=(*Thrt); /* 右指针回指 */
if(!T) /* 若二叉树空,则左指针回指 */
(*Thrt)->lchild=*Thrt;
else
{
(*Thrt)->lchild=T;
pre=(*Thrt);
MakeThreadBiTree(T); /* 中序遍历进行中序线索化 */
pre->rchild=*Thrt;
pre->rtag=Thread; /* 最后一个结点线索化 */
(*Thrt)->rchild=pre;
}
}
方法3
void Make(ThrBiTreeNode *ptr,ThrBiTreeNode *&pre)
{
if(ptr != NULL)
{
Make(ptr->lchild,pre);
if(ptr->lchild == NULL)
{
ptr->lchild = pre;
ptr->ltag = Thread;
}
if (pre != NULL && pre->rchild == NULL)
{
pre->rchild = ptr;
pre->rtag = Thread;
}
pre = ptr;
if (pre->rchild == NULL && pre->rtag == Link)
{
pre->rtag = Thread;
}
Make(ptr->rchild,pre);
}
}
ThrBiTreeNode * MakeThreadBiTree2(ThrBiTreeNode *ptr)
{
if(ptr == NULL)
{
return NULL;
}
ThrBiTreeNode *pre = NULL;
Make(ptr,pre);
return ptr;
}
中序线索二叉树的遍历
前序遍历
方法1
void ThrInOrder(ThrBiTreeNode *ptr)
{
assert(ptr != NULL);
ThrBiTreeNode *p;
p = ptr;
while (p != NULL)
{
while (p->ltag == Link)
{
p = p->lchild;
}
printf("%c ",p->data);
while (p->rtag == Thread && p->rchild != NULL)
{
p = p->rchild;
printf("%c ",p->data);
}
p = p->rchild;
}
}
方法2(带头结点的线索二叉树)
/* 中序遍历二叉线索树T(头结点)的非递归算法 */
void InOrderTraverse_Thr(ThrBiTree T)
{
ThrBiTree p;
p=T->lchild; /* p指向根结点 */
while(p!=T)
{ /* 空树或遍历结束时,p==T */
while(p->ltag==Link)
p=p->lchild;
printf("%c ",p->data);
while(p->rtag==Thread&&p->rchild!=T)
{
p=p->rchild;
printf("%c ",p->data); /* 访问后继结点 */
}
p=p->rchild;
}
}
方法3
ThrBiTreeNode * First(ThrBiTreeNode *ptr)
{
while (ptr != NULL && ptr->ltag == Link)
{
ptr = ptr->lchild;
}
return ptr;
}
ThrBiTreeNode * Next(ThrBiTreeNode *ptr)
{
if (ptr != NULL && ptr->rtag == Thread)
{
return ptr->rchild;
}
else
{
return First(ptr->rchild);
}
}
void ThrInOrder2(ThrBiTreeNode *ptr)
{
for (ThrBiTreeNode * temp = First(ptr);temp != NULL;temp = Next(temp))
{
printf("%c ",temp->data);
}
printf("\n");
}
后序遍历
方法1
void ThrInOrderReverse(ThrBiTreeNode *ptr)
{
assert(ptr != NULL);
ThrBiTreeNode *p;
p = ptr;
while (p != NULL)
{
while (p->rtag == Link)
{
p = p->rchild;
}
printf("%c ",p->data);
while (p->ltag == Thread && p->lchild != NULL)
{
p = p->lchild;
printf("%c ",p->data);
}
p = p->lchild;
}
}
方法2(带头结点的线索二叉树)
void ThrInOrderReverse2(ThrBiTree T)
{
ThrBiTree p;
p=T->lchild; /* p指向根结点 */
while(p!=T)
{ /* 空树或遍历结束时,p==T */
while(p->rtag==Link)
p=p->rchild;
printf("%c ",p->data);
while(p->ltag==Thread&&p->lchild!=T)
{
p=p->lchild;
printf("%c ",p->data); /* 访问后继结点 */
}
p=p->lchild;
}
}
方法3
ThrBiTreeNode * Last(ThrBiTreeNode *ptr)
{
while(ptr != NULL && ptr->rtag != Thread)
{
ptr = ptr->rchild;
}
return ptr;
}
ThrBiTreeNode * Prev(ThrBiTreeNode *ptr)
{
if (ptr != NULL && ptr->ltag == Thread)
{
return ptr->lchild;
}
else
{
return Last(ptr->lchild);
}
}
void ResThrInOrder(ThrBiTreeNode *ptr)
{
ThrBiTreeNode * temp;
for (temp = Last(ptr);temp != NULL;temp = Prev(temp))
{
printf("%c ",temp->data);
}
printf("\n");
}