/*
树-线索二叉树
LJK 2017-07-05
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef char TElemType;
typedef int Status;
/*
Link == 0 表示指向左右孩子的指针
Thread == 1 表示指向前驱或后继的线索
*/
typedef enum {Link,Thread} PointerTag;
// 二叉线索存储节点结构
typedef struct biThrNode
{
TElemType data; // 节点数据
struct biThrNode *lchild, *rchild; // 左右孩子指针
PointerTag LTag, RTag; // 左右标志
}BiThrNode;
int index = 0;
char String[] = "ABDH##I##EJ###CF##G##";
Status visit(TElemType e)
{
printf("%c", e);
return OK;
}
// 按前序输入二叉线索树中节点的值,构造二叉线索树
Status CreateBiThrTree(BiThrNode **T)
{
TElemType ch;
ch = String[index++];
if (ch == '#')
*T = NULL;
else
{
*T = (BiThrNode*)malloc(sizeof(BiThrNode));
if (!(*T)) exit(OVERFLOW);
(*T)->data = ch; // 生成根节点(前序)
CreateBiThrTree(&(*T)->lchild); // 构造左子树
if ((*T)->lchild)(*T)->LTag = Link;
CreateBiThrTree(&(*T)->rchild); // 构造右子树
if ((*T)->rchild) (*T)->RTag = Link;
}
return OK;
}
BiThrNode *pre; // 全局变量,始终指向刚刚访问过的节点
/* 中序遍历进行中序线索化 */
void InThreading(BiThrNode *p)
{
if (p)
{
InThreading(p->lchild); // 递归左子树线索化
if (!p->lchild) // 没有左孩子
{
p->LTag = Thread; // 前驱线索
p->lchild = pre; // 左孩子指针指向前驱
}
if (!p->rchild) // 前驱没有右孩子
{
pre->RTag = Thread; // 后继线索
pre->rchild = p; // 前驱右孩子指针指向后继(当前节点p)
}
pre = p; // 保持pre指向p的前驱
InThreading(p->rchild); // 递归右子树线索化
}
}
// 中序遍历二叉树T,并将其中序线索化,Thrt指向头节点
Status InOrderThreading(BiThrNode **Thrt, BiThrNode *T)
{
*Thrt = (BiThrNode *)malloc(sizeof(BiThrNode)); // 建头节点
if (!(Thrt)) exit(OVERFLOW);
(*Thrt)->LTag = Link;
(*Thrt)->RTag = Thread;
(*Thrt)->rchild = *Thrt; // 右指针回指
if (!(T)) (*Thrt)->lchild = *Thrt; // 若二叉树空,则左指针回指
else
{
(*Thrt)->lchild = T; // 头节点左孩子指向根节点
pre = (*Thrt); // pre指向头节点
InThreading(T); // 中序遍历进行中序线索化
pre->RTag = Thread;
pre->rchild = *Thrt; // 最后一个节点线索化,指向头节点
(*Thrt)->rchild = pre; // 头节点线索化,指向最后一个节点
}
return OK;
}
// 中序遍历二叉线索树T(头节点)的非递归算法
Status InOrderTraverse_Thr(biThrNode *T)
{
BiThrNode *p;
p = T->lchild; // p指向根节点
while (p != T)
{
// 空树或者遍历结束时, p == T
while (p->LTag == Link)
p = p->lchild;
if (!visit(p->data)) // 访问其左子树为空的结点
return ERROR;
while (p->RTag == Thread && p->rchild != T) // 有后继线索则直接指向后继结点
{
p = p->rchild;
visit(p->data); // 访问后继结点
}
p = p->rchild; // 进入右子树
}
return OK;
}
int main()
{
BiThrNode *t, *h;
PointerTag P;
printf("按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");
CreateBiThrTree(&t);
// 中序遍历,并中序线索化二叉树
InOrderThreading(&h, t);
// 中序遍历(输出),二叉线索树
InOrderTraverse_Thr(h);
printf("\n");
getchar();
return 0;
}