二叉树的线索化
为什么要线索化:
在中序遍历二叉树时能够快速的找到某个节点的前驱或后继节点。
条件支持:
在一棵有 n 个节点(每个节点都有前驱和后继两个指针域)的二叉树中,有 n-1 条边,所以会有 2n -(n-1)= n+1 个空指针域
线索化后的结果

线索化后的访问流程
中序线索二叉树的遍历过程如下:
1️⃣ 从根节点开始,沿着左指针一直向下,找到最左节点
p;
2️⃣ 访问该节点;
3️⃣ 然后根据rTag决定下一步:
若
p->rTag == 1,说明p->right是中序后继线索,直接执行p = p->right;若
p->rTag == 0,说明p->right是右子树,转到右子树,继续寻找该右子树的最左节点;不断重复步骤 2️⃣ 和 3️⃣,直到
p == NULL。
如上图所示,当找到D节点时,D是当前状态下的最左节点左点(先访问它),开始 p=p->right,p发现D节点的 rtag==1 说明 D->right 是D的后驱节点,直接访问B;发现 B->rtag == 0 说明 B->right 是B节点的右子树,则进入以 B->left 为根节点的右子树寻找最左节点;发现E就是该最左节点,直接访问E然后继续执行 p=p->right; 接下来的流程以此类推。
如何进行线索化

cur通过递归中的递不断从根节点往左走,然后通过归返回上一个节点。
但cur碰到第一个NULL时,通过归返回上一个节点并通过 cur->left = prev 使prev加入。
并不断通过 prev->right = cur 来记录cur的上一个节点
cur->left=prev; prev->right=cur;
节点结构
typedef struct treeNode{
Element data;
struct treeNode *left;
struct treeNode *right;
int lTag; // 0表示left指向左孩子,1表示left指向了中序前驱
int rTag; // 0表示right指向右孩子,1表示right指向了中序后驱
}BTNode;
// 树头结构
typedef struct{
BTNode *root;
int count;
}ThreadBTree;
线索化
static int *prev;
static void inOrderThreading(BTNode *cur){
if(cur){
inOrderThreading(cur->left);
// 此处代码与中序遍历输出结果的功能位置一致,只是把功能改成了线索化
// 相当于从左边第一次回中
if(cur->left==NULL){
cur->lTag=1;
cur->left=prev;
}
if(prev && prev->right==NULL){
cur->rTag=1;
prev->right=cur;
}
prev=cur; // 更新prev节点,让他指向cur的前一个节点
inOrderThreading(node->right);
}
}
void inOrderThreadingBTree(ThreadedBTree *tree){
if(tree){
inOrderThreading(tree->root);
}
}
// 线索化后遍历这棵树
void InOrderBTree(ThreadedBTree *tree){
BTNode *node=tree->root;
while(node){
// 一直往左走
while(node->lTag==0){
node=node->left;
}
// 找到了线索化的首节点
visitBTNode(node);
// 向右进行中序线索化后的结果
while(node->rTag && node->right){
node=node->right;
visitBTNode(node);
}
// 将这个不是右线索化的节点当作新节点再进行循环
node=node->right;
}
}
1579

被折叠的 条评论
为什么被折叠?



