先序線索化二叉樹


  先序線索化在很多書上都有詳細解讀,這里只是寫了一個較為完整的一個程序罷了

  1 #include <iostream>
  2 using namespace std;
  3 
  4 enum flag{Child, nChild};
  5 
  6 struct Node {
  7     char data;
  8     Node * lchild;
  9     Node * rchild;
 10     flag ltag, rtag;    // Child 表示是左或右孩子  nChild 表示前驅或后繼
 11 };
 12 
 13 class Tree {
 14 public:
 15     Tree();
 16     ~Tree();
 17     Node * getRoot();
 18     void Show_preTree(Node *);    // 先序遍歷輸出
 19 private:
 20     Node * root;
 21     Node * Create();        // 供構造函數調用初始化二叉樹
 22     void Delete(Node *);    // 供析構函數析構二叉樹
 23     void _preTree(Node *, Node *&);        // 先序 線索化
 24 };
 25 
 26 int main() {
 27     cout << "以先序方式輸入二叉樹:";
 28 
 29     Tree T;
 30     T.Show_preTree(T.getRoot());
 31 
 32     system("pause");
 33     return 0;
 34 }
 35 
 36 Tree::Tree() {
 37     root = Create();        // 先創建一個默認的二叉樹
 38     Node * pre = NULL;
 39     _preTree(root, pre);
 40 }
 41 
 42 Tree::~Tree() {
 43     Node * p = NULL;
 44     while (root != NULL) {
 45         p = root;                        // 待刪除結點
 46         if (root->ltag == Child) {    
 47             root = root->lchild;        // 有左孩子,則指向左孩子
 48         } else {
 49             root = root->rchild;        // 沒有左孩子,指向右孩子或者 后繼
 50         }
 51         delete p;
 52     }
 53 }
 54 
 55 Node * Tree::Create() {
 56     Node * root;
 57     char ch;
 58     cin >> ch;
 59     if (ch == '#') {
 60         root = NULL;
 61     } else {
 62         root = new Node();
 63         root->data = ch;
 64         root->ltag = root->rtag = Child;        //  默認設置左右指針域 為孩子
 65         root->lchild = Create();
 66         root->rchild = Create();
 67     }
 68     return root;
 69 }
 70 
 71 Node * Tree::getRoot() {
 72     return root;
 73 }
 74 
 75 void Tree::_preTree(Node * root, Node * &pre) {
 76     if (root == NULL) {                // 空結點,不操作,返回
 77         return;
 78     }
 79 
 80     if (root->lchild == NULL) {        // 左孩子為空,設置前驅,前驅為pre, pre表示上一次訪問過的結點
 81         root->lchild = pre;
 82         root->ltag = nChild;        // 左標志置為 nChild 表示是前驅
 83     }    
 84     if (pre != NULL && pre->rchild == NULL) {        // 上一個結點的,即上一次訪問過的結點右孩子為空,則在此時設置后繼
 85         pre->rchild = root;
 86         pre->rtag = nChild;            // 右標志置為 nChild 表示是后繼
 87     }
 88 
 89     pre = root;                        // pre 指向當前結點,下面開始遞歸一次,遞歸時,pre作為上一次訪問過的結點,即當前指向的結點
 90 
 91     if (root->ltag == Child) {        // 當前結點還有左孩子,遞歸一次
 92         _preTree(root->lchild, pre);
 93     }
 94     if (root->rtag == Child) {        // 當前結點還有右孩子,遞歸一次
 95         _preTree(root->rchild, pre);
 96     }
 97 }
 98 
 99 void Tree::Show_preTree(Node * root) {
100     Node * p = root;
101     if (p == NULL) {
102         return;
103     } else if (p->ltag == Child) {
104         cout << p->data << " ";
105         Show_preTree(p->lchild);
106     } else {
107         cout << p->data << " ";
108         Show_preTree(p->rchild);
109     }
110     /*
111     由於先序線索化(遍歷根、左、右),可以看出(畫圖看最清晰):
112         當 this(當前結點)的 ltag為Child的時候表示它是有孩子的應該先遍歷左子樹,直接可以 p = p->lchild然后輸出當前結點
113         當 this 的 ltag為 nChild的時候,表示沒有了左孩子,這個時候就應該遍歷它的右孩子 或者 是它的后繼 ( p = p->rchild)
114         由於 當某個結點沒有右孩子的時候,它會存在后繼,所以可以當做是“右孩子”一樣,當結點不存在右孩子或后繼時,表明已經到了右子樹的尾端
115     */
116 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM