思路
和中跟遍历差不多,不过需要预先定义一个指针pre,在进行中跟遍历访问到本节点时判断当前节点是不是需要的节点,如果不是则pre指向当前节点,是的话则结束遍历,pre当前指向就是前驱。
CODE
#include "func.h"
bool visit_thread(BiNode *node);
// 找前驱节点(中根)
// 使用笨方法
void visit01(){
printf("1");
};
// 中跟遍历
void InOrder(BiTree tree){
if(tree!=NULL){
InOrder(tree->left);
visit01();
InOrder(tree->right);
}
}
// Demo:
// A
// B C
// D E NULL F
//
// 前序:ABDECF 中序:DBEACF 后续:DEBFCA
//
// 假设找到C的中跟先驱节点
// 思路:对树进行中跟遍历,在遍历过程中需要有一个指针指向当前访问节点的先驱节点,假设为pre
// 1. 使用中跟遍历,找到第一个节点,即该节点的左孩子为NULL, 返回上一层递归
// 2. visit此节点,如果此节点为寻找的节点,则pre指向的位置就是前驱节点
// 如果此节点不是寻找的节点,那么让pre指向当前节点
bool InThread(BiTree tree){
if(tree!=NULL){
InThread(tree->left);
if (visit_thread(tree)){
return true;
}
InThread(tree->right);
}
}
// 变量声明
BiTree tree;
BiNode *target;
BiNode *pre = NULL;
BiNode *final;
bool visit_thread(BiNode *p){
if (p->data.value == target->data.value){
final = pre;
return true;
}
else{
pre = p;
return false;
}
}
int main() {
getDemo(tree);
target = tree->right; // 即要寻找C的中跟前驱A
bool flag = InThread(tree);
if(flag == true && pre!=NULL){ // 寻找成功且不为NULL(如果寻找第一个的前驱会返回NULL导致无法打印)
printf("%c",pre->data.value);
}
}
构造一个树
#include "func.h"
void init(BiTree &tree){
tree = (BiNode*) malloc(sizeof(BiNode));
tree->left = NULL;
tree->right = NULL;
}
BiNode* create_node(Element elem){
BiNode *p_node = (BiNode*) malloc(sizeof(BiNode));
p_node->data = elem;
p_node->left=p_node->right=NULL;
return p_node;
}
BiTree getDemo(BiTree &tree){
// Demo:
// A
// B C
// D E NULL F
//
init(tree);
Element A,B,C,D,E,F;
A.value = 'A';
B.value = 'B';
C.value = 'C';
D.value = 'D';
E.value = 'E';
F.value = 'F';
BiNode *pb = create_node(B);
BiNode *pc = create_node(C);
BiNode *pd = create_node(D);
BiNode *pe = create_node(E);
BiNode *pf = create_node(F);
tree->data = A;
tree->left = pb;
tree->right = pc;
pb -> left = pd;
pb->right = pe;
pc->right = pf;
}