C語言:線索二叉樹的線索化及其遍歷實現
阿新 • • 發佈:2019-02-07
前序和中序遍歷都實現了,後序線索化還不是很明白!如有大神看到,望指正!不勝感激!
// 中序線索二叉樹實現.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include<iostream> #include<stdio.h> #include<math.h> using namespace std; #define ElementType char typedef enum{ Link, Thread } PointerTag; //線索儲存標誌位 //Link(0):表示指向左右孩子的指標 //Thread(1):表示指向前驅和後繼的線索 typedef struct BiThrNode { ElementType Data; struct BiThrNode *Left; struct BiThrNode *Right; PointerTag Ltag; PointerTag Rtag; }BiThrNode, *BiThrTree; //全域性變數,始終指向剛剛問過的節點 BiThrNode *pre; //建立一個二叉樹:利用前序遍歷建立二叉樹 //函式宣告 void CreatTree(BiThrTree *BT); void DestroyBiTree(BiThrTree &T); void DestroyBiThrTree(BiThrTree &Thrt); //中序線索化二叉樹,並且實現中序遍歷操作函式定義 void InThreding(BiThrTree BT); void InorderThreding(BiThrTree *p, BiThrTree T); void InOrderTraverse(BiThrTree T); void InOrderTraverse_Iter(BiThrTree T); //前序線索化二叉樹,並且實現前序遍歷操作函式定義 void PreThreding(BiThrTree BT); void PreorderThreding(BiThrTree *p, BiThrTree T); void PreOrderTraverse(BiThrTree T); void PreOrderTraverse_Iter(BiThrTree T); //後序線索化二叉樹,並且實現後序遍歷操作函式定義 void PostThreding(BiThrTree BT); void PostorderThreding(BiThrTree *p, BiThrTree T); void PostOrderTraverse(BiThrTree T); void PostOrderTraverse_Iter(BiThrTree T); //函式定義 void CreatTree(BiThrTree *BT) { char ch; cin >> ch; if (ch == '#') *BT = NULL; else { *BT = (BiThrNode*)malloc(sizeof(struct BiThrNode)); (*BT)->Data = ch; (*BT)->Ltag = Link; (*BT)->Rtag = Link; CreatTree(&(*BT)->Left); CreatTree(&(*BT)->Right); } } void PostOrderTraverse(BiThrTree T) { if (T) { PostOrderTraverse(T->Left); PostOrderTraverse(T->Right); cout << T->Data; } } void InOrderTraverse(BiThrTree T) { if (T) { InOrderTraverse(T->Left); cout << T->Data; InOrderTraverse(T->Right); } } void PreOrderTraverse(BiThrTree T) { if (T) { cout << T->Data; PreOrderTraverse(T->Left); PreOrderTraverse(T->Right); } } void DestroyBiTree(BiThrTree &T) { if (T) // 非空樹 { if (T->Ltag == Link) // 有左孩子 DestroyBiTree(T->Left); // 銷燬左孩子子樹 if (T->Rtag == Link) // 有右孩子 DestroyBiTree(T->Right); // 銷燬右孩子子樹 free(T); // 釋放根結點 T = NULL; // 空指標賦0 } } // 初始條件:線索二叉樹Thrt存在。操作結果:銷燬線索二叉樹Thrt void DestroyBiThrTree(BiThrTree &T) { if (T) // 頭結點存在 { if (T->Left) // 根結點存在 { DestroyBiTree(T->Left); // 遞迴銷燬頭結點lchild所指二叉樹 } free(T); // 釋放頭結點 T = NULL; // 線索二叉樹Thrt指標賦0 } } //前序線索化二叉樹,並且實現前序遍歷操作函式定義 void PreThreding(BiThrTree BT) { if (BT) { if (!BT->Left) { BT->Ltag = Thread; BT->Left = pre; } if (!pre->Right) { pre->Right = BT; pre->Rtag = Thread; } pre = BT; if (BT->Ltag == Link) PreThreding(BT->Left);//遞迴左孩子線索化 if (BT->Rtag == Link) PreThreding(BT->Right);//遞迴右孩子線索化 } } void PreorderThreding(BiThrTree *p, BiThrTree T) {//p結點為頭結點,T結點為樹根結點 *p = (BiThrNode*)malloc(sizeof(struct BiThrNode)); (*p)->Ltag = Link; (*p)->Rtag = Thread; (*p)->Right = *p; if (!T) (*p)->Left = *p; else { (*p)->Left = T; pre = *p; PreThreding(T); pre->Right = *p; pre->Rtag = Thread; (*p)->Right = pre; } } void PreOrderTraverse_Iter(BiThrTree T) { BiThrTree p = T->Left; while (p != T) { cout << p->Data; if (p->Ltag == Link) p = p->Left; else p = p->Right; } } //與前序有關的函式實現結束 //中序線索化二叉樹,並且實現中序遍歷操作 //中序遍歷線索化的過程 void InThreding(BiThrTree BT) { if (BT) { InThreding(BT->Left);//遞迴左孩子線索化 //結點處理 if (!BT->Left) //如果該結點沒有左孩子, { BT->Ltag = Thread; BT->Left = pre; } if (!pre->Right) { pre->Rtag = Thread; pre->Right = BT; } pre = BT; InThreding(BT->Right);//遞迴右孩子線索化 } } void InorderThreding(BiThrTree *p, BiThrTree T) {//p結點為頭結點,T結點為樹根結點 *p = (BiThrNode*)malloc(sizeof(struct BiThrNode));//建立一個頭結點 (*p)->Ltag = Link; (*p)->Rtag = Thread; (*p)->Right = *p; //有指標回指 if (!T) (*p)->Left = *p; //若二叉樹為空,則做指標回指 else { (*p)->Left = T; //若二叉樹不為空,Left指向根結點 pre = *p; InThreding(T); //中序遍歷進行中序線索化 //最後一個結點線索化 pre->Rtag = Thread; pre->Right = *p; //終端結點指向頭結點 (*p)->Right = pre; //頭結點的右指標指向終端結點 } } //中序遍歷二叉樹,非遞迴實現 void InOrderTraverse_Iter(BiThrTree T) { BiThrTree p; p = T->Left; //p指向根結點T while (p != T) //二叉樹非空或遍歷未結束 { while (p->Ltag == Link) //訪問左子樹為空的結點 { p = p->Left; } cout << p->Data; while ((p->Rtag == Thread)&&(p->Right != T)) //p的Right指向後繼,訪問p結點的後繼 { p = p->Right; cout << p->Data; } p = p->Right; //p的Right指向右孩子 } } //與中序有關的函式實現結束 //後序線索化二叉樹,並且實現後序遍歷操作函式定義 void PostThreding(BiThrTree BT) { if (BT) { PostThreding(BT->Left); PostThreding(BT->Right); if (!BT->Left) { BT->Ltag = Thread; BT->Left = pre; } if (!pre->Right) { pre->Rtag = Thread; pre->Right = BT; } pre = BT; } } void PostorderThreding(BiThrTree *p, BiThrTree T) { //p結點為頭結點,T結點為樹根結點 *p = (BiThrNode*)malloc(sizeof(struct BiThrNode)); (*p)->Ltag = Link; (*p)->Rtag = Thread; if (!T) (*p)->Left = (*p)->Right = *p; else { (*p)->Left = (*p)->Right = *p; pre = *p; PostThreding(T); if (pre->Rtag != Link) // 最後一個結點沒有右孩子 { pre->Right = *p; // 最後一個結點的後繼指向頭結點 pre->Rtag = Thread; } } } void PostOrderTraverse_Iter(BiThrTree T) { BiThrTree p =T->Left; while (p->Ltag == Link || p->Rtag == Link) //有左孩子先訪問左孩子,沒有左孩子先訪問右孩子 { while (p->Ltag == Link) p = p->Left; if (p->Rtag == Link) //訪問左孩子為空的結點的右孩子 p = p->Right; } cout << p->Data; while (p != T) //p不為根結點 { if (p->Rtag == Link) //若p是有兄弟的左孩子 { if (pre->Rtag == Thread || p == pre->Right) //若p是雙親的右孩子或是獨生左孩子,則後繼為雙親 p = pre; else { p = pre->Right; //後繼為雙親的右子樹上按照後序遍歷訪問的第一個結點。 while (p->Ltag == Link || p->Rtag == Link) { if(p->Ltag == Link) p = p->Left; if (p->Rtag == Link) p = p->Right; } } } else p = p->Right; //p指向後繼 cout << p->Data; } } //與後序有關的函式實現結束 int _tmain(int argc, _TCHAR* argv[]) { BiThrTree T = NULL; BiThrTree BT = NULL; BiThrTree A = NULL; BiThrTree BA = NULL; BiThrTree D = NULL; BiThrTree BD = NULL; cout << "按照前序遍歷建立二叉樹:" << endl; CreatTree(&T); cout << "中序遍歷:"; InOrderTraverse(T); cout << endl; cout << "中序線索化!" << endl; InorderThreding(&BT, T); cout << "中序線索化後輸出:"; InOrderTraverse_Iter(BT); cout << endl; DestroyBiThrTree(BT); cout << "按照前序遍歷建立二叉樹:" << endl; CreatTree(&A); cout << "前序遍歷:"; PreOrderTraverse(A); cout << endl; cout << "前序線索化!" << endl; PreorderThreding(&BA, A); cout << "前序線索化後輸出:"; PreOrderTraverse_Iter(BA); cout << endl; DestroyBiThrTree(BA); cout << "按照前序遍歷建立二叉樹:" << endl; CreatTree(&D); cout << "後序遍歷:"; PostOrderTraverse(D); cout << endl; cout << "後序線索化!" << endl; PostorderThreding(&BD, D); cout << "後序線索化後輸出:"; PostOrderTraverse_Iter(BD); DestroyBiThrTree(BD); cout << endl; return 0; }