还是某影音题,第二次笔试只要求非递归实现后序就行了。这题在《编程之美》上有原题,当初过了一遍,没放心上。今天再来做,就把书上的例子搬上来吧。
思路:根据先序和中序重建树,再遍历。首先,求出根节点左右子树,此时,左右子树的先序和中序同样已知,完成递归。
代码实现:
/* 给定前序和中序遍历,求后序遍历 */
typedef struct TreeNode
{
char value;
struct TreeNode *lchild;
struct TreeNode *rchild;
}TNode;
void ReBuild(char *PreOrder, char *InOrder, int TreeLen, TNode **Root)
{
int TempLen = 0;
int LeftLen = 0;
int RightLen = 0;
char *OrgInOrder = NULL;
char *LeftEnd = NULL;
TNode *TempNode = NULL;
if (NULL == PreOrder || NULL == InOrder)
{
return;
}
TempNode = (TNode *)malloc(sizeof(TNode));
TempNode->value = *PreOrder;
TempNode->lchild = NULL;
TempNode->rchild = NULL;
if (NULL == *Root)
{
*Root = TempNode;
}
OrgInOrder = InOrder;
LeftEnd = InOrder;
while (*PreOrder != *LeftEnd) //据先序,求中序根节点左子树长度
{
if (NULL == PreOrder || NULL == InOrder)
{
return;
}
TempLen++;
if (TempLen > TreeLen)
{
break;
}
LeftEnd++;
}
LeftLen = (int)(LeftEnd - OrgInOrder);
RightLen = TreeLen - LeftLen - 1;
//递归实现重建子树
if (LeftLen > 0)
{
ReBuild(PreOrder+1, InOrder, LeftLen, &((*Root)->lchild));
}
if (RightLen > 0)
{
ReBuild(PreOrder+LeftLen+1, InOrder+LeftLen+1, RightLen, &((*Root)->rchild));
}
}
/* 后序非递归实现,思路框架 */
void Traverse(TNode *Root)
{
TNode *TempNode;
Stack *S;
//建栈并初始化
TempNode = Root;
while (NULL != TempNode || !IsEmpty(S))
{
while (NULL != TempNode)
{
//入栈, 栈节点包含: 树节点,遍历标志位(此处标记第一次遍历)
TempNode = TempNode->lchild;
}
if (!IsEmpty(S))
{
//TempNode出栈
if (/* 标志位为第一次遍历 */)
{
//标志位记第二次遍历
//再次入栈
TempNode = TempNode->rchild
}
else
{
printf("%c ", TempNode->value);
}
}
}
}