对于一个普通的二叉树

我们可以很明显的看到,在一个二叉树中,会有许多的空结点,而这些空结点必然会造成空间的浪费,为了解决这个问题,我们可以引入线索二叉树,把这些空结点利用起来,利用 ‘^’ 记录给定结点的前驱后继,那么问题就来了,该如何建立呢?

前面我们说过四种的遍厉方法,我应该用哪种方法来建立线索二叉树呢?

经过逐一的分析,我们发现利用中序遍历方法能够有效地建立起线索二叉树

我们先看一看在上述二叉树中中序遍历的结果

H D I B E A F C G

红色的结点为有空结点

在空结点中储存前驱与后继

单面对这样的一种二叉树时又怎么办呢?

中序遍历为

F D G B A C E

我们可以看到在b结点与结点 c出只有一个空结点

那机器该如何判断放的是线索还是指针呢?

为了解决这种问题,我们可以吧树的每个结点进行扩容

ltag : 为0时,表示lchild指向改结点的左孩子; 为1时,表示lchild指向该结点的前驱

rtag:为0时,表示rchild指向该结点的右孩子;为1时,表示rchild指向该结点的后继

线索二叉树的代码实现:

#include<iostream>
using namespace std; typedef char ElemType; //线索存储标志位
//Link 为0时,表示指向左右孩子的指针
//Thread 为1时,表示指向前驱后继的线索
typedef enum{Link, Thread} PointerTag; typedef struct BitThrNode
{
char data;
struct BitThrNode *lchild, *rchild;
PointerTag ltag;
PointerTag rtag;
}BitThrNode, *BitThrTree; //全局变量,指向刚刚访问过的节点
BitThrTree pre; //利用前序遍历创建二叉树
void createBitThrTree(BitThrTree *T) //根节点的地址
{
char c;
cin >> c;
if(c =='-')
{
*T=NULL;
}
else
{
*T=new BitThrNode;
(*T)->data=c;
(*T)->ltag=Link;
(*T)->rtag=Link;
createBitThrTree(&(*T)->lchild);
createBitThrTree(&(*T)->rchild);
}
} //中序遍历线索化
void InThreading(BitThrTree T)
{
if(T)
{
InThreading(T->lchild);//递归左孩子线索化
//结点处理
if(!T->lchild)
{
T->ltag=Thread;
T->lchild=pre;
} if(!pre->rchild)
{
pre->rtag=Thread;
pre->rchild=T;
} pre=T; InThreading(T->rchild);//递归右孩子线索化
}
} void InorderThreading(BitThrTree *p, BitThrTree T)
{
*p=new BitThrNode();
(*p)->ltag=Link;
(*p)->rtag=Thread;
(*p)->rchild=*p;
if(!T)
{
(*p)->lchild=*p;
}
else
{
(*p)->lchild=T;
pre=*p;
InThreading(T);
pre->rchild=*p;
pre->rtag=Thread;
(*p)->rchild=pre;
}
} void visit(char c)
{
cout<<c<<endl;
} //中序遍历二叉树非递归
void InorderTravel(BitThrTree T)
{
BitThrTree p;
p=T->lchild;
while(p!=T)
{
while(p->ltag==Link)
{
p=p->lchild;
}
visit(p->data); while(p->rtag==Thread&&p->rchild!=T)
{
p=p->rchild;
visit(p->data);
}
p=p->rchild;
}
} int main()
{
BitThrTree T=NULL;
BitThrTree p;
createBitThrTree(&T);
InorderThreading(&p,T); cout<<"中序遍历输出结果为"<<endl;
InorderTravel(p); return 0;
}

  

线索thread二叉树的更多相关文章

  1. 线索二叉树Threaded binary tree

    摘要   按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列.在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结点.这 ...

  2. 树和二叉树->线索二叉树

    文字描述 从二叉树的遍历可知,遍历二叉树的输出结果可看成一个线性队列,使得每个结点(除第一个和最后一个外)在这个线形队列中有且仅有一个前驱和一个后继.但是当采用二叉链表作为二叉树的存储结构时,只能得到 ...

  3. 线索二叉树的理解和实现(Java)

    线索二叉树的基本概念 我们按某种方式对二叉树进行遍历,将二叉树中所有节点排序为一个线性序列,在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结 ...

  4. javascript实现数据结构:线索二叉树

    遍历二叉树是按一定的规则将树中的结点排列成一个线性序列,即是对非线性结构的线性化操作.如何找到遍历过程中动态得到的每个结点的直接前驱和直接后继(第一个和最后一个除外)?如何保存这些信息? 设一棵二叉树 ...

  5. 算法与数据结构(三) 二叉树的遍历及其线索化(Swift版)

    前面两篇博客介绍了线性表的顺序存储与链式存储以及对应的操作,并且还聊了栈与队列的相关内容.本篇博客我们就继续聊数据结构的相关东西,并且所涉及的相关Demo依然使用面向对象语言Swift来表示.本篇博客 ...

  6. Data Structure 之 二叉树

          在计算机科学中,二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树”(right subtree).二叉树常被用于实现二叉查找树和二叉堆 ...

  7. Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)——无非是在传统遍历过程中修改叶子结点加入后继结点信息(传统是stack记录),然后再删除恢复

    先看看线索二叉树 n个结点的二叉链表中含有n+1(2n-(n-1)=n+1)个空指针域.利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索 ...

  8. 数据结构(C语言版)---二叉树

    1.二叉树:任意一个结点的子结点个数最多两个,且子结点的位置不可更改,二叉树的子树有左右之分. 1)分类:(1)一般二叉树(2)满二叉树:在不增加树的层数的前提下,无法再多添加一个结点的二叉树就是满二 ...

  9. C#数据结构-线索化二叉树

    为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...

随机推荐

  1. [SQL基础教程] 4-2 数据删除(DELETE)

    [SQL基础教程] C4 数据更新 4-2 数据删除(DELETE) DROP TABLE / DELETE DROP TABLE - 完全删除表 DELETE - 仅删除数据,保留表容器 DELET ...

  2. C# ObjectHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. 工具-maya2014软件操作细节(持续更新……)

    整体 ------------------------------------------------------- [全选控制器] 1.选中总控-显示-隔离选择-查看选定对象 2.全选并创建新层(不 ...

  4. USACO 3.2 Factorials

    Factorials The factorial of an integer N, written N!, is the product of all the integers from 1 thro ...

  5. mac相关

    1 mac的动态链接库 mac基于bsd,所以它使用的是bsd风格的动态链接库,即以.dylib为后缀的动态链接库. 这个和windows的.dll和linux的.so相区分.

  6. UITableView优化方案

    1.UITableView的简单认识 > UITableView最核心的思想就是UITableViewCell的重用机制.简单的理解就是:UITableView只会创建一屏幕(或一屏幕多一点)的 ...

  7. 图片上传插件用法,net语法【二】

    之前一直写过KindeEditor中的小控件作为单独上次,但业务要求需要另一种方式 现在改用ajaxfileupload.js试试,这个一百度 一.首页引用 <script src=" ...

  8. Java 并发 关键字volatile

    Java 并发 关键字volatile @author ixenos volatile只是保证了共享变量的可见性,不保证同步操作的原子性 同步块 和 volatile 关键字机制 synchroniz ...

  9. Zeppelin0.5.6使用hive解释器

    此zeppelin为官方0.5.6版,可能还在孵化阶段,可能出现一些bug吧. 配置 cp zeppelin-env.sh.template zeppelin-env.sh vi zeppelin-e ...

  10. IBM Minus One

    IBM Minus One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...