注意两个规定:在遍历序里的第一个元素没有前驱,最后一个元素没有后继,但规定:让它们分别指向head
节点,便于遍历操作
#include<bits/stdc++.h>
using namespace std;
struct Bth_node {
int val;
int ltag;
int rtag;
Bth_node* left;
Bth_node* right;
Bth_node(int val = 0, Tnode* left = nullptr, Tnode* right = nullptr, int ltag = 0, int rtag = 0)
:val(val), left(left), right(right),ltag(ltag),rtag(rtag) {};
};
struct Bth_Tree {
private:
bool lflag;
public:
Bth_node* root;
Bth_node* head; //指向root节点
Bth_node* pre; //在线索化中始终可见的 前驱节点
Tree() {
root = nullptr;
lflag = true;
}
void createTree(string& s);
void createThread(); //在这个函数里建head节点
void thread(Bth_node*& r); //可不传递引用类型
void Bth_InOrder();
};
int main(){
return 0;
}
//中序线索化二叉树
void Bth_Tree::createThread(){
head = new Bth_node(); //为 root 做 pre 节点
head->ltag = 0, head->rtag = 1; //head左孩子指向root,右节点为空
head->right = root; //线索化到root节点,实际可为任意节点。最终要线索化到 中序序列 的最后一个节点
if(root == nullptr){
head->left = head; //建空树
head->right = nullptr;
}
else{
head->left = root; //将实际首节点作为左孩子
pre = head; //pre始终指向节点r(thread函数的参数)的前驱节点,没有前驱则指向head
thread(root); //中序遍历线索化二叉树 所有节点
pre->rtag = 1; //给遍历序最后一个节点设置rtag right
pre->right = root;
head->right = pre; //最终对head的线索化,pre指向遍历序的最后节点
}
}
void Bth_Tree::thread(Bth_node*& r){ // 对 r 为头节点的树 进行线索化
if(r != nullptr){
Thread(r->left); //线索化左子树
if(r->left == nullptr){
r->left = pre;
r->ltag = 1;
}
//else r->ltag = 0; //应该可不用,默认为0
if(pre->right == nullptr){ //注意是 pre 节点 !!
pre->right = r; //pre在 遍历序 是r的前驱,反过来r在遍历序就是pre的后继
pre->rtag = 1;
}
//else r->rtag = 0;
pre = r; // pre 始终在 遍历序 中追随者r节点,故容易为其他节点提供前驱
Thread(r->right); //线索化右子树
}
}
void Bth_Tree::Bth_InOrder(){
Bth_node* p = head->left; //即 root 节点
while(p != head){ //非空树
while(p != head && p->ltag == 0){
p = p->left;
}
//对于子树,中序遍历 第一个节点
cout<<p->val<<" ";
while(p->rtag == 1 && p->right != head){ //根据线索访问后继 第二个条件为了保证p不是最右节点
p = p->right;
cout<<p->val<<" ";
}
p = p->right; //不再是线索,访问其右节点 下一轮循环解决
}
}
void Bth_Tree::createTree(string& s) { //括号表示串 建树
stack<Bth_node*>st;
Bth_node* p, q; //p 指向当前节点, q 指向栈顶节点/曾经节点
bool lflag = false;
int i = 0, n = s.size();
while (i < n) {
char ch = s[i];
switch (ch) {
case '(':
st.push(p); //当前节点成为 曾经节点
lflag = true;
break;
case ')':
st.pop(); //曾经节点 已处理完
break;
case ',':
lflag = false; //区分左右孩子节点
break;
default:
//当前节点
int num = 0;
while (i < n && s[i] >= '0' && s[i] <= '9') {
num = num * 10 + s[i++] - '0';
}
i--;
p = new Bth_node(num);
if (root == nullptr) {
root = p; //栈必然为空
}
else {
if (!st.empty()) { //栈的第一个节点
if (lflag) {
st.top()->left = p;
}
else {
st.top()->right = p;
}
}
}
break;
}
i++;
}
}