数据结构——线索二叉树

简介: 数据结构——线索二叉树

线索二叉树原理


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

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

本质

二叉树的遍历本质上是将一个复杂的非线性结构转换为线性结构,使每个结点都有了唯一前驱和后继(第一个结点无前驱,最后一个结点无后继)。对于二叉树的一个结点,查找其左右子女是方便的,其前驱后继只有在遍历中得到。为了容易找到前驱和后继,有两种方法。一是在结点结构中增加向前和向后的指针,这种方法增加了存储开销,不可取;二是利用二叉树的空链指针

分析

通过二叉树的中序遍历得:

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

如下图:
在这里插入图片描述
为了区分lchild是指向左孩子还是指向它的前继,rchild是指向右孩子还是指向它的后继
我们再在每个结点再增加两个标志域ltag和rtag,里面存放0和1在这里插入图片描述
其中:

  1. ltag为0时指向该节点的左孩子,为1时指向该节点的前驱
  2. rtag为0时指向该节点的右孩子,为1时指向该节点的后继

线索二叉数结构的实现

线索二叉数存储结构定义

typedef char TElemType;
typedef enum {
    Link,Thread}PointerTag;
typedef struct BiThrNode
{
    
    TElemType data;
    struct BiThrNode* lchild;
    struct BiThrNode* rchild;
    PointerTag ltag;
    PointerTag rtag;
}BiThrNode;

二叉树线索化

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

BiThrNode* pre = NULL;  //全局变量,始终指向刚刚访问过的结点
void InThreading(BiThrNode* p)
{
    
    if (p)
    {
    
        InThreading(p->lchild);    //递归左数进行线索化
        if (!p->lchild)          //前驱线索
        {
    
            p->ltag = Thread;
            p->lchild = pre;
        }
        if (!pre->rchild)    //后继线索
        {
    
            pre->rtag = Thread;
            pre->rchild = p;
        }
        pre = p;
        InThreading(p->rchild);  //递归有树线索化
    }
}

分析:
if (!p->lchild) 表示如果某节点的左指针域为空,则将其前驱赋连上刚刚访问过的结点pre,
即p->lchild = pre,并将标记进行修改p->ltag = Thread;
if (!pre->rchild) 表示如果刚刚访问过的结点pre的右指针域为空,则将它的后继连上正在访问的结点,
即pre->rchild = p,并将标记进行修改pre->rtag = Thread

线索二叉树的遍历

void InOrderTraverse(BiThrNode* T)
{
    
    while (T)
    {
    
        while (T->ltag == Link)
        {
    
            T = T->lchild;
        }
        printf("%c ", T->data);
        while (T->rtag == Thread && T->rchild != NULL)
        {
    
            T = T->rchild;
            printf("%c ", T->data);
        }
        T = T->rchild;
    }
}

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

总结

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

相关文章
|
14天前
|
存储 机器学习/深度学习
【数据结构】二叉树全攻略,从实现到应用详解
本文介绍了树形结构及其重要类型——二叉树。树由若干节点组成,具有层次关系。二叉树每个节点最多有两个子树,分为左子树和右子树。文中详细描述了二叉树的不同类型,如完全二叉树、满二叉树、平衡二叉树及搜索二叉树,并阐述了二叉树的基本性质与存储方式。此外,还介绍了二叉树的实现方法,包括节点定义、遍历方式(前序、中序、后序、层序遍历),并提供了多个示例代码,帮助理解二叉树的基本操作。
38 13
【数据结构】二叉树全攻略,从实现到应用详解
|
3月前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
28 0
|
11天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
11天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
11天前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
1月前
|
存储
【初阶数据结构篇】二叉树基础概念
有⼀个特殊的结点,称为根结点,根结点没有前驱结点。
|
1月前
|
存储 Linux Windows
【数据结构】二叉树
【数据结构】二叉树
|
1月前
|
存储 算法 Linux
【数据结构】树、二叉树与堆(长期维护)(1)
【数据结构】树、二叉树与堆(长期维护)(1)
|
1月前
|
算法
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
|
1月前
|
算法 Java
数据结构二叉树
这篇文章讨论了数据结构中的二叉树,并提供了一个二叉树中序遍历的算法示例,包括给定二叉树的根节点返回中序遍历结果的Java代码实现。
数据结构二叉树