数据结构学习笔记——线索二叉树

Posted 晚风(●•σ )

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构学习笔记——线索二叉树相关的知识,希望对你有一定的参考价值。

目录

一、线索二叉树的结点结构

在由n个结点组成的二叉链表中,含有n+1个空指针域,含有n-1个非空指针域。

如前面文章介绍的,含有n个结点的二叉树中,有n+1个空指针,对于叶子结点,它有两个空指针;对于度为1的结点(只有一个子结点),它只有一个空指针。将这些空指针利用起来,例如可以让其存放指向该结点的前驱或后驱,从而使遍历二叉树更加简便,即线索二叉树
如下图,由中序遍历序列(DBEAFCG)可以推出,其中结点D和结点G的中序前驱和中序后继为NULL:

  • 线索二叉树也分为前序线索二叉树、中序线索二叉树以及后序线索二叉树,即它们都是对二叉树中的所有结点的空指针进行某种遍历方式加线索,指向结点前驱和后继的指针称为线索,从而加快查找结点前驱和后继的效率。
线索二叉树 先序线索二叉树 中序线索二叉树 后序线索二叉树

线索二叉树的结点结构如下:

lchildltagdatartagrchild

其中ltag和rtag是标识域,用于区分线索指针和原本指向孩子结点的指针,不同标识域代表不同含义,我们规定如下:

ltag含义
0lchild指针,指向结点的左孩子
1lchild线索,指向结点的直接前驱
rtag含义
0rchild指针,指向结点的右孩子
1rchild线索,指向结点的直接前驱

如下图:

同理,先序线索二叉树和后序线索二叉树也是一样的,将原本的二叉树进行线索化。

二、线索二叉树的定义

线索二叉树的定义代码如下:

/*线索二叉树的定义*/
typedef struct CLTNode 
	char data;
	int ltag,rtag;			//标识域
	struct CLTNode *lchild,*rchild;
 CLTNode,*CLTree;

三、中序线索二叉树的遍历

指针p指向当前访问结点,以指针pre指向刚访问过的结点,例如对一个结点,检查p的左指针是否为空,若为空则将其指向指针pre,然后递归遍历右子树;检查pre的右指针是否为空,若为空则将其指向指针p,依次进行下去。

/*中序线索二叉树的遍历*/
void InTree2(CLTNode *p,CLTNode *&pre) 
	if(p!=NULL) 
		InTree2(p->lchild,pre);		//递归,左子树线索化 
		if(p->lchild==NULL) 		//若左子树为空
			p->lchild=pre;			//建立前驱线索,使pre指向p的直接前驱 
			p->ltag=1;				//将当前结点的ltag置为1,标识为线索,指向结点的直接前驱 
		
		if(pre!=NULL&&pre->rchild==NULL) 	//若左子树不为空,且右子树为空
			pre->rchild=p;			//建立后驱线索 ,使p指向pre的直接后驱 
			pre->rtag=1;			//将当前结点的rtag置为1,标识为线索,指向结点的直接后驱 
		
		pre=p;						//pre指向p 
		InTree2(p->rchild,pre);		//p指向下一个结点,递归,右子树线索化 
	

四、先序线索二叉树的遍历

先序线索二叉树的遍历代码在中序的代码基础上,将连接线索的代码放在左右子树递归线索化的前面。

/*先序线索二叉树的遍历*/
void ProTree2(CLTNode *p,CLTNode *&pre) 
	if(p!=NULL) 
		if(p->lchild==NULL) 		//若左子树为空
			p->lchild=pre;			//建立前驱线索,使pre指向p的直接前驱
			p->ltag=1;				//将当前结点的ltag置为1,标识为线索,指向结点的直接前驱
		
		if(pre!=NULL&&pre->rchild==NULL) 	//若左子树不为空,且右子树为空
			pre->rchild=p;			//建立后驱线索 ,使p指向pre的直接后驱
			pre->rtag=1;			//将当前结点的rtag置为1,标识为线索,指向结点的直接后驱
		
		pre=p;						//pre指向p
		if(p->ltag==0)
			ProTree2(p->lchild,pre);		//递归,左子树线索化
		if(p->rtag==0)
			ProTree2(p->rchild,pre);		//递归,右子树线索化
	

五、后序线索二叉树的遍历

而后序线索二叉树的遍历代码也在中序的代码基础上,将连接线索的代码放在左右子树递归线索化的后面。

/*后序线索二叉树的遍历*/
void PostTree2(CLTNode *p,CLTNode *&pre) 
	if(p!=NULL) 
		PostTree(p->lchild,pre);		//递归,左子树线索化 
		PostTree(p->rchild,pre);		//递归,右子树线索化 
		if(p->lchild==NULL) 		//若左子树为空
			p->lchild=pre;			//建立前驱线索,使pre指向p的直接前驱 
			p->ltag=1;				//将当前结点的ltag置为1,标识为线索,指向结点的直接前驱 
		
		if(pre!=NULL&&pre->rchild==NULL) 	//若左子树不为空,且右子树为空
			pre->rchild=p;			//建立后驱线索 ,使p指向pre的直接后驱 
			pre->rtag=1;			//将当前结点的rtag置为1,标识为线索,指向结点的直接后驱 
		
		pre=p;						//pre指向p 
	

以上是关于数据结构学习笔记——线索二叉树的主要内容,如果未能解决你的问题,请参考以下文章

线索二叉树--二叉树线索化

二叉树的线索化

二叉树的线索化

线索化二叉树

在线索二叉树中找前驱和后继(C语言)

线索二叉树的个人理解