//線索二叉樹,這里在二叉樹的基礎上增加了線索化
//楊鑫
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef enum {Link,Thread} childTag; //Link表示結點,Thread表示線索
typedef struct bitNode
{
ElemType data;
struct bitNode *lchild, *rchild;
int ltag, rtag;
} bitNode, *bitTree;
bitTree pre; //創建全局變量。表示剛剛訪問過的結點
/*
創建二叉樹,其輸入必須依照前序遍歷的次序。
T:二叉樹根節點
arr:依照前序遍歷次序排列的各節點的值。無孩子結點時用空格取代
*/
void create_tree(bitTree *T, char **arr)
{
char c;
sscanf(*arr,"%c",&c); //讀入一個結點值
(*arr)++;
if(' '== c) //假設是空格,表示空結點
{
*T=NULL;
}
else
{
*T=(bitTree)malloc(sizeof(bitNode)); //構造新結點
(*T)->data=c;
(*T)->ltag=Link;
(*T)->rtag=Link;
create_tree(&(*T)->lchild,arr); //構造新結點的左孩子
create_tree(&(*T)->rchild,arr); //構造新結點的右孩子
}
}
/*
訪問結點信息
*/
void visit(bitTree T)
{
printf("| %d | %c | %d |\n",T->ltag,T->data,T->rtag);
}
/*
前序遍歷訪問二叉樹
*/
void pre_order_traverse(bitTree T,int level)
{
if(T)
{
visit(T);
pre_order_traverse(T->lchild,level+1);
pre_order_traverse(T->rchild,level+1);
}
}
/*
中序遍歷二叉樹,對其進行線索化
*/
void in_order_threading(bitTree T)
{
if(T)
{
in_order_threading(T->lchild); //左孩子線索化
if(!T->lchild) //假設左孩子為空,則將其指向直接前驅
{
T->lchild=pre;
T->ltag=Thread;
}
if(!pre->rchild) //假設上一個結點的右孩子為空,則將其指向直接后繼。(注意:僅僅有訪問到下一個結點時,才會知道本結點的后繼是誰)
{
pre->rchild=T;
pre->rtag=Thread;
}
pre=T;
in_order_threading(T->rchild); //右孩子線索化
}
}
/*
增加一個頭結點,使二叉線索樹成一個封閉環
P:帶有頭結點的二叉樹。頭結點的左孩子指向二叉樹T;右孩子指向T樹中的最后一個葉子結點
T:不帶有頭結點的二叉樹。
*/
void in_thread(bitTree *P,bitTree T)
{
(*P)=(bitTree)malloc(sizeof(bitNode)); //構造新增加的頭結點
(*P)->ltag=Link;
(*P)->rtag=Thread;
(*P)->rchild=*P;
if(!T) //假設二叉樹為空,則P的孩子指向自己。
{
(*P)->lchild=*P;
}
else
{
(*P)->lchild=T;
pre=*P;
in_order_threading(T); //對二叉樹進行線索化
(*P)->rchild=pre; //將頭結點右孩子指向最后一個葉子結點
pre->rtag=Thread; //將最后一個葉子結點的右孩子指向頭結點。這樣。環就形成了。
pre->rchild=*P;
}
}
/*
非遞歸方式:中序遍歷二叉樹(樹必須帶有頭結點,且已經線索化)
P:帶有頭結點的二叉樹
*/
void in_order_traverse(bitTree P)
{
bitTree T;
T=P->lchild;
while(T!=P) //推斷是否空樹
{
while(T->ltag==Link) //從左孩子開始。直到葉子結點
{
T=T->lchild;
}
visit(T);
while(T->rtag==Thread && T->rchild!=P) //依據線索,訪問后繼結點。而且后繼結點不是指向頭結點的
{
T=T->rchild;
visit(T);
}
T=T->rchild;
}
}
int main()
{
bitTree P,T;
int level =1; //表示該結點的深度
char *arr="ab d ce "; //構造二叉樹所需結點(按前序遍歷方式輸入)
create_tree(&T,&arr); //構造二叉樹
printf("pre_order_traverse:先序遍歷:\n");
pre_order_traverse(T,level); //前序遍歷輸出二叉樹
printf("in_order_traverse:中序遍歷:\n");
in_thread(&P,T); //二叉樹線索化
in_order_traverse(P); //輸出線索化后的二叉樹
return 0;
}
如圖:

