樹——線索二叉樹的建立、遍歷(前序、中序、後序)
阿新 • • 發佈:2018-12-25
直接上程式碼。
#include<iostream> #include<cstdio> using namespace std; #define OK 1 #define ERROR 0 typedef int Status; typedef char TElemType; /* 定義線索二叉樹的資料結構 */ typedef struct BiThrNode { char data;//結點對應的資料 int ltag, rtag;//左右孩子標記 struct BiThrNode *lchild;//左孩子 struct BiThrNode *rchild;//右孩子 }BiThrNode,*BiThrTree; /* 輸出對應結點裡面的值 */ Status PrintElement(TElemType e) { cout << e; return OK; } /* 尋找p結點在Thrt樹中的父節點,便於進行後序遍歷 */ BiThrTree parent(BiThrTree &Thrt, BiThrTree &p) { BiThrTree temp=Thrt->lchild; if (p==Thrt->lchild)//p即為根節點,返回建立的頭結點 { return Thrt; } if (temp->lchild == p) { return temp;//父節點就是我們尋找的結點 } else { temp = temp->lchild; while (temp->lchild != p&&temp->rchild != p) { /* 如果節點有右孩子,那就往右 如果節點沒有右孩子,就往左 沒有左孩子,就往前驅 */ if (temp->rtag == 0) { temp = temp->rchild; } else { temp = temp->lchild; } } return temp; } } /* 建立線索二叉樹,初始化跟二叉樹的初始化遞迴演算法一樣 */ Status CreateBiThrTree(BiThrTree &T) { char ch; cin >> ch; if (ch == '#') T = NULL; else { if (!(T = (BiThrNode *)malloc(sizeof(BiThrNode)))) exit(OVERFLOW); T->data = ch; T->ltag = 0; T->rtag = 0; CreateBiThrTree(T->lchild); CreateBiThrTree(T->rchild); } return OK; } /* T指向頭結點,頭結點的左鏈lchild指向根節點 中序遍歷二叉線索樹T的非遞迴演算法,對每個資料元素呼叫函式Visit */ Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)) { BiThrTree p = T->lchild; while (p&&(p != T)) { while (p->ltag == 0) { p = p->lchild; } Visit(p->data); while (p->rtag == 1 && p->rchild != T) { p = p->rchild; Visit(p->data); } p = p->rchild; } return OK; } /* 前序遍歷二叉樹非遞迴演算法(仿造中序遍歷) */ Status PreOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)) { BiThrTree p = T; while (p) { while (p->ltag == 0) { Visit(p->data); p = p->lchild; } Visit(p->data); p = p->rchild; } return OK; } /* 後序遍歷二叉樹非遞迴演算法 */ Status PostOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)) { BiThrTree p = T->lchild; BiThrTree pre = T; //p指向第一個被訪問結點 while (p->ltag == 0||p->rtag==0) { while(p->ltag==0) p = p->lchild; if (p->rtag == 0) p = p->rchild; } while (p != T) { Visit(p->data); pre = parent(T, p);//找到該節點的雙親 if (T == pre)//如果雙親是T,就說明p是根節點,無後繼 { p = T; } //如果p是雙親的右孩子,或者雙親無右孩子,則後繼為雙親 else if(p==pre->rchild||pre->rtag==1) { p = pre; } else { //若p的雙親有右孩子,後繼為雙親右子樹上後序遍歷的第一個孩子 while (pre->rtag == 0) { pre = pre->rchild; while (pre->ltag == 0) { pre = pre->lchild; } } p = pre; } } return OK; } /* 中序遍歷進行二叉樹線索化 */ void InThreading(BiThrTree p,BiThrTree &pre) { if (p) { InThreading(p->lchild,pre);//左子樹線索化 if (!p->lchild) { p->ltag = 1; p->lchild = pre; } if ((!pre->rchild)&&pre->rchild==NULL) { pre->rtag = 1; pre->rchild = p; } pre = p; InThreading(p->rchild, pre);//右子樹線索化 } } /* 前序遍歷進行二叉樹線索化 */ void preThreading(BiThrTree p, BiThrTree &pre) { if (p) { if (p->lchild == NULL) { p->lchild = pre; p->ltag = 1; } if (pre != NULL&&pre->rchild == NULL) { pre->rchild = p; pre->rtag = 1; } pre = p; if (p->ltag == 0) preThreading(p->lchild, pre); if (p->rtag == 0) preThreading(p->rchild, pre); } } /* 後序遍歷進行線索二叉樹化 */ void postThreading(BiThrTree p, BiThrTree &pre) { if (p) { postThreading(p->lchild, pre); postThreading(p->rchild, pre); if (p->lchild==NULL) { p->lchild = pre; p->ltag = 1; } if (pre != NULL&&pre->rchild == NULL) { pre->rchild = p; pre->rtag = 1; } pre = p; } } /* 中序遍歷二叉樹T,並將其中序線索化,Thrt指向頭結點 */ Status InOrderThreading(BiThrTree &Thrt, BiThrTree T) { //建立頭結點 if (!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode)))) exit(OVERFLOW); Thrt->ltag = 0; Thrt->rtag = 1; Thrt->rchild = Thrt;//右指標回指 BiThrTree pre; if (!T) Thrt->lchild = Thrt;//若二叉樹為空,則指標回指 else { Thrt->lchild = T; pre = Thrt; InThreading(T,pre);//中序遍歷進行中序線索化 pre->rchild = Thrt;//最後一個結點線索化 pre->rtag = 1; Thrt->rchild = pre; } return OK; } /* 後序遍歷二叉樹,並將其線索化,原理同中序 */ Status PostOrderThreading(BiThrTree &Thrt, BiThrTree T) { //建立頭結點 if (!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode)))) exit(OVERFLOW); Thrt->ltag = 0; Thrt->rtag = 1; Thrt->rchild = Thrt;//右指標回指 BiThrTree pre; if (!T) Thrt->lchild = Thrt;//若二叉樹為空,則指標回指 else { Thrt->lchild = T; pre = NULL; postThreading(T, pre);//後序遍歷進行後序線索化 pre->rchild = Thrt; pre->rtag = 1; Thrt->rchild = pre;//最後一個結點線索化 } return OK; } void main() { BiThrTree T1, Thrt1; cout << "建立線索二叉樹,按先序次序輸入線索二叉樹中結點的值:\n"; CreateBiThrTree(T1); if (InOrderThreading(Thrt1, T1) == OK) cout << "成功建立中序線索化連結串列!\n"; cout << "中序遍歷線索二叉樹,結果是:\n"; InOrderTraverse_Thr(Thrt1, PrintElement); cout << endl; BiThrTree T2; cout << "建立線索二叉樹,按先序次序輸入線索二叉樹中結點的值:\n"; CreateBiThrTree(T2); BiThrTree test1 = T2; preThreading(T2, test1); cout << "前序遍歷線索二叉樹,結果是:\n"; PreOrderTraverse_Thr(T2, PrintElement); cout << endl; BiThrTree T3,Thrt3; cout << "建立線索二叉樹,按先序次序輸入線索二叉樹中結點的值:\n"; CreateBiThrTree(T3); if (PostOrderThreading(Thrt3, T3) == OK) cout << "成功建立後序序線索化連結串列!\n"; cout << "後序遍歷線索二叉樹,結果是:\n"; PostOrderTraverse_Thr(Thrt3, PrintElement); cout << endl; system("pause"); }