“一个二叉树通过如下的方法“穿起来”:所有原本为空的右(孩子)指针改为指向该节点在中序序列中的后继,所有原本为空的左(孩子)指针改为指向该节点的中序序列的前驱。”[1]
线索二叉树能线性地遍历二叉树,从而比递归的 中序遍历更快。使用线索二叉树也能够方便的找到一个节点的父节点,这比显式地使用父亲节点指针或者栈效率更高。这在栈空间有限,或者无法使用存储父节点的栈时很有作用(对于通过深度优先搜索来查找父节点而言)。 考虑这样的例子:一个节点k有一个右孩子r,那么r的左指针可能是指向一个孩子节点,或是一个指回k的线索。如果r有左孩子,这个左孩子同样也应该有一个左孩子或是指回k的线索。对于所有的左孩子同理。因此沿着这些从r发出的左指针,我们最终会找到一个指回k的线索。这种特性是对称的:当q是p的左孩子时,我们可以沿着q的右孩子找到一个指回p的线索。
传统的二叉树一般都是以链式存储的结构来表示。这样,二叉树中的每个节点都可以用链表中的一个链节点来存储,每个链节点就包含了若干个指针。但是,这种传统的链式存储结构只能表现出二叉树中节点之间的父子关系,而且不能利用空余的指针来直接得到某个节点的在特定的遍历顺序(先序,中序,后序)中的直接前驱和直接后继。通过分析传统的二叉树链式存储结构表示的二叉树中,存在大量的空闲指针。若能利用这些空指针域来存放指向该节点的直接前驱或是直接后继的指针,则可以进行某些更方便的运算。这些被重新利用起来的空指针就被称为线索,加上了这些线索的二叉树就是线索二叉树。
话不多说直接上代码
#include <iostream>
#include<stack>
#include<queue>
using namespace std;
struct Treenode
{
char val;
Treenode *left;
Treenode *right;
int lflag=0;
int rflag=0;
Treenode(char pval,Treenode* pleft=NULL,Treenode *pright =NULL):val(pval),left(pleft),right(pright)
{};
};
Treenode *pre;
void Threadtree(Treenode* roof)//线索化树
{
if (roof)
{
Threadtree(roof->left);//将左孩子线索化
if (!roof->left)
{
roof->lflag = 1;
roof->left = pre;
}
if (!pre->right)
{
pre->rflag = 1;
pre->right = roof;
}
pre = roof;
Threadtree(roof->right);//将右孩子线索化
}
}
void InOrderthread(Treenode* &Thrt, Treenode* roof)
{
Thrt = new Treenode(0, NULL, NULL);
Thrt->lflag = 0;
Thrt->rflag = 1;
Thrt->right = Thrt;
if (!roof)
{
Thrt->left = Thrt;
}
else
{
Thrt->left = roof;
pre = Thrt;
Threadtree(roof);
pre->right = Thrt;
pre->rflag = 1;
Thrt->right = pre;
}
}
Treenode *Prenode(Treenode *node)//寻找任意一个节点的前驱节点
{
Treenode *pre;
pre=node->left;
if(node->lflag==0)
{
while(pre->rflag==0)
{
pre=pre->right;
}
}
return pre;
}
Treenode *Nextnode(Treenode *node)//寻找任意一个节点的后继节点
{
Treenode *next;
next=node->right;
if(node->rflag==0)
{
while(next->lflag==0)
{
next=next->left;
}
}
return next;
}
//根据前驱节点来进行中序遍历
void FindPre(Treenode *head)
{
Treenode *curnode;
curnode=head->right;
while(curnode->rflag==0)
{
curnode=curnode->right;
}
while(curnode&&curnode!=head)
{
cout<<curnode->val<<" ";
curnode=Prenode(curnode);
}
}
//根据后继节点来进行中序遍历
void FindNext(Treenode *roof)
{
Treenode *curnode;
curnode=roof->left;
while(curnode->lflag==0)
{
curnode=curnode->left;
}
while(curnode&&curnode!=roof)
{
cout<<curnode->val<<" ";
curnode=Nextnode(curnode);
}
}
void createTree(Treenode* &head)//值得注意的是这里生成树是用前序遍历的方法
{
char c;
cin >> c;
if ('#' == c)
{
head = NULL;
}
else
{
head = new Treenode(c);
createTree(head->left);
createTree(head->right);
}
}
void predisplay(Treenode* head)
{
if (head)
{
cout << head->val << " ";
predisplay(head->left);
predisplay(head->right);
}
}
int main()
{
InOrderthread(head,roof);
FindPre(head);
cout << endl;
FindNext(head);
return 0;
}