2013.10.21 早上八点
问题:二叉树已知先序中序求后序遍历序列问题
问题描述:
已知二叉树的先序遍历
先序遍历:
1.访问根节点
2.前序遍历左子树
3.前序遍历右子树
已知二叉树的中序遍历
中序遍历:
1.中序遍历左子树
2.访问根节点
3.中序遍历右子树
求二叉树的额后序遍历序列:
1.后序遍历左子树
2.后序遍历右子树
3.访问根节点
比如:输入的先序序列为:” GDAFEMHZ”,中序序列为:” ADEFGHMZ”,其后序遍历序列为”AEFDHZMG”
大致思路:
1 二叉树的遍历
前序遍历:先遍历根节点,然后遍历左子树,然后遍历右子树
中序遍历:先遍历左子树,然后遍历根节点,然后遍历右子树
后序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点
举例如下:
前序遍历:a b d e c f g 中序遍历:d b e ag f c 后序遍历:d e b g f c a
2 已知两种遍历序列求第三种遍历序列
<1>已知前序和中序求后序遍历
拿上图举例根据前序序列:a b d e c f g 中序序列:d b e ag f c 由于前序序列先访问根节点,所以先序
序列的第一个就是二叉树的根节点,然后看中序序列中根节点a,他的左半部分(dbe)为他的左子树,(gfc)为他
的右子树。前序序列第二个访问b,中序序列可以判定出d为b的左子树,e为b的右子树。根据前序序列知道c为根节
点,根据中序得知c没右子树,只含左子树。同理最后可判定f为根节点,g为其左子树。至此可得出二叉树的图,
正如上图所示。即可写出后序序列:d e b g f c
<2>已知前序和后序求中序遍历
这样是不能得到一个唯一的二叉树出来滴举例如下:
树A:有结点1,2,3,2是1的左孩子,3是2的右孩子
树B:有结点1,2,3,2是1的右孩子,3是2的左孩子
则A,B的前序都是123,后序都是321,但A的中序是231,B的中序是132
<3>已知中序序列和后序序列求先序序列
依旧拿上图举例,已知中序序列:d b e a g f c 后序序列:d e b g f c a。由后序遍历序列定义得知最后一个
节点a必是树的根节点,由中序序列得知左子树(dbe),右子树(gfc),由后序序列倒数第二个为c,得知右子树根
节点为c,再由中序序列可判断出c只含左子树,由后序倒数第三个f判断出f为根节点,再由中序判断出f含左孩子
g。同理可依次判断左半部分(dbe)。至此可画出二叉树。
代码:(已知先序中序求后序) 参考至:http://functionghw.is-programmer.com/posts/38896.html
#ifndef_PREIN2POSTORDER_H_
#define_PREIN2POSTPRDER_H_
#include<iostream>
usingnamespace std;
structTreeNode
{
TreeNode* m_pLeft;
TreeNode* m_pRight;
char m_cValue;
};
//按后序遍历的顺利释放树的节点
voiddelete_tree(TreeNode* root)
{
if (root!=NULL)
{
delete_tree(root->m_pLeft);
delete_tree(root->m_pRight);
free(root);
}
}
//输出后序遍历的结果
voidpost_order_print(TreeNode* pNode)
{
if (pNode!=NULL)
{
post_order_print(pNode->m_pLeft);
post_order_print(pNode->m_pRight);
printf("%c",pNode->m_cValue);
}
}
//线性搜索函数,返回val在inorder中的位置
intindex_at_inseq(char* in_order_seq, int len, char val)
{
int i=0;
for (;i<len;++i)
{
if (*(in_order_seq+i)==val)
{
return i;
}
}
return -1;
}
//递归构造二叉树,最后一个参数用于指示构造是否成功
TreeNode*ConstructBTree(char* in_order_seq, char* pre_order_seq, int len, bool*is_success)
{
if (len<=0 || (*is_success)==false) //空树或者构造过程出错
{
return NULL;
}
int root_index=index_at_inseq(in_order_seq,len, *pre_order_seq);
if (root_index<0) //根节点的值不匹配,停止构造
{
(*is_success)=false;
fprintf(stderr,"wrongsequences.\n");
return NULL;
}
TreeNode*root=(TreeNode*)malloc(sizeof(TreeNode));
if (root==NULL) //内存不足,无法分配内存
{
(*is_success)=false;
fprintf(stderr,"out ofmemory.\n");
return NULL;
}
root->m_cValue=*pre_order_seq;
int left_subtree_len=root_index;
int rigth_subtree_len=len-(root_index+1);
//左子树
root->m_pLeft=ConstructBTree(in_order_seq,pre_order_seq+1,left_subtree_len,is_success);
//右子树
root->m_pRight=ConstructBTree(in_order_seq+root_index+1,pre_order_seq+root_index+1,rigth_subtree_len,is_success);
return root;
}
//使用时应该使用这个函数,如果构造失败,需要清理内存.
TreeNode*GetBTree(char* in_order_seq, char* pre_order_seq, int len)
{
bool is_success=true;
TreeNode*pNode=ConstructBTree(in_order_seq,pre_order_seq,len,&is_success);
if (is_success)
{
return pNode;
}else
{//构造失败,清理已创建节点
delete_tree(pNode);
return NULL;
}
}
int run()
{
char* in_order_seq="ADEFGHMZ";
char* pre_order_seq="GDAFEMHZ";
int len1=strlen(in_order_seq);
int len2=strlen(pre_order_seq);
if (len1!=len2)
{
fprintf(stderr,"the len of thesequences is not equal.\n");
return -1;
}
printf("the preorder is: ");
printf("%s",pre_order_seq);
printf("\n");
printf("the inorder is: ");
printf("%s",in_order_seq);
printf("\n");
TreeNode*TreeRoot=GetBTree(in_order_seq,pre_order_seq,len1);
printf("the postorder is: ");
post_order_print(TreeRoot);
printf("\n");
delete_tree(TreeRoot);
system("pause");
return 0;
}
#endif
样例运行结果:
代码:(已知中序后序求先序) 参考至:http://functionghw.is-programmer.com/posts/38896.html
#ifndef_INPOST2PREORDER_H_
#define_INPOST2PREORDER_H_
#include<iostream>
//#include<stdbool.h> //C99.
usingnamespace std;
typedefstruct TreeNode TreeNode;
structTreeNode {
char val;
TreeNode* left;
TreeNode* right;
};
//按后序遍历顺序释放节点.
voiddelete_tree(TreeNode* root)
{
if (root != NULL)
{
delete_tree(root->left);
delete_tree(root->right);
free(root);
}
}
//输出先序遍历的结果
voidpre_order_print(TreeNode* pNode)
{
if (pNode!=NULL)
{
printf("%c",pNode->val);
pre_order_print(pNode->left);
pre_order_print(pNode->right);
}
}
//一个线性搜索函数,返回val在in_order_seq[len]中的索引.
intindex_at_inseq(char* in_order_seq, int len, char val)
{
int i;
for (i = 0; i < len; ++i)
{
if(*(in_order_seq+i) == val) return i;
}
return -1;
}
//递归构造二叉树,最后一个参数用于指示构造是否成功.
TreeNode*ConstructBTree(char* in_order_seq, char* post_order_seq, int len, bool*is_success)
{
if (len < 1 || (*is_success) == false)//空树或构造过程已经出错.
{
return NULL;
}
int root_index = index_at_inseq(in_order_seq,len, *(post_order_seq+len - 1));
if (root_index < 0)//根节点的值不匹配,停止构造.
{
(*is_success) = false;
fprintf(stderr, "Wrongsequences.\n");
return NULL;
}
TreeNode* root =(TreeNode*)malloc(sizeof(TreeNode));
if (root == NULL)//内存不足.
{
(*is_success) = false;
fprintf(stderr, "Out ofmemory.\n");
return NULL;
}
root->val = *(post_order_seq+len - 1);
int left_subtree_len = root_index;
int right_subtree_len = len -(left_subtree_len + 1);
root->left = ConstructBTree(in_order_seq,
post_order_seq,
left_subtree_len,
is_success);
root->right = ConstructBTree(in_order_seq+ left_subtree_len + 1,
post_order_seq + left_subtree_len,
right_subtree_len,
is_success);
return root;
}
//使用时应该使用这个函数,如果构造失败,需要清理内存.
TreeNode*GetBTree(char* in_seq, char* post_seq, int len)
{
bool is_success = true;
TreeNode* p = ConstructBTree(in_seq,post_seq, len, &is_success);
if (is_success)
{
return p;
}
else
{//构造失败,清理所有已创建的节点.
delete_tree(p);
return NULL;
}
}
int run()
{
char* in_order_seq = "ADEFGHMZ";
char* post_order_seq = "AEFDHZMG";
int len1=strlen(in_order_seq);
int len2=strlen(post_order_seq);
if (len1!=len2)
{
fprintf(stderr,"the len of thesequences is not equal.\n");
return -1;
}
printf("the inorder is: ");
printf("%s",in_order_seq);
printf("\n");
printf("the postorder is: ");
printf("%s",post_order_seq);
printf("\n");
TreeNode* theTree = GetBTree(in_order_seq,post_order_seq, len1);
printf("the preorder is: ");
pre_order_print(theTree);
printf("\n");
delete_tree(theTree);
return 0;
}
#endif
样例运行结果:
问题关键点:掌握先序、中序、后序遍历的特点规律
资料参考至:
http://blog.csdn.net/fansongy/article/details/6798278?reload