当前位置:首页>正文

中序线索二叉树的叶子节点的前驱结点为啥是根节点 二叉树相关知识

2023-04-19 06:14:27 互联网 未知

中序线索二叉树的叶子节点的前驱结点为啥是根节点

先把二叉树给标记化(把二叉树遍历一遍):既设置两个标记Ltag,Rtag,如果左孩子指针为空,Ltag=1,如果右孩子指针为空,Rtag=1。
建一个队列,根据你的遍历方式进行入队,
比如先序遍历,就把visit到的元素依次入队,特别注意,中序遍历或后序遍历visit是从左下角开始的,不是根节点,如果还是不懂,就把输出元素那行改成入队的代码就ok了
然后如果Ltag=1,此时把左孩子指针回指队里前一个元素,这个元素就是前驱节点,然后往队尾依次进行线索化,同理,后继的话为Rtag=1时,你也应该知道怎么弄了吧。
如果lz觉得回答还不错的话,注意给分哦

刚才少说了一个,队里的第一个元素的的标记Ltag=0,因为没有前驱

二叉树相关知识

二叉树 (binary tree) 是另一种树型结构,它的特点是每个结点至多只有二棵子 树 (即二叉树中不存在度大于 2的结点 ),并且,二叉树的子树有左右之分,其次序不能任意颠倒 . 二叉树是一种数据结构 :

Binary_tree=(D,R)

其中: D是具有相同特性的数据元素的集合 若 D等于空 ,则 R等于空称为空的二叉树 若 D等于空则 R是 D上某个二元关系 H的集合,即 R={H},且
(1) D 中存在唯一的称为根的元素 r,它的关系 H下无前驱
(2) 若 D-{r}不等于空,则 D-{r}={Dl,Dr},且 Dl交 Dr等于空
(3) 若 Dl不等于空 ,则在 Dl中存在唯一的元素 xl,〈 r,xl〉属于 H,且存在 Dl上的关系 Hl属于 H; 若 Dr不等于空 ,则在 Dr中存在唯一的元素 xr,〈 r,xr〉 >属于 H, 且存 Dr上的关 系 Hr属于 H; H={r,xl,< r,xr> ,Hl, Hr}
(4) (Dl, Hl) 是一棵合本定义的二叉树,称为根 r的左子树 ,(Dr,Hr)是一棵符合定义的二叉树,称为根的右子树。

其中,图 6.2 是各种形态的二叉树 .

(1) 为空二叉树 (2)只有一个根结点的二叉树 (3)右子树为空的二叉树 (4)左子树为空的二叉树 (5)完全二叉树

二叉树的基本操作:

(1)INITIATE(BT ) 初始化操作。置 BT为空树。

(2)ROOT(BT)ROOT(x) 求根函数。求二叉树 BT的根结点或求结点 x所在二叉树的根结点。
若 BT是空树或 x不在任何二叉树上,则函数值为 “空 ”。

(3)PARENT(BT,x) 求双亲函数。求二叉树 BT中结点 x的双亲结点。若结点 x是二叉树 BT 的根结点
或二叉树 BT中无 x结点,则函数值为 “空 ”。

(4)LCHILD(BT,x) 和 RCHILD(BT,x) 求孩子结点函数。分别求二叉树 BT中结点 x的左孩 子和右孩子结点。
若结点 x为叶子结点或不在二叉树 BT中,则函数值为 “空 ”。

(5)LSIBLING(BT,x) 和 RSIBING(BT,x) 求兄弟函数。分别求二叉树 BT中结点 x的左兄弟和右兄弟结点。
若结点 x是根结点或不在 BT中或是其双亲的左 /右子树根 ,则函树值 为 “空 ”。

(6)CRT_BT(x,LBT,RBT) 建树操作。生成一棵以结点 x为根,二叉树 LBT和 RBT分别为左, 右子树的二叉树。

(7)INS_LCHILD(BT,y,x) 和 INS_RCHILD(BT,x) 插入子树操作。将以结点 x为根且右子树为空的二叉树
分别置为二叉树 BT中结点 y的左子树和右子树。若结点 y有左子树 /右子树,则插入后是结点 x的右子树。

(8)DEL_LCHILD(BT,x) 和 DEL-RCHILD(BT,x) 删除子树操作。分别删除二叉树 BT中以结点 x为根的左子树或右子树。
若 x无左子树或右子树,则空操作。

(9)TRAVERSE(BT) 遍历操作。按某个次序依此访问二叉树中各个结点,并使每个结点只被访问一次。

(10)CLEAR(BT) 清除结构操作。将二叉树 BT置为空树。

5.2.2 二叉树的存储结构

一 、顺序存储结构
连续的存储单元存储二叉树的数据元素。例如图 6.4(b)的完全二叉树 , 可以向量 (一维数组 ) bt(1:6)作它的存储结构,将二叉树中编号为 i的结点的数据元素存放在分量 bt[i]中 ,如图 6.6(a) 所示。但这种顺序存储结构仅适合于完全二叉树 ,而一般二叉树也按这种形式来存储 ,这将造成存 贮浪费。如和图 6.4(c)的二叉树相应的存储结构图 6.6(b)所示,图中以 “0”表示不存在此结点 .

二、 链式存储结构
由二叉树的定义得知二叉树的结点由一个数据元素和分别指向左右子树的两个分支构成 ,则表 示二叉树的链表中的结点至少包含三个域 :数据域和左右指针域 ,如图 (b)所示。有时 ,为了便于找 到结点的双亲 ,则还可在结点结构中增加一个指向其双亲受的指针域,如图 6.7(c)所示。

5.3 遍历二叉树

遍历二叉树 (traversing binary tree)的问题, 即如何按某条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。 其中常见的有三种情况:分别称之为先 (根 )序遍历,中 (根 )序遍历和后 (根 )序遍历。

5.3.1 前序遍历

前序遍历运算:即先访问根结点,再前序遍历左子树,最后再前序遍历右子树。前序遍历运算访问二叉树各结点是以根、左、右的顺序进行访问的。例如:

按前序遍历此二叉树的结果为: Hello!How are you?

proc preorder(bt:bitreprtr)
if (bt<>null)[
print(bt^)
preorder(bt^.lchild)
preorder(bt^.rchild)]
end

5.3.2 中序遍历

中序遍历运算:即先中前序遍历左子树,然后再访问根结点,最后再中序遍历右子树。中序遍历运算访问二叉树各结点是以左、根、右的顺序进行访问的。例如:

按中序遍历此二叉树的结果为: a*b-c

proc inorder(bt:bitreprtr)
if (bt<>null)[
inorder(bt^.lchild)
print(bt^)
niorder(bt^.rchild)]
end

5.3.3 后序遍历

后序遍历运算:即先后序遍历左子树,然后再后序遍历右子树,最后访问根结点。后序遍历运算访问二叉树各结点是以左、右、根的顺序进行访问的。例如:

按后序遍历此二叉树的结果为: Welecome to use it!

proc postorder(bt:bitreprtr)
if (bt<>null)[
postorder(bt^.lchild)
postorder(bt^.rchild)]
print(bt^)
end

五、例:
1.用顺序存储方式建立一棵有31个结点的满二叉树,并对其进行先序遍历。
2.用链表存储方式建立一棵如图三、4所示的二叉树,并对其进行先序遍历。
3.给出一组数据:R={10.18,3,8,12,2,7,3},试编程序,先构造一棵二叉树,然后以中序遍历访问所得到的二叉树,并输出遍历结果。
4.给出八枚金币a,b,c,d,e,f,g,h,编程以称最少的次数,判定它们蹭是否有假币,如果有,请找出这枚假币,并判定这枚假币是重了还是轻了。

两个二叉树遍历选择题

3.分块查找流程如下:
step1 先选取各块中的最大关键字构成一个索引表;
step2 查找分两个部分:
①先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;
②然后,在已确定的块中用顺序法进行查找。
适应动态变化就是说:如果你在这个集合中插入元素的话可以先找到刚好大于新元素的关键字所在的块,比如有如下块:
10,20,30,40
如果插入14的话就把14插入到关键字为20的块中,因为关键字是有序的,所以仍然可以用折半查找,而在块内使用顺序查找由于块的跨度不大所以开销也不大。
4.二叉排序树的定义:(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树;
对于叶子节点来说是否大于前驱小于后继不需要去判断,因为如果它不大于前驱A说明它的前驱A不小于它(A的后继),如果不小于后继B说明后继不大于它(B的后继)。而且不会有两个叶子互为前驱后继。

写出中序线索二叉树中找指定节点在后序下的前驱结点的算法

.[题目分析]在后序序列中,若结点p有右子女,则右子女是其前驱,若无右子女而有左子女,则左子女是其前驱。若结点p左右子女均无,设其中序左线索指向某祖先结点f(p是f右子树中按中序遍历的第一个结点),若f有左子女,则其左子女是结点p在后序下的前驱;若f无左子女,则顺其前驱找双亲的双亲,一直继续到双亲有左子女(这时左子女是p的前驱)。还有一种情况,若p是中序遍历的第一个结点,结点p在中序和后序下均无前驱。
BiThrTree InPostPre (BiThrTree t,p)
//在中序线索二叉树t中,求指定结点p在后序下的前驱结点q
{BiThrTree q
if (p->rtag==0) q=p->rchild //若p有右子女,则右子女是其后序前驱
else if (p->ltag==0) q=p->lchild //若p无右子女而有左子女,左子女是其后序前驱。
else if(p->lchild==null) q=null//p是中序序列第一结点,无后序前驱
else //顺左线索向上找p的祖先,若存在,再找祖先的左子女
{while(p->ltag==1 && p->lchild!=null) p=p->lchild
if(p->ltag==0) q=p->lchild //p结点的祖先的左子女是其后序前驱
else q=null //仅右单枝树(p是叶子),已上到根结点,p结点无后序前驱
}
return(q) }//结束InPostPre