文章作者:Slyar 文章来源:Slyar Home (www.slyar.com) 转载请注明,谢谢合作。
今天数据结构课讲树的存储和遍历,老师讲的很简单,也没什么代码要发...唯一看到一个比较重要的东西,总结一下算法好了。
这种题一般有二种形式,共同点是都已知中序序列。如果没有中序序列,是无法唯一确定一棵树的,证明略。
一、已知二叉树的前序序列和中序序列,求解树。
1、确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素。
2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。
3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。
二、已知二叉树的后序序列和中序序列,求解树。
1、确定树的根。树根是当前树中所有元素在后序遍历中最后出现的元素。
2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。
3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。
举例说明:根据已知求解二叉树
中序序列 BDCEAFHG
后序序列 DECBHGFA
1、BDCEAFHG在后序序列中最后出现的元素为A,BDCE|A|FHG
2、BDCE在后序序列中最后出现的元素为B,|B|DCE|A|FHG
3、FHG在后序序列中最后出现的元素为F,|B|DCE|A||F|HG
4、DCE在后序序列中最后出现的元素为C,|B|D|C|E|A||F|HG
5、HG在后序序列中最后出现的元素为G,|B|D|C|E|A||F|H|G|
6、所有元素都已经定位,二叉树求解完成。
A
/ \
B F
\ \
C G
/ \ /
D E H
编程之美上讲解的算法实现
#include <iostream> using namespace std; #define TREELEN 6 struct NODE{ NODE *pLeft; NODE *pRight; char chValue; }; void ReBuild(char *pPreOrder,char *pInOrder,int nTreeLen,NODE** pRoot) { if (pPreOrder == NULL || pInOrder == NULL)//检查边界条件 { return; } NODE* pTemp = new NODE;//获得前序遍历的第一个节点 pTemp->chValue = *pPreOrder; pTemp->pLeft = NULL; pTemp->pRight = NULL; if (*pRoot == NULL)//如果节点为空,就把当前节点复制到根节点 { *pRoot = pTemp; } if (nTreeLen == 1)//如果长度为1,那么已经是最后一个节点 { return; } char *pOrgInorder = pInOrder;//寻找子树的长度 char *pLeftEnd = pInOrder; int nTemplen = 0; while(*pPreOrder!=*pLeftEnd)//找到左子树的结尾 { if (pPreOrder == NULL || pLeftEnd == NULL) { return; } nTemplen++; if (nTemplen > nTreeLen) { break; } pLeftEnd++; } int nLeftLen = 0; nLeftLen = (int)(pLeftEnd - pOrgInorder); int nRighLen = 0; nRighLen = nTreeLen - nLeftLen - 1; if (nLeftLen > 0) { ReBuild(pPreOrder+1,pInOrder,nLeftLen,&(*pRoot)->pLeft); } if (nRighLen > 0) { ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRighLen,&((*pRoot)->pRight)); } } void PreOrderTraverse(NODE **t) { if(!(*t)) return; printf("%c\n",(*t)->chValue); PreOrderTraverse(&((*t)->pLeft)); PreOrderTraverse(&((*t)->pRight)); } int main() { char szPreOrder[TREELEN] = {'a','b','d','c','e','f'}; char szInOrder[TREELEN] = {'d','b','a','e','c','f'}; NODE * pRoot = NULL; ReBuild(szPreOrder,szInOrder,TREELEN,&pRoot); PreOrderTraverse(&(pRoot)); system("pause"); }