二叉线索树实现
二叉线索树主要是方便查找树的前趋和后继的,充分的把二叉树的空指针域利用起来,要是有前趋就指向前趋,要是有后继就只想后继。
代码:
#include<iostream>
using namespace std;
/**通过枚举类型,child = 0, thread = 1,来表示树中的节点指向的是正常的孩子,还是用来指引线索*/
typedef enum{ child, thread } PointTag;
/**创建线索二叉树的结点*/
struct ThBiTreeNode{
char m_nValue;
ThBiTreeNode* m_pLeft;
PointTag m_pLeftTag;
ThBiTreeNode* m_pRight;
PointTag m_pRightTag;
};
/**在创建时需要加进去的head*/
ThBiTreeNode* pre;
/**通过前序遍历来构造一个树*/
void CreateBiTree(ThBiTreeNode* &T){
char c;
scanf("%c", &c);
if (c == ' '){
T = NULL;
}
else{
T = new(ThBiTreeNode);
T->m_nValue = c;
T->m_pLeftTag = child;
T->m_pRightTag = child;
CreateBiTree(T->m_pLeft);
CreateBiTree(T->m_pRight);
}
}
/**构建线索树(填装线索)*/
void InThred(ThBiTreeNode* &T){
if (T){
InThred(T->m_pLeft);
/**左子树为空,改变tag,并指向它的前驱*/
if (!(T->m_pLeft)){
T->m_pLeftTag = thread;
T->m_pLeft = pre;
}
/**此次遍历到了B,B在序列中前一个节点为A,如果A没有右节点,那么久把B作为A的后继*/
if (!(pre->m_pRight)){
pre->m_pRightTag = thread;
pre->m_pRight = T;
}
/**本次的结点处理完之后,就成为了下一次处理节点的上一个节点*/
pre = T;
InThred(T->m_pRight);
}
}
/**构建线索数(增加head节点),最后把序列最后一个数和head节点的右节点建立线索*/
void InOrderThreadBiTree(ThBiTreeNode* &head, ThBiTreeNode* &T){
/**先把head节点放进来,判断T是否为空树的话,在添加线索的时候做,T为空树,我head照样可以连接*/
head = new(ThBiTreeNode);
head->m_nValue = NULL;
head->m_pLeftTag = child;
head->m_pRightTag = thread;
/**如果传进来的树是一个空树,那么head节点的左子节点指向自己*/
if (!T){
head->m_pLeft = head;
}
else{
head->m_pLeft = T;
pre = head;
InThred(T);
/**是在所有都线索化完成之后,才把序列的最后一个的右线索,连接在head节点上*/
/**在完成上面的线索建立后,pre是指向中序遍历的最后一个元素的,就是树中最右边的元素*/
pre->m_pRightTag = thread;
pre->m_pRight = head;
/**把head的右线索连接在序列最后一个*/
head->m_pRight = pre;
}
}
void vist(ThBiTreeNode* T){
std::cout << T->m_nValue << std::endl;
}
/**中序遍历打印二叉树*/
void InorderTraverse(ThBiTreeNode* T){
ThBiTreeNode* temp;
/**现在这个temp指向的就是加入了head节点之后树的根节点(不是head)*/
temp = T->m_pLeft;
/**如过指向左孩子的指针,和指向根节点的指针是同一个的时候*/
/**表示这个树要么是空树,要么是遍历结束的时候*/
while (temp != T){
while (temp->m_pLeftTag == child){
temp = temp->m_pLeft;
}
vist(temp);
/**p-rchild != T,就表示这个点不是指向你加入的那个head节点,就表明,现在这个遍历的结点是有真正的后继的*/
while (temp->m_pRightTag == thread && temp->m_pRight != T){
/**这个时候,树已经线索化完成了,p的右孩子现在指向的是它序列中的后继*/
temp = temp->m_pRight;
vist(temp);
}
temp = temp->m_pRight;
}
}
int main(){
/**原始树*/
ThBiTreeNode* T;
/**加了头的树*/
ThBiTreeNode* T_head;
/**根据输入创建基本二叉树*/
CreateBiTree(T);
/**把head节点加进去,并且建立线索*/
InOrderThreadBiTree(T_head, T);
/**中序遍历带有head的树*/
InorderTraverse(T_head);
system("pause");
return 0;
}