一、線索二叉樹
如果二叉樹的節點包含數據域和兩個指針域( lchild 和 rchild ),當節點沒有下一個節點時,將指針域賦值爲空(NULL),但有時會造成很大的浪費,所以可以將空指針域利用起來,存放其他節點的地址,這樣就便於索引,像二叉樹遍歷,查找之類就會變得相對容易。
像上面的二叉樹就會造成很大的浪費。當該二叉樹以中序遍歷輸出時,爲FDGBACE,紅色表示有兩個指針域可以利用,藍色表示有一個指針域可以利用,而黑色表示沒有多餘的指針域可以利用,若果將一個節點的lchild(如果可以使用)指向它前一個節rchlid(如果可以使用)指向它的後一個節點(這裏的前後是針對於FDGBACE這個序列而言的)。而假若在最前面增加一個頭結點,數據域爲data,那麼會更加便捷。最終它們的指向會變爲:
這樣的對於中序遍歷二叉樹就會變得很容易。
然而,機器怎麼判斷一個節點到底有多少個指針域可以使用呢?這樣就需要一個標誌,指示該節點的兩個指針域是否可以被利用,於是,我們把節點擴容,變爲:
ltag爲0時指向該結點的左孩子,爲1時指向該結點的前驅。rtag爲0時指向該結點的右孩子,爲1時指向該結點的後繼。
這樣就能分別指示左右指針域是否可以利用。雖然犧牲了一點空間,但換來的是效率的提高。
二、代碼實現
- #include <stdio.h>
- #include <stdlib.h>
- typedef char ElemType;
- // 線索存儲標誌位
- // Link(0):表示指向左右孩子的指針
- // Thread(1):表示指向前驅後繼的線索
- typedef enum {Link, Thread} PointerTag;
- typedef struct BiThrNode
- {
- char data;
- struct BiThrNode *lchild, *rchild;
- PointerTag ltag;
- PointerTag rtag;
- } BiThrNode, *BiThrTree;
- // 全局變量,始終指向剛剛訪問過的結點
- BiThrTree pre;
- // 創建一棵二叉樹,約定用戶遵照前序遍歷的方式輸入數據
- void CreateBiThrTree( BiThrTree *T )
- {
- char c;
- scanf("%c", &c);
- if( ' ' == c )
- {
- *T = NULL;
- }
- else
- {
- *T = (BiThrNode *)malloc(sizeof(BiThrNode));
- (*T)->data = c;
- (*T)->ltag = Link;
- (*T)->rtag = Link;
- CreateBiThrTree(&(*T)->lchild);
- CreateBiThrTree(&(*T)->rchild);
- }
- }
- // 中序遍歷線索化
- void InThreading(BiThrTree T)
- {
- if( T )
- {
- InThreading( T->lchild ); // 遞歸左孩子線索化
- if( !T->lchild ) // 如果該結點沒有左孩子,設置ltag爲Thread,並把lchild指向剛剛訪問的結點。
- {
- T->ltag = Thread;
- T->lchild = pre;
- }
- if( !pre->rchild )
- {
- pre->rtag = Thread;
- pre->rchild = T;
- }
- pre = T;
- InThreading( T->rchild ); // 遞歸右孩子線索化
- }
- }
- void InOrderThreading( BiThrTree *p, BiThrTree T )
- {
- *p = (BiThrTree)malloc(sizeof(BiThrNode));
- (*p)->ltag = Link;
- (*p)->rtag = Thread;
- (*p)->rchild = *p;
- if( !T )
- {
- (*p)->lchild = *p;
- }
- else
- {
- (*p)->lchild = T;
- pre = *p;
- InThreading(T);
- pre->rchild = *p;
- pre->rtag = Thread;
- (*p)->rchild = pre;
- }
- }
- void visit( char c )
- {
- printf("%c", c);
- }
- // 中序遍歷二叉樹,非遞歸
- void InOrderTraverse( BiThrTree T )
- {
- BiThrTree p;
- p = T->lchild;
- while( p != T )
- {
- while( p->ltag == Link )
- {
- p = p->lchild;
- }
- visit(p->data);
- while( p->rtag == Thread && p->rchild != T )
- {
- p = p->rchild;
- visit(p->data);
- }
- p = p->rchild;
- }
- }
- int main()
- {
- BiThrTree P, T = NULL;
- CreateBiThrTree( &T );
- InOrderThreading( &P, T );
- printf("中序遍歷輸出結果爲: ");
- InOrderTraverse( P );
- printf("\n");
- return 0;
- }
三、效果展示