线索二叉树的深度理解

不知道你是否和我当时一样,对于线索二叉树,有点云里雾里的感觉,现在我们来一起探讨下吧。

首先,我们所应该知道的是:线索二叉树是对二叉链表中空指针的充分利用,也就是说,使得原本是空指针的转化成在某种遍历的顺序下,指向该结点的前驱和后继。也许听的有点糊涂,没关系,请接着往下看。

在二叉链表中,每个结点都带有*leftChild和*rightChild,两个指针,而除根结点外,每个结点只被一个指针所对应,要么是leftChild,要么是rightChild.而总共有2*n个指针,也就是说,有2*n-(n-1)个空指针,从这个角度,也说明了线索二叉树的必要性。

线索二叉树在二叉链表的基础上增加了两个成员数据:leftTag,rightTag;用来标记当前结点的leftChild,rightChild指针指向的是孩子,还是线索。leftTag=rightTag=1,表示线索,leftTag=rightTag=0;表示孩子;

下面给出中序遍历顺序下的线索二叉树的构造函数,*p为根;

template <class ElemType>

void InThreadBinTree<ElemType>::InThreadHelp(ThreadBinTreeNode<ElemType> *p,ThreadBinTreeNode<ElemType> *pre)

{

if(p!=NULL)

{

InThreadHelp(p->leftChild,pre);

if(p->leftChild==NULL)

{

p->leftChild=pre;

p->leftTag=1;

}

else

p->leftTag=0;

if(pre!=NULL&&pre->rightChild==NULL)

{

pre->rightChild=p;

pre->rightTag=1;

}

else if(pre!=NULL)

{

pre->rightTag=0;

}

pre=p;

InThreadHelp(p->rightChild,pre);

}

}

该段程序可被分为3部分,1.左孩子的线索化,2.p的线索化,3.p右孩子的线索化。

在中序遍历的前提下,判断p是否有空指针,然而,再遍历右子树之前,如果p->rightChild=NULL是无法确定p的后继的,因此,此时,只能判断p->leftChild是否为空,若为空,则leftChild=pre;此时,判断pre->rightChild是否为空,如为空,pre->rightChild=p;

p=pre;你也许注意到了,此时pre->rightChild,也就是先前p->rightChild,此时可以判断了,并且后继就是现在的p;此时所有空指针的线索化已经完成。当然,第一个结点的leftchild,和最后一个结点的rightchild是空指针,因为他们不需要线索化。

那么问题又来了,做了这么多,线索二叉树有什么用,或者说要怎么用。

以下是个人理解;

通过构造线索二叉树,我们可以很容易确定树中任何一个结点在某种遍历顺序下的前驱或者后继。不妨以中序遍历为例;

树中必然存在这样两种结点:被线索化了的,以及没有被线索化的

被线索化的,leftTag==1,leftchild即为前驱,rightTag==1,rightChild即为后继;

若leftTag==0,则该结点的前驱通过leftchild为根的树的rightchild循环,直到rightTag==1,即为其前驱,

若rightTag==0,则通过rightchild为根的leftchild循环,直到leftTag==1,即为其后继。

也就是说,任何结点按中序遍历的顺序的前驱和后继都能找到。这就是线索二叉树的作用,方便确定某种遍历的顺序。

时间: 2024-10-25 05:28:30

线索二叉树的深度理解的相关文章

彻底理解线索二叉树

一.线索二叉树的原理 通过考察各种二叉链表,不管儿叉树的形态如何,空链域的个数总是多过非空链域的个数.准确的说,n各结点的二叉链表共有2n个链域,非空链域为n-1个,但其中的空链域却有n+1个.如下图所示. 因此,提出了一种方法,利用原来的空链域存放指针,指向树中其他结点.这种指针称为线索. 记ptr指向二叉链表中的一个结点,以下是建立线索的规则: (1)如果ptr->lchild为空,则存放指向中序遍历序列中该结点的前驱结点.这个结点称为ptr的中序前驱: (2)如果ptr->rchild为

求二叉树的深度和宽度 ----我对默认构造函数的理解

////计算二叉树的深度和宽度:深度:层数   宽度:各层最大节点数 ///关于二叉树问题,一般都要用到递归的方法. ////算法:首先构造二叉树节点的结构:要创建二叉树,创建的过程,使用递归算法:其次,计算二叉树深度,也要递归:最难的一点是计算求出层次中的最大节点数,使用队列的方法 #include <iostream>#include <queue>#include <tchar.h>using namespace std;struct BTNode{ char m

对于linux下system()函数的深度理解(整理)

对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54) 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定?

二叉树各种相关操作(建立二叉树、前序、中序、后序、求二叉树的深度、查找二叉树节点,层次遍历二叉树等)(C语言版)

将二叉树相关的操作集中在一个实例里,有助于理解有关二叉树的相关操作: 1.定义树的结构体: 1 typedef struct TreeNode{ 2 int data; 3 struct TreeNode *left; 4 struct TreeNode *right; 5 }TreeNode; 2.创建根节点: 1 TreeNode *creatRoot(){ 2 TreeNode * root =(TreeNode *)malloc(sizeof(TreeNode)); 3 if(NULL=

数据结构之---C语言实现线索二叉树

//线索二叉树,这里在二叉树的基础上增加了线索化 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef char ElemType; typedef enum {Link,Thread} childTag; //Link表示结点.Thread表示线索 typedef struct bitNode { ElemType data; struct bitNode *lchild, *rchild; int ltag, rtag; } b

一步一步写数据结构(线索二叉树)

线索二叉树,在原始二叉树的基础上对节点进行“扩容”,使之变成了一颗节点信息更加丰富,利用率更高的二叉树.具体来说增加了两个指示标签,ltag和rtag,每个标签有两个值,1和0,0代表存在孩子,指针指向相应孩子,1代表没有对应的孩子,指针表示线索,指向其前驱或后继.这样虽然节点多占用了空间(其实很少,只是两个枚举常量而已),换来的却是让原来结构中存在的大量空指针利用起来,变成线索,指示前驱后继,从而使得空间利用效率大大提高, 并且有了线索以后,对后续的查找等操作提高很多效率. 下面是代码,本来以

小堆 线索二叉树补充

1.小堆: 堆的构造,i>数组直接生成堆(向下调整),iii>插入创建堆(向上调整): (1).怎么实现一次调整? 找到最后一个非叶子结点,n/2-1:一直往下调整即可! (2)堆排----->优先级队列 堆的删除,只能是堆顶元素,再拿最后一个元素补充上去.在向下做一次调整.形成新的堆结构(满足堆的性质),将删除的数字输出就是堆排. 小堆:根(父)小于左右结点:最小的数字先出: 大堆:根(父)大于左右结点:最大的数字先出:   因而,进行堆排是就是优先级队列! 2.线索二叉树的查找父结点

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

求一个二叉树的深度

求一个二叉树的深度,是这样理解这个问题的. 如果这个棵树为空,那么他的深度为0 如果一个树只有一个节点,那么他的深度为1 如果根节点只有左子,没有右子,那么他的深度为左子树的深度+1 如果根节点只有右子,没有左子,那么他的深度为右子树的深度+1 如果根节点既有左子,又有右子,那么他的深度为左子右子较大的那个深度+1 struct BNode { int data;   //数据域 BNode* left;//左子 BNode* right;//右子} int TreeDepth(BNode* n