二叉树的线索化算法——C语言

通过中序遍历对二叉树线索化的算法实现

在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化

线索二叉树的结点结构:

ltaglchilddatarchildrtag

其中,标志域的含义如下:
l t a g { 0 , l c h i l d 域 指 向 结 点 的 左 孩 子 1 , l c h i l d 域 指 向 结 点 的 前 驱 ltag\left\{ \begin{aligned} 0,lchild域指向结点的左孩子 \\ 1,lchild域指向结点的前驱 \end{aligned} \right. ltag{0lchild1lchild
r t a g { 0 , r c h i l d 域 指 向 结 点 的 右 孩 子 1 , r c h i l d 域 指 向 结 点 的 后 继 rtag\left\{ \begin{aligned} 0,rchild域指向结点的右孩子 \\ 1,rchild域指向结点的后继 \end{aligned} \right. rtag{0rchild1rchild
线索二叉树存储结构描述如下:

typedef struct ThreadNode {
// 定义线索二叉树存储结构
  ElemType data;                        // 数据域
  struct ThreadNode *lchild, *rchild;   // 左、右孩子指针
  int ltag, rtag;                       // 左、右线索标志
}ThreadNode, *ThreadTree;

线索二叉树的构造:
对二叉树的线索化,实质就是遍历一次二叉树,只是在遍历的过程中,检查当前结点左、右指针域是否为空,若为空,将它们改为指向前驱结点或后继结点的线索。

递归算法
void InThread(ThreadTree p, ThreadTree* pre) {
// 中序遍历对二叉树线索化的递归算法
  if (p) {
    InThread(p->lchild, pre);       // 递归,线索化左子树
    if (!p->lchild) {               // 左子树为空,则建立前驱线索
      p->lchild = *pre;
      p->ltag = 1;
    }
    if (*pre && !(*pre)->rchild) {  // 建立前驱结点的后继线索
      (*pre)->rchild = p;
      (*pre)->rtag = 1;
    }
    *pre = p;                       // 标记当前结点成为刚刚访问过的结点
    InThread(p->rchild, pre);       // 递归,线索化右子树
  }
}

void CreateInThread(ThreadTree T)
{// 通过中序遍历建立中序线索二叉树的主过程
  ThreadTree pre = NULL;
  if (T) {                            // 非空二叉树,线索化
    InThread(T, &pre);                // 线索化二叉树
    pre->rchild = NULL;               // 处理遍历的最后一个结点
    pre->rtag = 1;
  }
}
非递归算法
void InThread(ThreadTree T) {
// 中序遍历对二叉树线索化的非递归算法
  SqStack S = {0}; S.top = -1;
  ThreadTree p = T, pre = NULL;
  while(p || S.top != -1) {             // 根节点或栈非空时循环
    if (p) {                            // 每遇到非空结点先入栈,再往左遍历
      Push(&S, p);
      p = p->lchild;
    } else {                            // 退栈,访问根结点
      Pop(&S, &p);
      if (!p->lchild) {                 // 若左子树为空,则建立前驱线索
        p->lchild = pre;
        p->ltag = 1;
      }
      if (pre && !pre->rchild) {        // 建立前驱结点的后继线索
        pre->rchild = p;
        pre->rtag = 1;
      }
      pre = p;                          // 标记当前结点成为刚刚访问过的结点
      p = p->rchild;                    // 遍历右子树
    }
  }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值