在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
传统的二叉树由于只有指向左右孩子结点的指针,因此如果在某个业务中需要频繁的使用其前驱结点,因此这种情况下就会非常的不方便,只能采用从头遍历的笨办法,因此采用线索化的方法,通过将前后驱结点利用线索化的方法串联起来,会使得我们处理这些问题变得更加的方便。
using namespace std;
#define ElemType int
typedef struct ThreadNode {
ElemType data;
struct ThreadNode *left, *right;
int rtag, ltag;
}ThreadNode, *ThreadTree;
//全局变量指向q的前驱
ThreadNode *pre = nullptr;
void visited(ThreadNode *q) {
//左子树为空,建立前驱
if (q->left == nullptr) {
q->left = pre;
q->ltag = 1;
}
//前驱的右子树为空,建立后继
if (pre != nullptr && pre->right == nullptr) {
pre->right = q;
pre->rtag = 1;
}
pre = q;
}
void inOrder(ThreadTree L) {
if (L == nullptr)
return;
inOrder(L->left);
visited(L);
inOrder(L->right);
}
void preOrder(ThreadTree L) {
if (L == nullptr)
return;
visited(L);
if (L->ltag == 0) //left不是前驱线索的时候
preOrder(L->left);
preOrder(L->right);
}
//中序遍历建立线索二叉树
void CreateTreeInorder(ThreadTree T) {
//初始化pre指针
pre = nullptr;
if (T != nullptr) {
inOrder(T);
//将最后一个结点的tag设置为1
if (pre->right == nullptr)
pre->rtag = 1;
}
}
//先序遍历建立线索二叉树
void CreateTreePreOrder(ThreadTree T) {
pre = nullptr;
if (T != nullptr) {
preOrder(T);
if (pre->right == nullptr)
pre->rtag = 1;
}
}
需要注意的是在先序建立的时候要考虑是否链表存在环,因此我们在先序遍历的时候要通过tag变量去判断其左孩子是否已经线索化!
不论是什么方法去建立,最后都别忘记要将最后一个孩子的右指针置为null,这是一个很好的习惯。