数据结构笔记18:线索二叉树的实现(c语言)

一、前言:什么是二叉树的线索化?(为什么要有二叉树的线索化?)

  • 通过前面内容的学习,我们知道了二叉树的存储结构其实是通过二叉链表的方式实现的。但二叉链表由于每个结点均有左右孩子域,这使得叶子结点以及部分非叶子结点出现了孩子指针域为空的情况。

如图例:

在这里插入图片描述

  • 可以发现的是,随着二叉树结点个数 的增长,二叉树中空指针域的个数越来越多,这会造成不小的存储空间浪费。
  • 假设,现在需要你求解一个节点的前驱节点/后续节点,你要如何进行呢?
  • 通过遍历方法我们确实可以知道二叉树中某个结点的前驱和后继分别是谁,但是这是建立在二叉树遍历的基础上的。一旦二叉树遍历结束后,如果想要知道二叉树中某个结点的前驱或后继时,得从头结点开始遍历二叉链表,这将会造成不小的时间开销。
  • 如图中的二叉链表如果我想要找到 的前驱是谁,得遍历一遍二叉树才能搞定
  • 既然有那么多空指针域,为什么不能把这些空指针域利用起来,让每个空指针域用来记录当前结点的前驱呢?这样一来,是不是就解决了空指针域造成的存储空间浪费以及查找前驱后继时时造成的时间浪费呢?
    因此,二叉线索树诞生了

二、二叉线索树的概念

2.1:名词解释

  • 让二叉树中的空指针域记录二叉树某种遍历次序下的前驱和后继结点的地址,这样的话,再想找二叉树中某个结点的前驱后继时间性能将大为提升。
  • 这种将二叉链表中指向前驱后继的指针称为线索,加上线索的二叉链表称之为线索链表,线索链表所对应的二叉树称之为线索二叉树(Threaded Binary Tree)
    在这里插入图片描述

三、二叉线索树的实现

3.1:二叉线索树的基本数据结构

typedef struct ThreadedTreeNode {
    // 线索化二叉树节点
    eleType val;
    struct ThreadedTreeNode* left;  // 左指针
    struct ThreadedTreeNode* right; // 右指针
    int leftTag;  // 左标志位:0 表示指向左子树,1 表示指向前驱
    int rightTag; // 右标志位:0 表示指向右子树,1 表示指向后继
} ThreadedTreeNode;
//leftTag和rightTag默认为0
  • eleType val:存储节点的值,根据宏定义,这里是 char 类型。 - struct ThreadedTreeNode* left:指向左子节点的指针。
  • struct ThreadedTreeNode* right:指向右子节点的指针。
  • int leftTag:标志位,0 表示 left 指针指向左子树,1 表示 left 指针指向前驱节点。
  • int rightTag:标志位,0 表示 right 指针指向右子树,1 表示 right 指针指向后继节点。

3.2:初始化节点

// 初始化节点
ThreadedTreeNode* Init_Node(eleType val) 
{
   
    ThreadedTreeNode* node = (ThreadedTreeNode*)malloc(sizeof(ThreadedTreeNode));
    node->val = val;
    node->left = NULL;
    node->right = NULL;
    node->leftTag = 0;
    node->rightTag = 0;
    return node;
}

在这里插入图片描述

  • ThreadedTreeNode* Init_Node(eleType val):一个函数,用于初始化一个 ThreadedTreeNode 节点。
    • ThreadedTreeNode* node = (ThreadedTreeNode*)malloc(sizeof(ThreadedTreeNode));:为新节点分配内存空间。
    • node->val = val;:将传入的值存储到节点的 val 成员中。
    • node->left = NULL;node->right = NULL;:将左右子节点指针初始化为 NULL
    • node->leftTag = 0;node->rightTag = 0;:将左右标志位初始化为 0,表示它们初始时都指向左右子树。
    • return node;:返回初始化好的节点指针。

3.3:创建一个普通二叉树

// 创建普通二叉树(同前面代码中一样,略去重复部分)
ThreadedTreeNode* CreateTree(eleType a[], int size, int index, eleType nullNode) 
{
   
    if (index >= size || a[index] == nullNode) 
    {
   
        return NULL;
    }
    ThreadedTreeNode* root = Init_Node(a[index]);   //初始化节点
    root->left = CreateTree(a, size, 2 * index + 1, nullNode);  //递归创建二叉树
    root->right = CreateTree(a, size, 2 * index + 2, nullNode);
    return root;
}
  • ThreadedTreeNode* CreateTree(eleType a[], int size, int index, eleType nullNode):一个递归函数,用于根据数组元素创建普通二叉树。
    • if (index >= size || a[index] == nullNode):如果当前索引超出数组范围或元素等于 nullNode,返回 NULL,表示该位置无节点。
    • ThreadedTreeNode* root = Init_Node(a[index]);:创建当前位置的节点。
    • root->left = CreateTree(a, size, 2 * index + 1, nullNode);:递归创建左子树。
    • root->right = CreateTree(a, size, 2 * ind
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值