資料結構-------------線索二叉樹(c語言)
阿新 • • 發佈:2018-12-25
一、線索二叉樹
如果二叉樹的節點包含資料域和兩個指標域( 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; }
三、效果展示