C语言线索二叉树基础解读

 更新时间:2022年04月25日 17:10:29   作者:洛语言  
线索二叉树还是按照链二叉树的方法创建,只不过在结点原本为空的左指针改为指向该结点在中序遍历中的前驱,结点原本为空的右指针改为指向该结点在中序遍历中的后继,也就是说把空的指针给利用了起来

线索二叉树的意义

  • 对于一个有n个节点的二叉树,每个节点有指向左右孩子的指针域。其中会出现n+ 1个空指针域,这些空间不储存任何事物,浪费着内存的资源。
  • 对于一些需要频繁进行二叉树遍历操作的场合,二叉树的非递归遍历操作过程相对比较复杂,递归遍历虽然简单明了,但是会有额外的开销,对于操作的时间和空间都比较浪费。
  • 我们可以考虑利用这些空地址,存放指向节点在某种遍历次序下的前驱和后继节点的地址。通过这些前驱和后继节点的地址可以知道,从当前位置下一步应该走向哪里。

线索二叉树的定义

  • 指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树。
  • 对二叉树以某种次序遍历使其变为线索二叉树的过程称为线索化。

线索二叉树结构的实现

二叉树的线索存储结构

为了区分二叉树某一节点是指向它的孩子节点还是指向前驱或者后继节点,我们可以在每个节点增设两个标志,Ltag,Rtag.

其中:

  • Ltag为0时,代表该节点指向它的左孩子,Ltag为1时,代表该节点指向它的前驱节点。
  • Rtag为0时,代表该节点指向它的右孩子,Rtag为1时,代表该节点指向它的后继节点。

所以,线索二叉树结构定义代码如下:

typedef char BTDataType;
typedef enum{Link,Thread}PointerTag;//Link 是0,Thread 是1。
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	PointerTag LTag ;
	PointerTag RTag;
	BTDataType data;
}BTNode;

二叉树的中序线索化

线索化的过程就是在遍历过程中修改空指针的过程

以上二叉树中序遍历可以得到:

  D B E A F C
  D的前驱是空,后继是B
  B的前驱是D,后继是E
  E的前驱是B,后继是A
  F的前驱是A,后继是C
  C的前驱是F,后继是空

线索化后:

中序遍历线索化的递归函数代码如下:

//中序线索化
BTNode* pre = NULL;/*全局变量,始终指向刚刚访问过的节点*/
void InThreading(BTNode* p)
{
	if (p == NULL) return;
	InThreading(p->left);//递归左子树线索化
	if (!p->left)//左孩子为空,left指针指向前驱
	{
		p->LTag = Thread;
		p->left = pre;
	}
	if (pre!=NULL && !pre->right)//右孩子为空,right指针指向后继指针。
	//这里判断 pre!=NULL 是因为线索化中序遍历的第一个节点(节点D)时,它并没有前驱节点,此时的pre仍然是NULL。
	{
		pre->RTag = Thread;
		pre->right = p;
	}
	pre = p;//保持pre指向p的前驱
	InThreading(p->right);
}

分析:

  • if (!p->left)表示如果某节点的左指针域为空,因为其前驱节点刚刚访问过,并且赋值给了pre,所以可以将pre赋值给 l -> left,并且修改 p-> LTag = Thread,以完成前驱节点的线索化。
  • pre 是 p 的前驱,那么, p 就是 pre 的后继。当pre -> right 为空时,就可以将p赋值给 pre -> right , 并且修改 pre -> RTag = Thread。

线索二叉树的中序遍历

void MidOrder(BTNode*p)
{
	while (p != NULL)
	{
		while (p->LTag == Link)//
		{
			p = p->left;
		}
		printf("%c ",p->data);
		while (p->RTag == Thread && p->right != p)
		{
			p = p->right;
			printf("%c ", p->data);
		}
		p = p->right;
	}
	return;
}

分析:

  • while (T->ltag == Link)从根节点开始遍历,如果左标记是Link让它一直循环下去,直到找到标记为Thread的的结点,也就是要遍历的第一个结点,然后根据后驱指针找到后继结点
  • 后面就是重复以上过程,直到遍历完整个二叉数。

总结

如果所用的二叉数需要经常遍历或查找结点时需要某种遍历序列中的前驱和后继,那么采用线索二叉数是一个很好的选择;

以上内容参考于《大话数据结构》。

到此这篇关于C语言线索二叉树基础解读的文章就介绍到这了,更多相关C语言线索二叉树内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现迷宫算法实例解析

    C++实现迷宫算法实例解析

    这篇文章主要介绍了C++实现迷宫算法实例解析,是一个比较经典的C++算法,有一定的学习与借鉴价值,需要的朋友可以参考下
    2014-07-07
  • CrashRpt使用案例详解

    CrashRpt使用案例详解

    这篇文章主要介绍了CrashRpt使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++ 中 const和static readonly区别

    C++ 中 const和static readonly区别

    这篇文章主要介绍了C++ 中 const和static readonly区别的相关资料,需要的朋友可以参考下
    2017-05-05
  • C语言链表实现通讯录系统课程设计

    C语言链表实现通讯录系统课程设计

    这篇文章主要为大家详细介绍了C语言链表实现通讯录系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言 数据结构堆排序顺序存储(升序)

    C语言 数据结构堆排序顺序存储(升序)

    这篇文章主要介绍了C语言 数据结构堆排序顺序存储(升序)的相关资料,需要的朋友可以参考下
    2017-05-05
  • C语言实现猜数字小游戏

    C语言实现猜数字小游戏

    这篇文章主要为大家详细介绍了C语言实现猜数字小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • C语言编程数据结构基础详解小白篇

    C语言编程数据结构基础详解小白篇

    这篇文章主要介绍了数据结构的基础,非常适合初学数据结构的小白,有需要的朋友可以借鉴参考下,希望可以有所帮助,祝大家多多进步,早日升职加薪
    2021-09-09
  • C++解决大数组栈内存不够问题的方法分析

    C++解决大数组栈内存不够问题的方法分析

    这篇文章主要介绍了C++解决大数组栈内存不够问题的方法,结合实例形式对比分析了C++针对大数组栈内存不足情况的常见解决方法及其优缺点,具有一定参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • C语言运算符的重载详解

    C语言运算符的重载详解

    这篇文章主要为大家详细介绍C语言运算符的重载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++ map的简单使用实现

    C++ map的简单使用实现

    map是STL的一个关联容器,它以<key,value>一对一的形式存储,且map的内部自建一个红黑树,使得其可以自动排序,本文就介绍一下C++ map的简单使用,感兴趣的可以了解一下
    2021-05-05

最新评论