×

线索二叉树是一种逻辑结构

线索二叉树是一种逻辑结构(线索二叉树是逻辑结构还是物理结构呢,帮忙解释一下)

admin admin 发表于2023-06-07 13:37:00 浏览32 评论0

抢沙发发表评论

本文目录

线索二叉树是逻辑结构还是物理结构呢,帮忙解释一下


线索二叉树是一种逻辑结构,是在二叉树的基础上做出的改进,方便查找
这么说吧,对于具有n个节点的二叉树,采用二叉链存储结构时,每个节点有2个指针域,总共有2n个指针域,但是使用的只有(n-1)个,有(n+1)个被浪费掉了。线索二叉树就是利用这些空链域存放节点的直接前驱和直接后继节点的指针,这样指向该线性序列中的“直接前驱”和“直接后继”的指针称作线索

线索二叉树的概念


这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。
注意:
线索链表解决了无法直接找到该结点在某种遍历序列中的前趋和后继结点的问题,出现了二叉链表找左、右孩子困难的问题。


线索二叉树是一种什么结构


存储结构。

在我们规定中,二叉树已经被认为是一种逻辑结构,它隶属于非线性逻辑结构,同属于非线性结构的还有图、集合等,但是在线索二叉树中,多了“线索”这么一个概念,而在我们的规定中,“线索”并不属于逻辑结构中的任何一种类型或任何一种类型的某部分。

所以只有我们在使用确定的计算机编程语言时通过借助语言的特性才能去将它表示出来(如c语言中的指针)。

综上,我们可以得出结论:线索二叉树属于存储结构(物理结构)。

概念

对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树。

这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。

注意:线索链表解决了无法直接找到该结点在某种遍历序列中的前驱和后继结点的问题,解决了二叉链表找左、右孩子困难的问题。


什么是二叉树


二叉树

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

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。

一棵深度为k,且有2^k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。具有n个节点的完全二叉树的深度为log2n+1。深度为k的完全二叉树,至少有2^(k-1)个节点,至多有2^k-1个节点。

一、定义

二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。

二、基本概念

二叉树是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:

(1)空二叉树——如图(a);

(2)只有一个根结点的二叉树——如图(b);

(3)只有左子树——如图(c);

(4)只有右子树——如图(d);

(5)完全二叉树——如图(e)。

注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。

三、相关术语

树的结点:包含一个数据元素及若干指向子树的分支;

孩子结点:结点的子树的根称为该结点的孩子;

双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;

兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;

祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙

结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;

树的深度:树中最大的结点层

结点的度:结点子树的个数

树的度: 树中最大的结点度。

叶子结点:也叫终端结点,是度为 0 的结点;

分枝结点:度不为0的结点;

有序树:子树有序的树,如:家族树;

无序树:不考虑子树的顺序; 

四、二叉树性质

(1) 在非空二叉树中,第i层的结点总数不超过 , i》=1;

(2) 深度为h的二叉树最多有 个结点(h》=1),最少有h个结点;

(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;

(4) 具有n个结点的完全二叉树的深度为

(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

若I为结点编号则 如果I》1,则其父结点的编号为I/2;

如果2*I《=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I》N,则无左儿子;

如果2*I+1《=N,则其右儿子的结点编号为2*I+1;若2*I+1》N,则无右儿子。

(6)给定N个节点,能构成h(N)种不同的二叉树。

h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。

(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i 

五、存储结构

(1)顺序存储方式

1  typenode=record

2  data:datatype

3  l,r:integer;

4  end;

5  vartr:array[1..n]ofnode;

(2)链表存储方式,如:

1  typebtree=^node;

2  node=record

3  data:datatye;

4  lchild,rchild:btree;

5  end;

六、辨析

二叉树不是树的一种特殊情形,尽管其与树有许多相似之处,但树和二叉树有两个主要差别:

1. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2;

2. 树的结点无左、右之分,而二叉树的结点有左、右之分。

七、遍历顺序

遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。

设L、D、R分别表示遍历左子树、访问根结点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先根次序遍历),LDR(称为中根次序遍历),LRD (称为后根次序遍历)。

先序遍历

首先访问根,再先序遍历左(右)子树,最后先序遍历右(左)子树,C语言代码如下:

1  voidXXBL(tree*root){

2  //DoSomethingwithroot

3  if(root-》lchild!=NULL)

4  XXBL(root-》lchild);

5  if(root-》rchild!=NULL)

6  XXBL(root-》rchild);

7  }

中序遍历

首先中序遍历左(右)子树,再访问根,最后中序遍历右(左)子树,C语言代码如下

1  voidZXBL(tree*root)

2  {

3  if(root-》lchild!=NULL)

4  ZXBL(root-》lchild);//DoSomethingwithroot

5  if(root-》rchild!=NULL)

6  ZXBL(root-》rchild);

7  }

后序遍历

首先后序遍历左(右)子树,再后序遍历右(左)子树,最后访问根,C语言代码如下

1  voidHXBL(tree*root){

2  if(root-》lchild!=NULL)

3  HXBL(root-》lchild);

4  if(root-》rchild!=NULL)

5  HXBL(root-》rchild);//DoSomethingwithroot

6  }

层次遍历

即按照层次访问,通常用队列来做。访问根,访问子女,再访问子女的子女(越往后的层次越低)(两个子女的级别相同)

线索二叉树

线索二叉树(保留遍历时结点在任一序列的前驱和后继的信息):若结点有左子树,则其lchild域指示其左孩子,否则令lchild域指示其前驱;若结点有右子树,则其rchild域指示其右孩子,否则令rchild指示其后继。还需在结点结构中增加两个标志域LTag和RTag。LTag=0时,lchild域指示结点的左孩子,LTag=1时,lchild域指示结点的前驱;RTag=0时,rchild域指示结点的右孩子,RTag=1时,rchild域指示结点的后继。以这种结点结构构成的二叉线索链表,链表作为二叉树的存储结构,叫做其中指向结点前驱和后继的指针叫做线索,加上线索的二叉树称为线索二叉树。对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化。若对二叉树进行中序遍历,则所得的线索二叉树称为中序线索二叉树,线索链表称为为中序线索链表。线索二叉树是一种物理结构。

线索二叉树的存储结构

在中序线索树找结点后继的规律是:若其右标志为1,则右链为线索,指示其后继,否则遍历其右子树时访问的第一个结点(右子树最左下的结点)为其后继;找结点前驱的规律是:若其左标志为1,则左链为线索,指示其前驱,否则遍历左子树时最后访问的一个结点(左子树中最右下的结点)为其前驱。

在后序线索树中找到结点的后继分三种情况:

若结点是二叉树的根,则其后继为空;若结点是其双亲的右孩子,或是其双亲的左孩子且其双亲没有右子树,则其后继即为双亲结点;若结点是其双亲的左孩子,且其双亲有右子树,则其后继为双亲右子树上按后序遍历列出的第一个结点。

数据结构定义为:

/*二叉线索存储表示*/typedefenum{Link,Thread}PointerTag;/* Link(0):指针,Thread(1):线索*/typedefstruct BiThrNode{ TElemType data;struct BiThrNode *lchild,*rchild;/*左右孩子指针*/PointerTag LTag,RTag;/* 左右标志 */}BiThrNode,*BiThrTree;

八、实现演示

范例二叉树:

A

B C

D E

此树的顺序结构为:ABCD##E

int main()
{    

node*p=newnode;    

node*p=head;    

head=p;    

stringstr;   

cin 》》str;   

creat(p,str,0)//默认根节点在str下标0的位置    

return 0;

}

//p为树的根节点(已开辟动态内存),str为二叉树的顺序存储数组ABCD##E或其他顺序存储数组,r当前结点所在顺序存储数组位置.

int main()

{    

node* p = newnode;   

node* p = head;    

head = p;   

string str;    

cin 》》 str;   

creat(p, str, 0)//默认根节点在str下标0的位置    

return 0;

}

//p为树的根节点(已开辟动态内存),str为二叉树的顺序存储数组ABCD##E或其他顺序存储数组,r当前结点所在顺序存储数组位置。

void creat(node* p, string str, int r)

{    

p-》data = str[r];

if (str[r * 2 + 1] == ’#’ || r * 2 + 1 》 str.size() - 1)p-》lch = NULL;

else

{       

p-》lch = newnode;       

creat(p-》lch, str, r * 2 + 1);

}    

if (str[r * 2 + 2] == ’#’ || r * 2 + 2 》 str.size() - 1)p-》rch = NULL;    

else    

{       

p-》rch = newnode;        

creat(p-》rch, str, r * 2 + 2);   

}

}