摘要

 

按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列。在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点;除最后一个结点外每一个结点有且仅有一个直接后继结点。这些指向直接前驱结点和指向直接后续结点的指针被称为线索(Thread),加了线索的二叉树称为线索二叉树

编辑本段概念

n个结点的二叉链表中含有n+1(2n-(n-1)=n+1)个空指针域。利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前趋和后继结点的指针(这种附加的指针称为"线索")。
这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。
注意:
线索链表解决了无法直接找到该结点在某种遍历序列中的前趋和后继结点的问题,出现了二叉链表找左、右孩子困难的问题。

编辑本段线索二叉树结构

二叉树的遍历本质上是将一个复杂的非线性结构转换为线性结构,使每个结点都有了唯一前驱和后继(第一个结点无前驱,最后一个结点无后继)。对于二叉树的一个结点,查找其左右子女是方便的,其前驱后继只有在遍历中得到。为了容易找到前驱和后继,有两种方法。一是在结点结构中增加向前和向后的指针fwd和bkd,这种方法增加了存储开销,不可取;二是利用二叉树的空链指针。现将二叉树的结点结构重新定义如下:
lchild
ltag
data
rtag
rchild
其中:ltag=0 时lchild指向左子女;
ltag=1 时lchild指向前驱;
rtag=0 时rchild指向右子女;
rtag=1 时rchild指向后继;

编辑本段构建

建立线索二叉树,或者说对二叉树线索化,实质上就是遍历一颗二叉树。在遍历过程中,访问结点的操作是检查当前的左,右指针域是否为空,将它们改为指向前驱结点或后续结点的线索。为实现这一过程,设指针pre始终指向刚刚访问的结点,即若指针p指向当前结点,则pre指向它的前驱,以便设线索。
另外,在对一颗二叉树加线索时,必须首先申请一个头结点,建立头结点与二叉树的根结点的指向关系,对二叉树线索化后,还需建立最后一个结点与头结点之间的线索。
下面是建立中序二叉树的递归算法,其中pre为全局变量。
BiThrNodeType *pre;
BiThrTree InOrderThr(BiThrTree T)
{ /*中序遍历二叉树T,并将其中序线索化,pre为全局变量*/
BiThrTree head;
head=(BitThrNodeType *)mallocsizeof(BiThrType));/*设申请头结点成功*/
head->ltag=0;head->rtag=1;/*建立头结点*/
head->rchild=head;/*右指针回指*/
if(!T)head->lchild=head;/*若二叉树为空,则左指针回指*/
else{head->lchild=T;pre=head;
InThreading(T);/*中序遍历进行中序线索化*/
pre->rchild=head;
pre->rtag=1;/*最后一个结点线索化*/
head->rchild=pre;
};
return head;
}
void InThreading(BiThrTree p)
{/*通过中序遍历进行中序线索化*/
if(p)
{InThreading(p->lchild);/*左子树线索化*/
if(p->lchild==NULL)/*前驱线索*/
{p->ltag=1;
p->lchild=pre;
}
else p->ltag=0;
if(p->rchild==NULL)p->rtag=1;/*后驱线索*/
else p->rtag = 0;
if(pre!=NULL && pre->rtag==1) pre->rchild=p;
pre=p;
InThreading(p->rchild);/*右子树线索化*/
}
}

编辑本段算法

进行中序线索化的算法

bithptr*pre; /* 全程变量*/
voidINTHREAD(bithptr *p)
{if(p!=NULL)
{ INTHREAD(p->lchild); /* 左子树线索化*/
if(p->lchild==NULL) {p->ltag=1;p->lchild=pre;}
if(p->rchild==NULL) p->rtag=1;
if(pre!=NULL && pre->rtag==1)pre->rchild=p;
pre=p; /* 前驱指向当前结点*/
INTHREAD(p->rchild); /* 右子树线索化*/
}

线索二叉树查找前驱和后继

(1)中序线索二叉树:若结点的ltag=1,lchild指向其前驱;否则,该结点的前驱是以该结点为根的左子树上按中序遍历的最后一个结点。若rtag=1,rchild指向其后继;否则,该结点的后驱是以该结点为根的右子树上按中序遍历的第一个结点。
求后继的算法如下:
bithptr *INORDERNEXT(bithptr *p)
{if (p->rtag==1)return(p->rchild);
else {q=p->rchild; /* 找右子树最先访问的结点*/
while (q->ltag==0) q=q->lchild;
return(q);
}
}
求前驱的算法如下:
bithptr *INORDERNEXT(bithptr *p)
{if (p->ltag==1)return(p->lchild);
else {q=p->lchild;/* 找左子树最后访问的结点*/
while (q->rtag==0) q=q->rchild;
return(q);
}
}
(2) 后序线索二叉树:
在后序线索二叉树中查找结点*p的前驱:若结点*p无左子树,则p->lchild指向其前驱;否则,若结点*p有左子树,当其右子树为空时,其左子树的根(即p->lrchild)为其后序前驱。当其右子树非空时,其右子树的根(即p->rchild)为其后序前驱。
在后序线索二叉树中查找结点*p的后继:若结点*p为根,则无后继;若结点*p为其双亲的右孩子,则其后继为其双亲;若结点*p为其双亲的左孩子,且双亲无右子女,则其后继为其双亲;若结点*p为其双亲的左孩子,且双亲有右子女,则结点*p的后继是其双亲的右子树中按后序遍历的第一个结点。所以,求后序线索二叉树中结点的后继要知道其双亲的信息,要使用栈,所以说后序线索二叉树是不完
(3)先序线索二叉树:
在先序线索二叉树中查找结点的后继较容易,而查找前驱要知道其双亲的信息,要使用栈,所以说先序线索二叉树也是不完善的。

线索二叉树Threaded binary tree的更多相关文章

  1. 遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  2. 数据结构《9》----Threaded Binary Tree 线索二叉树

    对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为  n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构. Definition: "A binary ...

  3. 笔试算法题(41):线索二叉树(Threaded Binary Tree)

    议题:线索二叉树(Threaded Binary Tree) 分析: 为除第一个节点外的每个节点添加一个指向其前驱节点的指针,为除最后一个节点外的每个节点添加一个指向其后续节点的指针,通过这些额外的指 ...

  4. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  5. 数据结构-二叉树(Binary Tree)

    1.二叉树(Binary Tree) 是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根节点和两棵互不相交的,分别称为根节点的左子树和右子树的二叉树组成.  2.特数二 ...

  6. [Swift]LeetCode105. 从前序与中序遍历序列构造二叉树 | Construct Binary Tree from Preorder and Inorder Traversal

    Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  7. [Swift]LeetCode106. 从中序与后序遍历序列构造二叉树 | Construct Binary Tree from Inorder and Postorder Traversal

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  8. [Swift]LeetCode226. 翻转二叉树 | Invert Binary Tree

    Invert a binary tree. Example: Input: 4 / \ 2 7 / \ / \ 1 3 6 9 Output: 4 / \ 7 2 / \ / \ 9 6 3 1 Tr ...

  9. [Swift]LeetCode654. 最大二叉树 | Maximum Binary Tree

    Given an integer array with no duplicates. A maximum tree building on this array is defined as follo ...

随机推荐

  1. 链接器工具错误 LNK2011

    问题描述: 使用visual studio 2015编译apr-iconv失败,提示"链接器工具错误 LNK2011:未链接预编译对象:映像可能不能运行"错误. 原因分析: MSD ...

  2. Redis rdb文件CRC64校验算法 Java实现

    查看RDB文件结构,发现最后的8字节是CRC64校验算得,从文件头开始直到8字节校验码前的FF结束码(含),经过CRC64校验计算发现,貌似最后的8字节是小端模式实现的. 参考redis的crc64实 ...

  3. ViewTreeObserver类概述

    ViewTreeObserver 版本:Android 3.0 r1 结构 继承关系 public final class ViewTreeObserver extends Object java.l ...

  4. [WCF]IIS部署到新系统

    最近为以前的一个企业部署软件的时候,接触到WCF,通过博客园大佬的系列文章和一些书籍,基本了解了一些.简单说也算是SOA一种方式,提供某种服务,可以理解为一个类库,供其他项目使用,可以做到业务分离.但 ...

  5. Smarty模板引擎技术二

    Smarty模板引擎技术 内建函数 include_php内建函数 作用:载入一个php文件,将载入的文件的内容赋值给一个变量   注意:该内建函数只能在2.0中使用,如果使用的话,必须得实例化Sma ...

  6. 《Web编程入门经典》

    在我还不知道网页的基础结构的时候,我找过很多本介绍Web基础的书籍,其中这本<Web编程入门经典>,我认为是最好的. 这本书内容很全面.逻辑很严谨.结构很清晰.语言文字浅显易懂. 看这本书 ...

  7. 我们一起学Windows Phone 8-01-开发环境搭建

    我们仅讨论Windows Phone 8的开发,不考虑兼容向下兼容.也不会提供任何盗版软件的下载.破解. 需要准备 知识:.NET相关开发经验,C#语言开发经验.如果有WPF或Silverlight开 ...

  8. 转载:邮箱正则表达式Comparing E-mail Address Validating Regular Expressions

    Comparing E-mail Address Validating Regular Expressions Updated: 2/3/2012 Summary This page compares ...

  9. MAF+WPF实现插件式应用程序框架

    关于maf和wpf大家感兴趣的话可以去百度学习一下,下面展示一下成果: 登录界面 主界面:默认的是我的应用,表示已经下载到本地的应用. 辅助应用类似appstore功能,指示未下载或者需要升级的程序列 ...

  10. DTcms 导航选中样式以及简化方法

    (建议使用方法2,执行效率略高) 一般用于导航不能循环输出的情况. 可以循环输出导航的情况直接用if判断即可. 首页模版中顶部,自定义c#代码. <%set string channel=&qu ...