中序线索化二叉树
1 void Tree::_inTree(Node * root, Node * &pre) { 2 if (root == NULL) { // 结点为空, 1:二叉树为空 2:已到达右子树的最后一个右结点的 rchild 3 return; 4 } 5 _inTree(root->lchild, pre); // 到达当前结点的左子树的底部左结点 6 if (root->lchild == NULL) { 7 root->ltag = nChild; // 当前结点 无左孩子, 设置标记为 nChild 8 root->lchild = pre; // 设置 lchild 的指针域 为前驱 pre 9 } // 注意下列的条件判断, 要先判断pre是不是空,再是 pre的其他指针域! 10 if (pre != NULL && pre->rchild == NULL) { // pre 为上一次访问过的结点, root为当前结点,通过对 pre的操作,达到线索化,pre位于左子树是作为前驱,位于右子树作为后继 11 pre->rtag = nChild; 12 pre->rchild = root; 13 } 14 pre = root; // 把 pre 指向当前结点,保存上一次访问的结点 15 _inTree(root->rchild, pre); 16 }
较为完整可运行程序
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 Node * _next(Node *); // 返回待查找结点的后继 19 void Show_inTree(Node *); // 中序遍历输出 20 private: 21 Node * root; 22 Node * Create(); // 供构造函数调用初始化二叉树 23 void Delete(Node *); // 供析构函数析构二叉树 24 void _inTree(Node *, Node *&); // 中序 线索化 25 }; 26 27 int main() { 28 cout << "以先序方式输入二叉树:"; 29 30 Tree T; 31 T.Show_inTree(T.getRoot()); 32 33 system("pause"); 34 return 0; 35 } 36 37 Tree::Tree() { 38 root = Create(); // 先创建一个默认的二叉树 39 Node * pre = NULL; 40 _inTree(root, pre); // 再对二叉树进行线索化 41 } 42 43 Tree::~Tree() { 44 while (root->lchild != NULL) { // 将root,设置为左子树的最左下角的结点 45 root = root->lchild; 46 } 47 Delete(root); 48 } 49 50 void Tree::Delete(Node * root) { 51 if (root->rchild != NULL) { // 右指针域 是一直指向下一个结点,直到指向为右子树最右下角的最后结点 52 Delete(root->rchild); 53 delete root; 54 } 55 } 56 57 Node * Tree::Create() { 58 Node * root; 59 char ch; 60 cin >> ch; 61 if (ch == ‘#‘) { 62 root = NULL; 63 } else { 64 root = new Node(); 65 root->data = ch; 66 root->ltag = root->rtag = Child; // 默认设置左右指针域 为孩子 67 root->lchild = Create(); 68 root->rchild = Create(); 69 } 70 return root; 71 } 72 73 void Tree::_inTree(Node * root, Node * &pre) { 74 if (root == NULL) { // 结点为空, 1:二叉树为空 2:已到达右子树的最后一个右结点的 rchild 75 return; 76 } 77 _inTree(root->lchild, pre); // 到达当前结点的左子树的底部左结点 78 if (root->lchild == NULL) { 79 root->ltag = nChild; // 当前结点 无左孩子, 设置标记为 nChild 80 root->lchild = pre; // 设置 lchild 的指针域 为前驱 pre 81 } // 注意下列的条件判断, 要先判断pre是不是空,再是 pre的其他指针域! 82 if (pre != NULL && pre->rchild == NULL) { // pre 为上一次访问过的结点, root为当前结点,通过对 pre的操作,达到线索化,pre位于左子树是作为前驱,位于右子树作为后继 83 pre->rtag = nChild; 84 pre->rchild = root; 85 } 86 pre = root; // 把 pre 指向当前结点,保存上一次访问的结点 87 _inTree(root->rchild, pre); 88 } 89 90 Node * Tree::getRoot() { 91 return root; 92 } 93 94 void Tree::Show_inTree(Node * root) { 95 if (root == NULL) { 96 return; 97 } 98 Node * p = root; 99 while (p->ltag == Child) { // 索引到左子树没有孩子,即中序遍历中的第一个结点 100 p = p->lchild; 101 } 102 cout << p->data << " "; // 输出第一个结点 103 while (p->rchild != NULL) { // 通过线索化,右孩子为空的时候表示 整个二叉树访问完毕 104 p = _next(p); // 获取当前结点的后继,即下一个元素, 注:_next 函数返回的是下一个结点的地址,故此不需要 p = p->rchild; 105 cout << p->data << " "; 106 } 107 cout << endl; 108 } 109 110 Node * Tree::_next(Node * root) { 111 Node * p = NULL; 112 if (root->rtag == nChild) { // 右标志为 nChild,无右孩子,直接线索化得到 113 p = root->rchild; 114 } else { // 否则是,右孩子的左子树的最左下结点 115 p = root->rchild; 116 while (p->ltag == Child) { 117 p = p->lchild; 118 } 119 } 120 return p; 121 }
时间: 2024-10-20 17:44:08