中序线索二叉树
线索二叉树就是在原本的二叉树中将其空的指针域赋上前驱指针或者后继指针
中序遍历:左->根->右
①当指针域不为空,向左进行遍历,找到最左边的结点
②如果该结点的右孩子为空,标记前tag,并使前驱指向左孩子
③如果该结点的前驱为空,标记后tag,并使后继指向右孩子
结点结构
在原本的二叉树上再添加两个标记:Ltag,Rtag;Ltag=0表示有左孩子,Ltag=1表示有前驱;Rtag同理
遍历
因为有了前驱与后继,所以可以像数组一样进行遍历,但是需要(在中序遍历中)找到线索二叉树的第一个结点与他的next,即后继指针,从而进行遍历
其他处理
因为中序遍历会遍历到最后一个结点,所以最后一个结点的Rtag=1;最后一个结点的Rchild=NULL
#include<iostream>
using namespace std;
typedef struct TreeNode
{
char data;
struct TreeNode* Lchild;
struct TreeNode* Rchild;
int Ltag;//0表示有孩子,1表示有前驱或者后继
int Rtag;
}TreeNode;
void creatTree(TreeNode** T, char* x, int* index)
{
char ch;
ch = x[*index];
*index +=1;
if (ch == '#')
{
*T = NULL;
}
else
{
*T = new TreeNode;
(*T)->data = ch;
(*T)->Ltag = 0;//因为有孩子,所以设置为0
(*T)->Rtag = 0;
creatTree(&(*T)->Lchild, x, index);
creatTree(&(*T)->Rchild, x, index);
}
}
void visit(TreeNode* T)
{
cout << T->data << " ";
}
void threadTree(TreeNode* T, TreeNode** pre)
{
if (T != NULL)
{
threadTree(T->Lchild, pre);
if (T->Lchild == NULL)//没有左孩子,可以有前驱
{
T->Ltag = 1;//标记为有前驱
T->Lchild = *pre;//T根节点的左孩子保存为*pre前驱
}
if (*pre != NULL&&(*pre)->Rchild==NULL)//自己不为NULL,且右孩子为NULL,可以做后继
{
(*pre)->Rtag = 1;
(*pre)->Rchild = T;
}
*pre = T;
threadTree(T->Rchild, pre);
}
}
TreeNode* getFirst(TreeNode* T)
{
while (T->Ltag == 0)//第一个结点的前驱为NULL,Ltag为1
{
T = T->Lchild;
}
return T;
}
TreeNode* getNext(TreeNode* T)
{
if (T->Rtag == 1)//即当前结点有后继,直接返回后继
{
return T->Rchild;
}
else//当前结点有孩子,就找这棵树的第一个结点
{
return getFirst(T->Rchild);
}
}
int main()
{
char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
TreeNode* T = new TreeNode;
TreeNode* pre = NULL;
int index = 0;
creatTree(&T, arry, &index);
threadTree(T, &pre);//通过创建线索树,T根结点移动到最后一个结点上
pre->Rtag = 1;//最后一个结点有后继,其后继的右孩子为NULL
pre->Rchild = NULL;
for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node))
{
cout << node->data << " ";
}
cout << endl;
}
前序遍历
#include<iostream>
using namespace std;
typedef struct TreeNode
{
char Tdata;
struct TreeNode* Lchild;
struct TreeNode* Rchild;
bool Ltag;
bool Rtag;
};
void creatTree(TreeNode** T, char* x, int* index)
{
char ch;
ch = x[*index];
*index += 1;
if (ch == '#')
*T = NULL;
else
{
*T = new TreeNode;
(*T)->Tdata = ch;
(*T)->Ltag = 0;
(*T)->Rtag = 0;
creatTree(&(*T)->Lchild, x, index);
creatTree(&(*T)->Rchild, x, index);
}
}
void visit(TreeNode* T)
{
cout << T->Tdata << " ";
}
void preThreadTree(TreeNode* T, TreeNode** pre)
{
if (T)
{
if (T->Lchild == NULL)
{
T->Ltag = 1;
T->Lchild = *pre;
}
if (*pre != NULL && (*pre)->Rchild==NULL)
{
(*pre)->Rtag = 1;
(*pre)->Rchild = T;
}
*pre = T;
if(T->Ltag==0)
preThreadTree(T->Lchild,pre);
preThreadTree(T->Rchild,pre);
}
}
TreeNode* getNext(TreeNode* T)
{
if (T->Rtag == 1)//如果没有右孩子
{
return T->Rchild;//直接返回后继
}
else//有右孩子
{
if (T->Ltag == 0)//又看成一个根结点,有左孩子,直接返回其左孩子当做前驱
return T->Lchild;
else
return T->Rchild;
}
}
/*
TreeNode* getNext(TreeNode* T)
{
if (T->Ltag == 0)
return T->Lchild;
else
return T->Rchild;
}*/
int main()
{
char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
TreeNode* T;
TreeNode* pre = NULL;
int index = 0;
creatTree(&T, arry, &index);
preThreadTree(T, &pre);
(*pre).Rtag = 1;
(*pre).Rchild = NULL;
cout << "前序遍历:";
for (TreeNode* node = T; node != NULL; node = getNext(node))
{
visit(node);
}
cout << endl;
}
后序遍历
#include<iostream>
using namespace std;
typedef struct TreeNode
{
char data;
struct TreeNode* Lchild;
struct TreeNode* Rchild;
struct TreeNode* Parent;
int Ltag;
int Rtag;
}TreeNode;
void createTree(TreeNode** T, char* x, int* index, TreeNode* parent)
{
char ch;
ch = x[*index];
*index += 1;
if (ch == '#')
{
*T = NULL;
}
else
{
*T = new TreeNode;
(*T)->data = ch;
(*T)->Ltag = 0;
(*T)->Rtag = 0;
(*T)->Parent = parent;
createTree(&(*T)->Lchild, x, index, *T);
createTree(&(*T)->Rchild, x, index, *T);
}
}
void visit(TreeNode* T)
{
cout << T->data << " ";
}
void postThreadTree(TreeNode* T, TreeNode** pre)
{
if (T)
{
postThreadTree(T->Lchild, pre);
postThreadTree(T->Rchild, pre);
if (T->Lchild == NULL)
{
T->Ltag = 1;
T->Lchild = *pre;
}
if (*pre != NULL && (*pre)->Rchild == NULL)
{
(*pre)->Rtag = 1;
(*pre)->Rchild = T;
}
*pre = T;
}
}
TreeNode* getFirst(TreeNode* T)
{
while (T->Ltag == 0)
{
T = T->Lchild;
}
if (T->Rtag == 0)
return getFirst(T->Rchild);
return T;
}
TreeNode* getNext(TreeNode* T)
{
if (T->Rtag == 1)
return T->Rchild;
else
{
//判断是否是根结点
if (T->Parent == NULL)
return NULL;
else if (T == T->Parent->Rchild)//如果是右孩子(说明左孩子已经遍历了)
{
return T->Parent;
}
else//如果是左孩子
{
if (T->Parent->Rtag == 0)//如果当前结点的Parent有右孩子,就获得右孩子那一分支的第一个结点
{
return getFirst(T->Parent->Rchild);
}
else
{
return T->Parent;
}
}
}
}
int main()
{
char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
TreeNode* T;
TreeNode* pre = NULL;
int index = 0;
createTree(&T, arry, &index, NULL);
postThreadTree(T, &pre);
cout << "后序遍历:";
for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node))
{
visit(node);
}
cout << endl;
}