后序线索化二叉树

 1 void Tree::_postTree(Node * root, Node *&pre) {
 2     if (root == NULL) {        // 空值不操作
 3         return;
 4     }
 5     else {
 6         _postTree(root->lchild, pre);    // 递归左树,首先是递归到左子树的最左下的结点
 7         _postTree(root->rchild, pre);    // 递归右树,首先是递归到左子树的最左下的第一个右结点
 8         // 对当前结点进行操作,只对含有空指针的结点指针域操作
 9         if (root->lchild == NULL) {        // 左孩子为空,操作的是前驱,前驱是 pre
10             root->ltag = nChild;
11             root->lchild = pre;
12         }
13         // 首先要判断 pre 是否为空,后才能判断他的指针域,因为第一次的 pre在未执行下面语句 pre = root 时是NULL 值, 指针为 NULL值的没有访问其他内存空间的权限
14         if (pre != NULL && pre->rchild == NULL) {    // 右孩子为空,操作的是后继, pre是前驱的话,那么root不就是后继吗?
15             pre->rtag = nChild;
16             pre->rchild = root;
17         }
18         pre = root;
19     }
20 }
后序线索化
 1 void Tree::Show_postTree(Node * root) {
 2     cout << "后序线索化遍历(最大使用栈暂存元素个数 100):";
 3     Node * Stack[100];    // 后序遍历需要用到栈,所以该方法有局限性
 4     int top = -1;
 5     Node * p = root;
 6     Node * pre = NULL;            // 作为前驱,保留上一次访问过的指针域
 7     do {
 8         while (p != NULL) {        // 将当前结点的左孩子全部入栈,一直走到最左边的左孩子
 9             Stack[++top] = p;
10             p = p->lchild;
11             if (p == pre) {        // 防止对叶子结点操作中, p = p->rchild 导致 p 不为 NULL, 在执行上面一条语句 p = p->lchild时再次访问了已访问过的结点
12                 break;
13             }
14         }
15         p = Stack[top];            // 将 p 指向栈顶指针域,进行操作当前结点
16         if (p->rtag == nChild || p->rchild == pre) {    // 当前结点没有右孩子 或者 它的右孩子已经被访问过
17             cout << p->data << " ";
18             top--;        // 输出一个结点,就出栈一个指针域
19             pre = p;
20             p = NULL;    // p 为 NULL,目的是为了使其不满足第一个while,防止再次访问已访问过的结点,转去操作下一个结点
21         }
22         else {
23             p = p->rchild;
24         }
25     } while (top != -1 && pre != NULL);
26     cout << endl;
27 }
后序遍历
 1 Tree::~Tree() {
 2     Node * Queue[100];
 3     int rear = -1, front = -1;
 4     if(root != NULL) {
 5         Queue[++rear] = root;
 6     } 
 7     Node * p = NULL;
 8     while (rear != front) {
 9         p = Queue[front+1];
10         if(p->ltag == Child) {            // 有左孩子就进队,没有就不管,判断有无孩子 是看它的标志
11             Queue[++rear] = p->lchild;
12         }
13         if(p->rtag == Child) {            // 有右孩子入队
14             Queue[++rear] = p->rchild;
15         }
16         cout << "析构:" << p->data << endl;
17         delete p;                        // 删除队头所指向的那一块存储空间
18         front++;                        // 出队一个 front+1
19     }
20     system("pause");
21 }
后序线索化的析构
  1 #include <iostream>
  2 using namespace std;
  3 
  4 enum flag{ Child, nChild };    // Child 表示有孩子 nChild 即 not Child 没有孩子
  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_postTree(Node *);    // 后序遍历输出
 19 private:
 20     Node * root;
 21     Node * Create();                    // 供构造函数调用初始化二叉树
 22     void _postTree(Node *, Node *&);    // 后序 线索化
 23 };
 24 
 25 int main() {
 26     cout << "以先序方式输入二叉树('#'代表NULL):";
 27 
 28     Tree T;
 29 
 30     T.Show_postTree(T.getRoot());
 31 
 32     system("pause");
 33     return 0;
 34 }
 35 
 36 Tree::Tree() {
 37     root = Create();        // 先创建一个默认的二叉树
 38     Node * pre = NULL;
 39     _postTree(root, pre);
 40 }
 41 
 42 Tree::~Tree() {
 43     Node * Queue[100];
 44     int rear = -1, front = -1;
 45     if(root != NULL) {
 46         Queue[++rear] = root;
 47     } 
 48     Node * p = NULL;
 49     while (rear != front) {
 50         p = Queue[front+1];
 51         if(p->ltag == Child) {            // 有左孩子就进队,没有就不管,判断有无孩子 是看它的标志
 52             Queue[++rear] = p->lchild;
 53         }
 54         if(p->rtag == Child) {            // 有右孩子入队
 55             Queue[++rear] = p->rchild;
 56         }
 57         cout << "析构:" << p->data << endl;
 58         delete p;                        // 删除队头所指向的那一块存储空间
 59         front++;                        // 出队一个 front+1
 60     }
 61     system("pause");
 62 }
 63 
 64 Node * Tree::Create() {
 65     Node * root;
 66     char ch;
 67     cin >> ch;
 68     if (ch == '#') {
 69         root = NULL;
 70     }
 71     else {
 72         root = new Node();
 73         root->data = ch;
 74         root->ltag = root->rtag = Child;        //  默认设置左右指针域 为孩子
 75         root->lchild = Create();
 76         root->rchild = Create();
 77     }
 78     return root;
 79 }
 80 
 81 Node * Tree::getRoot() {
 82     return root;
 83 }
 84 
 85 void Tree::_postTree(Node * root, Node *&pre) {
 86     if (root == NULL) {        // 空值不操作
 87         return;
 88     }
 89     else {
 90         _postTree(root->lchild, pre);    // 递归左树,首先是递归到左子树的最左下的结点
 91         _postTree(root->rchild, pre);    // 递归右树,首先是递归到左子树的最左下的第一个右结点
 92         // 对当前结点进行操作,只对含有空指针的结点指针域操作
 93         if (root->lchild == NULL) {        // 左孩子为空,操作的是前驱,前驱是 pre
 94             root->ltag = nChild;
 95             root->lchild = pre;
 96         }
 97         // 首先要判断 pre 是否为空,后才能判断他的指针域,因为第一次的 pre在未执行下面语句 pre = root 时是NULL 值, 指针为 NULL值的没有访问其他内存空间的权限
 98         if (pre != NULL && pre->rchild == NULL) {    // 右孩子为空,操作的是后继, pre是前驱的话,那么root不就是后继吗?
 99             pre->rtag = nChild;
100             pre->rchild = root;
101         }
102         pre = root;
103     }
104 }
105 
106 void Tree::Show_postTree(Node * root) {
107     cout << "后序线索化遍历(最大使用栈暂存元素个数 100):";
108     Node * Stack[100];
109     int top = -1;
110     Node * p = root;
111     Node * pre = NULL;            // 作为前驱,保留上一次访问过的指针域
112     do {
113         while (p != NULL) {        // 将当前结点的左孩子全部入栈,一直走到最左边的左孩子
114             Stack[++top] = p;
115             p = p->lchild;
116             if (p == pre) {        // 防止对叶子结点操作中, p = p->rchild 导致 p 不为 NULL, 在执行上面一条语句 p = p->lchild时再次访问了已访问过的结点
117                 break;
118             }
119         }
120         p = Stack[top];            // 将 p 指向栈顶指针域,进行操作当前结点
121         if (p->rtag == nChild || p->rchild == pre) {    // 当前结点没有右孩子 或者 它的右孩子已经被访问过
122             cout << p->data << " ";
123             top--;        // 输出一个结点,就出栈一个指针域
124             pre = p;
125             p = NULL;    // p 为 NULL,目的是为了使其不满足第一个while,防止再次访问已访问过的结点,转去操作下一个结点
126         }
127         else {
128             p = p->rchild;
129         }
130     } while (top != -1 && pre != NULL);
131     cout << endl;
132 }
较为完整的程序

 

posted @ 2016-11-24 18:01  enjoy_Lify  阅读(483)  评论(0编辑  收藏  举报