中序线索化二叉树

  中序线索化二叉树

 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

中序线索化二叉树的相关文章

中序线索化二叉树[C语言实现及注释]

根据我自己的理解给代码加了注释. /* 中序线索二叉树 2014/11/14 */ #include<stdio.h> #include<stdlib.h> typedef struct BiTrNoDe{ char data; struct BiTrNoDe *lchild; struct BiTrNoDe *rchild; unsigned ltag : 1; //LINK是1 此处也可以用枚举类型或者宏定义去写 unsigned rtag : 1; //threading是0

C++中序线索化二叉树

1 #include <iostream> 2 using namespace std; 3 4 typedef struct TBTNode 5 { 6 char data; 7 int ltag,rtag; 8 struct TBTNode * lchild; 9 struct TBTNode * rchild; 10 }TBTNode; 11 12 TBTNode * initTBTNode() 13 { 14 TBTNode * p=(TBTNode*)malloc(sizeof(TB

先序线索化二叉树

先序线索化在很多书上都有详细解读,这里只是写了一个较为完整的一个程序罢了 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 T

数据结构例程——线索化二叉树(中序)

本文是数据结构基础系列(6):树和二叉树中第14课时线索二叉树的例程. #include <stdio.h> #include <malloc.h> #define MaxSize 100 typedef char ElemType; typedef struct node { ElemType data; int ltag,rtag; //增加的线索标记 struct node *lchild; struct node *rchild; } TBTNode; void Creat

【数据结构】线索化二叉树中序线索化的递归写法和非递归写法

二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历.用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继. 为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息.所以引入了线索化二叉树.下面我们讲一下线索化二叉树中序线索化的两种实现方法: (1).递归实现中序线索化二叉树 首先我们先看一下线索化二叉树的结构 enum PointerTag{ THREAD, LINK 

数据结构与算法---线索化二叉树(Threaded BinaryTree)

先看一个问题 将数列 {1, 3, 6, 8, 10, 14  } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8, 10, 14 这几个节点的 左右指针,并没有完全的利用上. 如果我们希望充分的利用 各个节点的左右指针, 让各个节点可以指向自己的前后节点,怎么办? 解决方案-线索二叉树 线索二叉树基本介绍 1.n个结点的二叉链表中含有n+1  [公式 2n-(n-1)=n+1] 个空指针域.利用二叉链表中的空

JAVA递归实现线索化二叉树

JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节点 (只要记住根节点在哪里就是什么遍历,且都是先左再右) 线索化 现在有这么一棵二叉树,它的数据结构由左节点+权+右节点构成. 可以看到4,5,6,7这几个节点的左右节点空间被浪费了.因此,线索化是指有效利用这些空间. 中序遍历的顺序为:4 2 5 1 6 3 7 现在引入前驱节点以及后继节点. 前

java实现线索化二叉树的前序、中序、后续的遍历(完整代码)

java实现线索化二叉树的前序.中序.后续的遍历 比如创建一个二叉树 1 / 3 6 / \ / 8 10 14 线索化二叉树几个概念: n个节点的二叉链表中含有n+1 [公式2n-(n-1)=n+1]个空指针域.利用二叉链表中的空指针域,存放指向该节点在某种遍历次序下的前驱和后继节点的指针(这种附加指针成为线索).如下面的就是6+1=7个空指针域 (8,10,14各有连个指针没有指向 6有一个) 加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树.分为前序线索二叉树.中序线索二叉树.

线索化二叉树的构建与先序,中序遍历(C++版)

贴出学习C++数据结构线索化二叉树的过程, 方便和我一样的新手进行测试和学习 同时欢迎各位大神纠正. 不同与普通二叉树的地方会用背景色填充 //BinTreeNode_Thr.h 1 enum PointTag 2 {Link,Thread}; 3 4 template<typename ElemType> 5 struct BinTreeNode 6 { 7 ElemType data; //数据元素 8 PointTag LTag,RTag; //左标志,右标志 9 BinTreeNode