//線索二叉樹,這裡在二叉樹的基礎上添加了線索化 //楊鑫 #include#include 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; }
如圖: