数据结构与算法之二叉树的线索化

两种方式(这里主要讲述中序线索化)

用土办法找到中序前驱(暴力)

void InOrder(BiTree T){
	if(T!=NULL){
		InOrder(T->lchild);//递归遍历左子树
		visit(T);
		InOrder(T->rchild);//递归遍历右子树
	}
}
void visit(BiTNode *q){
	if(q==p){
		final = pre;//找到p的前驱
	}else{
		pre = q;
	}
}
//辅助全局变量,用于查找结点p的前驱
BiTNode *p;//p指向目标结点
BiTNode * pre = NULL;//指向当前访问结点的前驱
BiTNode * final = NULL;//用于记录最终结果

image.png

中序线索化

先序线索化后序线索化也参考此思路

typedef struct ThreadNode{
  ElemType data;
  struct ThreadNode *lchild,*rchild;
  int ltag,rtag;//左右线索标志
}ThreadNode,*ThreadTree;

//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre=NULL;

void InThread(ThreadTree T){
	if (T!=NULL){
		InThread(T->lchild);//中序遍历左子树
		visit(T);//访问根节点
		InThread(T->rchild);//中序遍历右子树
	}
}

void visit(BiTNode *q){
	if(q->lchild==NULL){//左子树为空,建立前驱线索
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre!=NUll&&q->rchild==NULL){
		pre.rchild=q;//建立前驱结点的后继线索
		pre->rtag=1;
	}
	pre=q;
}

注意:最后还要检查prerchild是否为NULL,如果是,则令rtag=1;

VeryCapture_20220601154136.gif

image.png

全部代码展示

/**
 * 二叉搜索树
 * @author five-five
 * @created 2022/6/1
 *
 */

#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"

typedef struct ThreadNode {
    int data;
    struct ThreadNode *lChild;
    struct ThreadNode *rChild;
    int ltag;
    int rtag;
} ThreadNode, *ThreadTree;

ThreadNode **preNode = NULL;

void preVisit(ThreadNode *pNode);

/**
 * 前序线索化二叉树
 * @param threadTree 二叉树
 * @param pre 使用双重指针接受上结点
 * @return ture?线索化成功:线索化失败
 */
bool preInitThreadTree(ThreadTree threadTree, ThreadNode **pre) {
    if (threadTree == NULL) {
        return false;
    }
    *pre = NULL;
    //左子树
    preInitThreadTree(threadTree, pre);
    if (threadTree->lChild == NULL) {
        threadTree->lChild = (*pre);
        threadTree->ltag = 1;
    }
    //当前结点
    if (*pre != NULL && (*pre)->rChild == NULL) {
        *pre = threadTree->rChild;
        (*pre)->rtag = 1;
    }
    *pre = threadTree;
    //右结点
    preInitThreadTree(threadTree->rChild, pre);
    return true;
}

/**
 * 先序遍历
 * @param threadTree 要遍历的树
 * @return true?成功:失败
 */
bool preOrder(ThreadTree threadTree) {
    if (threadTree == NULL) {
        return false;
    }
    preOrder(threadTree->lChild);
    preVisit(threadTree);
    preOrder(threadTree->rChild);
    return true;
}

/**
 * 先序遍历
 * @param pNode 当前结点
 * @param pre 前序结点指针
 */
void preVisit(ThreadNode *pNode) {
    if (pNode == NULL) {
        return;
    }
    if (pNode->lChild == NULL) {
        pNode->lChild = (*preNode);
        pNode->ltag = 1;
    }
    if ((*preNode) != NULL && (*preNode)->rChild == NULL) {
        (*preNode)->rChild = pNode;
        (*preNode)->rtag = 1;
    }
    (*preNode) = pNode;
}

总结

image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

five-five

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值