在线索二叉树中找前驱后继
在线索二叉树中找前驱后继
在线索二叉树中,每个节点除了左右子节点指针外,还增加了两个标记位:ltag和rtag。其中,ltag表示左子节点是否为前驱,rtag表示右子节点是否为后继。通过这两个标记位,我们可以方便地找到任意节点的前驱和后继节点。
一、前驱节点的查找
1. 中序线索二叉树:
在中序线索二叉树中,如果一个节点的左子节点为空,则它的前驱节点就是它的左子节点;否则,我们需要沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空,那么这个节点就是前驱节点。
代码实现:
ThreadedNode* inPredecessor(ThreadedNode* p) {
if (p->ltag == 0) { // 如果左子节点不为空,则直接返回左子节点
return p->left;
} else { // 否则,沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空
ThreadedNode* q = p->left;
while (q->rtag == 1) {
q = q->right;
}
return q;
}
}
2. 前序线索二叉树:
在前序线索二叉树中,如果一个节点的左子节点为空,则它的前驱节点就是它的左子节点;否则,我们需要沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空,那么这个节点就是前驱节点。
①如果能找到p的父节点且p是左孩子
②如果能找到p的父节点,且p是右孩子,其左兄弟为空
③如果能找到p的父节点,且p是右孩子,其左兄弟非空
④如果p是根节点,则p没有先序前驱
代码实现:
ThreadedNode* prePredecessor(ThreadedNode* p) {
if (p->ltag == 0) { // 如果左子节点不为空,则直接返回左子节点
return p->left;
} else { // 否则,沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空
ThreadedNode* q = p->left;
while (q->rtag == 1) {
q = q->right;
}
return q;
}
}
3. 后序线索二叉树
在后序线索二叉树中,如果一个节点的左子节点为空,则它的前驱节点就是它的左子节点;否则,我们需要沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空,那么这个节点就是前驱节点。
代码实现:
ThreadedNode* postPredecessor(ThreadedNode* p) {
if (p->ltag == 0) { // 如果左子节点不为空,则直接返回左子节点
return p->left;
} else { // 否则,沿着左子节点一直向下遍历,直到找到一个节点的右子节点为空
ThreadedNode* q = p->left;
while (q->rtag == 1) {
q = q->right;
}
return q;
}
}
二、后继节点的查找
1. 中序线索二叉树:
在中序线索二叉树中,如果一个节点的右子节点为空,则它的后继节点就是它的右子节点;否则,我们需要沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空,那么这个节点就是后继节点。
代码实现:
ThreadedNode* inSuccessor(ThreadedNode* p) {
if (p->rtag == 0) { // 如果右子节点不为空,则直接返回右子节点
return p->right;
} else { // 否则,沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空
ThreadedNode* q = p->right;
while (q->ltag == 1) {
q = q->left;
}
return q;
}
}
2. 前序线索二叉树:
在前序线索二叉树中,如果一个节点的右子节点为空,则它的后继节点就是它的右子节点;否则,我们需要沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空,那么这个节点就是后继节点。
代码实现:
ThreadedNode* preSuccessor(ThreadedNode* p) {
if (p->rtag == 0) { // 如果右子节点不为空,则直接返回右子节点
return p->right;
} else { // 否则,沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空
ThreadedNode* q = p->right;
while (q->ltag == 1) {
q = q->left;
}
return q;
}
}
3. 后序线索二叉树:
在后序线索二叉树中,如果一个节点的右子节点为空,则它的后继节点就是它的右子节点;否则,我们需要沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空,那么这个节点就是后继节点。
①如果能找到p的父节点,且p是右孩子
②如果能找到p 的父节点,且p是左孩子,其右兄弟为空
③如果能找到p的父节点,且p是左孩子,其右兄弟非空
④如果p是根节点,则p没有后序后继
代码实现:
ThreadedNode* postSuccessor(ThreadedNode* p) {
if (p->rtag == 0) { // 如果右子节点不为空,则直接返回右子节点
return p->right;
} else { // 否则,沿着右子节点一直向下遍历,直到找到一个节点的左子节点为空
ThreadedNode* q = p->right;
while (q->ltag == 1) {
q = q->left;
}
return q;
}
}
本文原文来自CSDN