2024王道408数据结构P144 T18
思考过程
首先还是先看题目的意思,让我们在中序线索二叉树里查找指定结点在后序的前驱结点,这题有一点难至少对我来说…我讲的不清楚理解一下我做的也有点糊涂。 在创建结构体时多两个变量ltag和rtag,当ltag=0时就说明该结点有左孩子,当ltag=1时说明该结点的lchild指向它的前驱结点 。 那么我们需要把一个二叉树给中序线索化,线索化后假设有这么一颗二叉树 之后要查找指定结点在后序的前驱结点有这么五种情况,假设指定结点为指针p:
如果p有右孩子,那么在后序的前驱结点也就是该结点的右孩子 ,if(p->rtag==0)
从上面那个二叉树来看很明显。如果p没有右孩子但是有左孩子,那么在后序的前驱结点也就是改结点的左孩子 ,if(p->ltag==0)
比如上图的结点B,当B没有右孩子但是有左孩子时,在后序序列中的前驱结点也就是它的左孩子D。如果p是中序遍历中的第一个结点的话,那么在后序遍历中也必定是第一个结点 ,if (p->lchild==NULL)
这时候也就说明该结点没有前驱结点,我们直接q=NULL就好了。第四种情况就是该结点没有左右孩子,比如下图这种情况 这棵树中的C结点就是没有左右孩子的,此时它在后序序列中的前驱结点就是先要找到该结点的祖先, while (p->ltag == 1 && p->lchild != NULL) p = p->lchild;
找到祖先后那也就是该祖先结点的左孩子。if (p->ltag == 0) q = p->lchild;
那最后一种情况就是一棵树中既没有左孩子也没有右孩子,只有一个孤零零的结点,此时也就是q=NULL;
了
完整代码
# include "iostream"
using namespace std;
typedef struct TreeNode
{
char data;
struct TreeNode * lchild, * rchild;
int ltag, rtag;
} * tree;
void CreateTree ( tree & t)
{
char ch = getchar ( ) ;
if ( ch == '#' )
t = NULL ;
else
{
t = ( struct TreeNode * ) malloc ( sizeof ( struct TreeNode ) ) ;
t-> data = ch;
t-> lchild = NULL ;
t-> rchild = NULL ;
t-> ltag = t-> rtag = 0 ;
CreateTree ( t-> lchild) ;
CreateTree ( t-> rchild) ;
}
}
struct TreeNode * pre;
void zx ( tree & t)
{
if ( t)
{
zx ( t-> lchild) ;
if ( t-> lchild == NULL )
{
t-> ltag = 1 ;
t-> lchild = pre;
}
else
t-> ltag = 0 ;
if ( pre != NULL && pre-> rchild == NULL )
{
pre-> rtag = 1 ;
pre-> rchild = t;
}
pre = t;
zx ( t-> rchild) ;
}
}
tree Inpostpre ( tree & t, struct TreeNode * p)
{
struct TreeNode * q;
if ( p-> rtag == 0 )
q = p-> rchild;
else if ( p-> ltag == 0 )
q = p-> lchild;
else if ( p-> lchild == NULL )
q = NULL ;
else
{
while ( p-> ltag == 1 && p-> lchild != NULL )
p = p-> lchild;
if ( p-> ltag == 0 )
q = p-> lchild;
else
q = NULL ;
}
return q;
}
int main ( )
{
tree t;
CreateTree ( t) ;
zx ( t) ;
printf ( "%c " , Inpostpre ( t, t-> rchild) -> data) ;
return 0 ;
}