中序线索二叉树的遍历、寻找结点前驱和后继
笔者在学习过程中,借鉴博客:
https://blog.csdn.net/One_castle/article/details/102968998
遍历
观察图中箭头指向。因为右孩子有可能指向后继,而且即使右孩子不是后继,我们也可以先去到右孩子的最左边,这样后继就是这个结点。所以遍历的核心思想是:先找到最左边的节点,然后判断其右子树是否为线索,如果是线索,那么就遍历后继结点,如果右子树是右孩子,那么就进入到右孩子的最左边的节点,进行同样的判断,直到遍历完了整棵树为止。
void traverThiTree(binThiTree* head) {
binThiTree* p = head->lchild;//头结点的左子树即二叉树的根节点
while (p != head) {//判断遍历是否结束
while (p->LTag == false) { //找打二叉树的最左边的点
p = p->lchild;
}
printf("%d",p->date);//此时p指向最左边的节点
while (p->RTag == true && p->rchild != head) {
p = p->rchild;//指向后继
printf("%d",p->date);
}
p = p->rchild;
//右子树是右孩子,先到右子树,进入下一个循环,找到右子树的最左边结点
}
}
线索二叉树的好处就在于利用了多余的空区域,使之指向前驱或后继,这就使寻找结点的前驱和后继更加方便。
寻找结点前驱
观察线索二叉树的示意图,如果LTag=1,直接找到前驱,如果LTag=0,则走到该结点左子树的最右边的结点,即为要寻找的结点的前驱。
binThiTree* preTreeNode(binThiTree* q) {
binThiTree* cur;
cur = q;
if (cur->LTag == true) {
cur = cur->lchild;
return cur;
}
else{
cur = cur->lchild;//进入左子树
while (cur->RTag == false) {
cur = cur->rchild;
}//找到左子树的最右边结点
return cur;
}
}
寻找结点后继
观察线索二叉树示意图,如果RTag=1,直接找到后继,如果RTag=0,则走到该结点右子树的最左边的结点,即为要寻找的结点的后继。
binThiTree* rearTreeNode(binThiTree* q) {
binThiTree* cur = q;
if (cur->RTag == true) {
cur = cur->rchild;
return cur;
}
else {
//进入到*cur的右子树
cur = cur->rchild;
while (cur->LTag == false) {
cur = cur->lchild;
}
return cur;
}
}