今天寫了一下線索二叉樹的建立和遍歷,感受還能夠,不算很難,把思路理清楚以後,就好下手了。數據結構
記得剛開始看數據結構的時候,感受很是頭疼,如今愈來愈感受有意思了,固然,主要是在解決了一個問題以後的成就感讓人很知足。
函數
/* 線索二叉樹的創建,遍歷代碼實現 */ # include <stdio.h> # include <stdlib.h> # include <malloc.h> //這裏失誤了,剛開始都加了";"號,致使報錯missing ')' before ';' # define LINK 0 # define THREAD 1 # define OK 1 # define ERROR 0 typedef char TElemType; typedef int Status; /* 線索樹節點 */ typedef struct BiThrNode { TElemType data; struct BiThrNode * lchild, * rchild; //左右孩子的指針 Status LTag, RTag; }BITHRTREE, * PBITHRTREE; //定義一個全局變量pre,用於指定一個前驅元素 PBITHRTREE pre = NULL; /* 建立一顆二叉樹 第一次定義這個函數的時候是這樣寫的 Status CreateTree( PBITHRTREE ); 報錯:error C2668: 'CreateTree' : ambiguous call to overloaded function 緣由是使用了引用,而在函數前置中沒有體現出來,須要改成: Status CreateTree( PBITHRTREE & ); */ Status CreateTree( PBITHRTREE & ); /* 使用遞歸的方法,中序遍歷二叉樹 */ Status InOrderTraveler( PBITHRTREE & ); /* 爲二叉樹添加線索 */ Status InOrderTreading( PBITHRTREE &, PBITHRTREE ); /* 中序遍歷的方式添加線索 */ Status InThreading( PBITHRTREE ); /* 按照線索遍歷二叉樹 */ Status InOrderTraveler_Thread( PBITHRTREE & ); /* 建立一個二叉樹,空格表明無子樹。 函數的形參,使用引用的方式,操做簡便。 */ Status CreateTree( PBITHRTREE &BaseTree ) { TElemType data; scanf( "%c", &data ); if( ' ' == data ) { BaseTree = NULL; } else { BaseTree = ( PBITHRTREE )malloc( sizeof( BITHRTREE ) ); BaseTree -> data = data; CreateTree( BaseTree -> lchild ); CreateTree( BaseTree -> rchild ); } return OK; } /* 使用遞歸的方法,中序遍歷二叉樹 PS:其實寫這個中序遍歷的函數,主要是想看看方纔的二叉樹生成了沒 ……囧…… */ Status InOrderTraveler( PBITHRTREE &BaseTree ) { if( NULL != BaseTree ) { InOrderTraveler( BaseTree -> lchild ); printf( "%c", BaseTree -> data ); InOrderTraveler( BaseTree -> rchild ); } return OK; } /* 爲一個二叉樹添加線索,以中序爲例 @param PBITHRTREE &ThreadTree 要生成的線索二叉樹 @param PBITHRTREE &BaseTree 已經生成基礎二叉樹 return Status; */ Status InOrderTreading( PBITHRTREE &ThreadTree, PBITHRTREE BaseTree ) { //建立一個頭結點 ThreadTree = ( PBITHRTREE )malloc( sizeof( BITHRTREE ) ); ThreadTree -> LTag = LINK; ThreadTree -> RTag = THREAD; ThreadTree -> rchild = ThreadTree; //右指針回指 if( NULL == BaseTree ) { ThreadTree -> lchild = ThreadTree; //基礎樹爲空,這左孩子回指 } else { ThreadTree -> lchild = BaseTree; // 這裏須要一個全局變量,來指示前驅元素 pre = ThreadTree; InThreading( BaseTree ); pre -> RTag = THREAD; pre -> rchild = ThreadTree; ThreadTree -> rchild = pre; } return OK; } /* 中序的方式設置線索 */ Status InThreading( PBITHRTREE Tree ) { if( NULL != Tree ) { InThreading( Tree -> lchild ); if( NULL == Tree -> lchild ) { //若是右孩子是空,那麼放入前驅元素 Tree -> LTag = THREAD; Tree -> lchild = pre; } if( NULL == pre -> rchild ) { /* 若是這個前驅元素的右孩子爲空,就把當前節點的指針賦予它 做爲後繼元素 */ pre -> RTag = THREAD; pre -> rchild = Tree; } pre = Tree; InThreading( Tree -> rchild ); } return OK; } /* 按照線索遍歷二叉樹 */ Status InOrderTraveler_Thread( PBITHRTREE & Tree ) { PBITHRTREE p = Tree -> lchild; while( p != Tree ) { /* 首先,一路查找每一個元素的ltag是否是等於1 若是等於1,說明這是第一個節點,將其值輸出 注意!!! 怎麼會這樣呢?(其實我想說個我草),下行一開始寫的 while( p -> LTag != LINK ) 沒法找到第一個節點,致使遍歷出錯,之後長點心吧 */ while( p -> LTag != THREAD ) { //printf( "遍歷到了%c,他的LTag是%d\n", p -> data, p -> LTag ); p = p -> lchild; } //循環退出,說明這是第一個節點,輸出其值 printf( "%c", p -> data ); /* 查看他的LTag,若是也是1,說明是線索,直接輸出 若是不是1,說明他有孩子,將指針下移一位, 從第一個while那裏按照這裏的思路再循環一次 */ while( p -> RTag == THREAD && p -> rchild != Tree ) { p = p -> rchild; printf( "%c", p -> data ); } p = p -> rchild; } return OK; } Status main( void ) { PBITHRTREE ThreadTree = NULL, BaseTree = NULL; //首先建造一顆不帶線索的二叉樹 printf( "請輸入一顆二叉樹:\n" ); CreateTree( BaseTree ); printf( "中序遞歸遍歷二叉樹:\n" ); InOrderTraveler( BaseTree ); printf( "\n" ); printf( "將剛纔創造的二叉樹線索化。…… Lording ……" ); InOrderTreading( ThreadTree, BaseTree ); printf( "\n" ); printf( "按照線索遍歷二叉樹:\n" ); InOrderTraveler_Thread( ThreadTree ); printf( "\n" ); return 0; } /* VC++6.0中輸出的結果是 ======================================= 請輸入一顆二叉樹: ABEQ F CD 中序遞歸遍歷二叉樹: QEFBADC 將剛纔創造的二叉樹線索化。…… Lording …… 按照線索遍歷二叉樹: QEFBADC ======================================= 總結: 須要總結的地方太多了,都是一些白癡性錯誤,邏輯上仍是比較清晰的。 好比說: 預約義不用就加「;」 修改函數類型的時候,記得把前置函數定義哪裏也修改了 還有就是須要在編寫的時候,再 認真一些。 */
學PHP的小螞蟻 博客 http://my.oschina.net/woshixiaomayi/blogspa