實現下面這棵樹:
先序遍歷: A B C D E F
中序遍歷: C B D A E Fide
代碼函數
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <unistd.h> typedef enum {links, thread} TAG; typedef struct treeNode { char name; struct treeNode *lchild, *rchild; TAG ltag; TAG rtag; }TREENODE, *TREE; void createTree(TREE *); void traverse(TREE); void traverse_middle(TREE); void traverse_middle_detail(TREE); // 線索化二叉樹,相比普通的中序遍歷,這裏把輸出節點數據的步驟改成了判斷指針域的邏輯 void inThread(TREE, TREE *, TREE); void traverse_inThread_by_rchild(TREE); // 調用此函數時須要傳入head void traverse_inThread_by_rchild(TREE head) { printf("中序正向遍歷二叉鏈表:\n"); printf("self %p - lc %10p, lt %u, %c, rt %u, rc %10p\n", head, head->lchild, head->ltag, head->name, head->rtag, head->rchild); TREE p = head->lchild; while (p->lchild != head) { p = p->lchild; //usleep(100000); } while (p) { printf("self %p - lc %10p, lt %u, %c, rt %u, rc %10p\n", p, p->lchild, p->ltag, p->name, p->rtag, p->rchild); p = p->rchild; } } void inThread(TREE p, TREE *pre, TREE head) { if (! p) return; inThread(p->lchild, pre, head); printf("pre p %p - lc %10p, lt %u, %c, rt %u, rc %10p\n", (*pre), (*pre)->lchild, (*pre)->ltag, (*pre)->name, (*pre)->rtag, (*pre)->rchild); // 判斷自身是否有左孩子,若是沒有指向前驅節點 if (! p->lchild) { p->ltag = thread; p->lchild = *pre; } /* * 由於遍歷(中序)時,路徑只走到當前節點,並不知道後繼是否有, * 因此每一個節點都只處理本身的前驅和前驅的後繼 * head節點rchild在第1個節點處理時指向了第1個節點 */ if (! (*pre)->rchild) { (*pre)->rtag = thread; (*pre)->rchild = p; } printf(" inThread p %p - lc %10p, lt %u, %c, rt %u, rc %10p\n", p, p->lchild, p->ltag, p->name, p->rtag, p->rchild); // 本節點處理完後,更新pre指向自身,做爲中序遍歷下一個節點的前驅 *pre = p; // 頭指針rchild指向當前節點,最終線索化完成後,頭節點的右孩子一定指向中序最後1個節點 head->rchild = p; inThread(p->rchild, pre, head); } void traverse_middle(TREE p) { if (p) { traverse_middle(p->lchild); printf("%c ", p->name); traverse_middle(p->rchild); } } void traverse_middle_detail(TREE p) { if (p) { traverse_middle_detail(p->lchild); printf("self %p - lc %10p, lt %u, %c, rt %u, rc %10p\n", p, p->lchild, p->ltag, p->name, p->rtag, p->rchild); traverse_middle_detail(p->rchild); } } void traverse(TREE p) { if (p) { printf("%c ", p->name); traverse(p->lchild); traverse(p->rchild); } } // 前序初始化樹的各節點 void createTree(TREE *p) { char c; scanf("%c", &c); if (c == '_') { *p = NULL; } else { *p = (TREE)malloc(sizeof(TREENODE)); (*p)->name = c; // 不管是否會有左右孩子,都先把tag標識爲links (*p)->ltag = (*p)->rtag = links; createTree(&(*p)->lchild); createTree(&(*p)->rchild); } } int main(void) { // 頭指針,指向線索二叉樹的頭節點(該節點的lchild指向root) TREE head = NULL; TREE tree; head = (TREE)malloc(sizeof(TREENODE)); head->lchild = head->rchild = NULL; head->ltag = head->rtag = thread; // 爲了方便確認頭節點 head->name = 'H'; TREE pre = head; createTree(&tree); // 頭節點lchild手動指向tree根節點(rchild已經在線索化完成後指向了中序最後1個節點) head->lchild = tree; printf("先序遍歷: "); traverse(tree); putchar('\n'); printf("中序遍歷: "); traverse_middle(tree); putchar('\n'); printf("中序遍歷(detail):\n"); traverse_middle_detail(tree); putchar('\n'); // 線索化二叉樹(把空閒的lchild, rchild指向各自的前驅和後繼) inThread(tree, &pre, head); // 使用rchild遍歷中序線索化的二叉鏈表 traverse_inThread_by_rchild(head); /* * 目前中序最後1個節點的rchild依然是NULL,可是已經能夠實現根據頭節點正反向遍歷二叉鏈表 * 若是按照其它教程裏的須要把中序尾節點rchild的指向頭節點,則中序遍歷記住最後1個指針操做一下就能夠。。。(若是須要判斷空樹等狀況能夠參考網上其它教程) */ return 0; }
output指針
[root@8be225462e66 c]# gcc thrTree.c && ./a.out ABC__D__E_F__ 先序遍歷: A B C D E F 中序遍歷: C B D A E F 中序遍歷(detail): self 0x1a83740 - lc (nil), lt 0, C, rt 0, rc (nil) self 0x1a83710 - lc 0x1a83740, lt 0, B, rt 0, rc 0x1a83770 self 0x1a83770 - lc (nil), lt 0, D, rt 0, rc (nil) self 0x1a836e0 - lc 0x1a83710, lt 0, A, rt 0, rc 0x1a837a0 self 0x1a837a0 - lc (nil), lt 0, E, rt 0, rc 0x1a837d0 self 0x1a837d0 - lc (nil), lt 0, F, rt 0, rc (nil) pre p 0x1a832a0 - lc 0x1a836e0, lt 1, H, rt 1, rc (nil) inThread p 0x1a83740 - lc 0x1a832a0, lt 1, C, rt 0, rc (nil) pre p 0x1a83740 - lc 0x1a832a0, lt 1, C, rt 0, rc (nil) inThread p 0x1a83710 - lc 0x1a83740, lt 0, B, rt 0, rc 0x1a83770 pre p 0x1a83710 - lc 0x1a83740, lt 0, B, rt 0, rc 0x1a83770 inThread p 0x1a83770 - lc 0x1a83710, lt 1, D, rt 0, rc (nil) pre p 0x1a83770 - lc 0x1a83710, lt 1, D, rt 0, rc (nil) inThread p 0x1a836e0 - lc 0x1a83710, lt 0, A, rt 0, rc 0x1a837a0 pre p 0x1a836e0 - lc 0x1a83710, lt 0, A, rt 0, rc 0x1a837a0 inThread p 0x1a837a0 - lc 0x1a836e0, lt 1, E, rt 0, rc 0x1a837d0 pre p 0x1a837a0 - lc 0x1a836e0, lt 1, E, rt 0, rc 0x1a837d0 inThread p 0x1a837d0 - lc 0x1a837a0, lt 1, F, rt 0, rc (nil) 中序正向遍歷二叉鏈表: self 0x1a832a0 - lc 0x1a836e0, lt 1, H, rt 1, rc 0x1a837d0 self 0x1a83740 - lc 0x1a832a0, lt 1, C, rt 1, rc 0x1a83710 self 0x1a83710 - lc 0x1a83740, lt 0, B, rt 0, rc 0x1a83770 self 0x1a83770 - lc 0x1a83710, lt 1, D, rt 1, rc 0x1a836e0 self 0x1a836e0 - lc 0x1a83710, lt 0, A, rt 0, rc 0x1a837a0 self 0x1a837a0 - lc 0x1a836e0, lt 1, E, rt 0, rc 0x1a837d0 self 0x1a837d0 - lc 0x1a837a0, lt 1, F, rt 0, rc (nil) [root@8be225462e66 c]#