您的位置:首页 > 其它

重建二叉树

2013-06-25 16:58 225 查看
/article/5115836.html

中序和后序也能重构------------

前序和后序好像不能重构----没找到资料

已只二叉树的前序和中序遍历,要求构建出完整的二叉树

如前序遍历为:abdcef

中序遍历为:dbaecf

由于前序遍历先访问的是根节点所以整棵树的根节点是a

中序遍历中,先访问左子树,再访问右子树,所以db是左子树,ecf是右子树

如此递归下去,可以找到整棵树的结构

#include<iostream>

#defineTREELEN6

usingnamespacestd;

structNODE{

NODE*pLeft;

NODE*pRight;

charchValue;

};

voidReBuild(char*pPreOrder,char*pInorder,intnTreeLen,NODE**pRoot){

if(pPreOrder==NULL||pInorder==NULL)//两个数组不为空

return;

NODE*pTemp=newNODE;

pTemp->chValue=*pPreOrder;//前序遍历的首节点即时根节点

pTemp->pLeft=NULL;

pTemp->pRight=NULL;

if(*pRoot==NULL)//原来的根节点不存在,就把temp给pRoot

*pRoot=pTemp;

if(nTreeLen==1)//树长为1时,说明已经是最后一个节点

return;

char*pOrgInorder=pInorder;//中序遍历的首地址

char*pLeftEnd=pInorder;//中序遍历的左子树的最后一个元素的地址

intnTempLen=0;

while(*pPreOrder!=*pLeftEnd){//前序的首地址值!=中序左子树的最后一个元素地址就一直循环

if(pPreOrder==NULL||pLeftEnd==NULL)//前序或者左子树的中序最后一个为空时返回

return;

nTempLen++;

if(nTempLen>nTreeLen)

break;

pLeftEnd++;//中序的指针向后移动

}

intnLeftLen=0;

nLeftLen=(int)(pLeftEnd-pOrgInorder);//左子树的长度

intnRightLen=0;

nRightLen=nTreeLen-nLeftLen-1;//右子树的长度

if(nLeftLen>0)//重构左子树

ReBuild(pPreOrder+1,pInorder,nLeftLen,&((*pRoot)->pLeft));

if(nRightLen>0)//重构右子树

ReBuild(pPreOrder+nLeftLen+1,pInorder+nLeftLen+1,nRightLen,&((*pRoot)->pRight));

}

intmain()

{

charszPreOrder[TREELEN]={'a','b','d','c','e','f'};

charszInorder[TREELEN]={'d','b','a','e','c','f'};

NODE*pRoot=NULL;

ReBuild(szPreOrder,szInorder,TREELEN,&pRoot);

cout<<"SUCCESS"<<endl;

return0;

}

程序中边界检查十分重要,与测试用例的选取相互关联

1://3_9重建二叉树.cpp:定义控制台应用程序的入口点。

2://

3:

4:#include"stdafx.h"

5:

6:#include

7:#defineTREELEN6

8:

9:usingnamespacestd;

10:

11:

12:

13:structNode

14:{

15:Node*pLeft;

16:Node*pRight;

17:charchValue;

18:};

19:

20:voidReBuild(char*pPreOrder,

21:char*pInOrder,

22:intnTreeLen,

23:Node**pRoot)//pRoot是一个指向指针的指针

24:{

25:if(pPreOrder==NULL||pInOrder==NULL)

26:{

27:return;

28:}

29:

30://获得前序遍历的第一个节点

31:Node*pTemp=newNode;

32:pTemp->chValue=*pPreOrder;

33:pTemp->pLeft=NULL;

34:pTemp->pRight=NULL;

35:

36://如果根节点为空,把当前节点复制到根节点

37:if(*pRoot==NULL)//如果pRoot指向的根节点指针为NULL

38:{

39:*pRoot=pTemp;

40:}

41:

42://如果当前树长度为1,那么已经是最后一个结点

43:if(nTreeLen==1)

44:{

45:return;

46:}

47:

48://寻找子树长度

49:char*pOrgInOrder=pInOrder;

50:char*pLeftEnd=pInOrder;

51:intnTempLen=0;

52:

53:while(*pPreOrder!=*pLeftEnd)

54:{

55:if(pPreOrder==NULL||pLeftEnd==NULL)

56:{

57:return;

58:}

59:nTempLen++;

60:

61:if(nTempLen>nTreeLen)

62:{

63:break;

64:}

65:

66:pLeftEnd++;

67:}

68:

69:intnLeftLen=0;

70:nLeftLen=(int)(pLeftEnd-pOrgInOrder);

71:

72:intnRightLen=0;

73:nRightLen=nTreeLen-nLeftLen-1;

74:

75:if(nLeftLen>0)

76:{

77:ReBuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->pLeft));

78:}

79:

80:if(nRightLen>0)

81:{

82:ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->pRight));

83:}

84:

85:return;

86:}

87:

88:

89:

90:voidprintInOrder(Node*current)//第一个*解析成Node指针,第二个*把Node指针解析成Node对象

91:{

92:if(current!=NULL)

93:{

94://printInOrder(&((*current)->pLeft));//注意这里的&((*current)->pLeft)

95:

96:printInOrder(current->pLeft);

97:cout<chValue<<"";

98:printInOrder(current->pRight);

99:return;

100:}

101:}

102:

103:voidprintPreOrder(Node*current)

104:{

105:

106:if(current!=NULL)

107:{

108:cout<chValue<<"";

109:printPreOrder(current->pLeft);

110:printPreOrder(current->pRight);

111:return;

112:}

113:}

114:

115:voidprintPostOrder(Node*current)

116:{

117:if(current!=NULL)

118:{

119:printPostOrder(current->pLeft);

120:printPostOrder(current->pRight);

121:cout<chValue<<"";

122:return;

123:}

124:}

125:

126:int_tmain(intargc,_TCHAR*argv[])

127:{

128://charszPreOrder[TREELEN]={'z','b','d','c','e','f'};//非中序遍历结果,结果是错误的

129:

130://原:

131://charszPreOrder[TREELEN]={'a','b','a','e','c','f'};

132://charszInOrder[TREELEN]={'d','b','a','e','c','f'};

133:

134://有重复字符的结点:结果是错误的

135:charszPreOrder[TREELEN]={'a','a','d','e','c','f'};

136:charszInOrder[TREELEN]={'d','a','a','e','c','f'};

137:

138:Node*pRoot=NULL;

139:ReBuild(szPreOrder,szInOrder,TREELEN,&pRoot);

140:

141:cout<<"前序遍历:";

142:printInOrder(pRoot);

143:cout<<endl;<pre="">



144:




145:cout<<"中序遍历:";




146:printPreOrder(pRoot);




147:cout<<endl;<pre="">



148:




149:cout<<"后序遍历:";




150:printPostOrder(pRoot);




151:cout<<endl;<pre="">



152:




153:system("pause");return0;




154:}




155:

</endl;<>

</endl;<>

</endl;<>


栈实现的方式及扩展问题的实现

#include<iostream>

usingnamespacestd;

constintMax=20;

structNode{

Node*pLeft;

Node*pRight;

charchValue;

};

template<classT>

classStack{

public:

Stack(ints=Max):size(s),top(-1){a=newT[size];}

~Stack(){delete[]a;}

voidpush(Tx)

{

if(top<size-1)

a[++top]=x;

}

Tpop()

{

if(top>-1)

returna[top--];

}

TgetT()const

{

if(top!=-1)

returna[top];

}

boolisEmpty()const{returntop==-1;}

boolisFull()const{returntop==(size-1);}

private:

intsize;

inttop;

T*a;

};

voidRebuild(char*pPreOrder,char*pInOrder,intnTreeLen,Node**pRoot)//重建二叉树

{

if(*pRoot==NULL)

{

*pRoot=newNode();

(*pRoot)->chValue=*pPreOrder;

(*pRoot)->pLeft=NULL;

(*pRoot)->pRight=NULL;

}

if(nTreeLen==1)

return;

intnLeftLen=0;

char*InOrder=pInOrder;

while(*pPreOrder!=*InOrder)

{

if(pPreOrder==NULL||InOrder==NULL)

return;

nLeftLen++;

InOrder++;

}

intnRightLen=nTreeLen-nLeftLen-1;

if(nLeftLen>0)

{

Rebuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->pLeft));

}

if(nRightLen>0)

{

Rebuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->pRight));

}

}

voidpreOrder1(Node*root)//递归实现

{

if(root!=NULL)

cout<<root->chValue<<endl;

if(root->pLeft!=NULL)

preOrder1(root->pLeft);

if(root->pRight!=NULL)

preOrder1(root->pRight);

}

voidpreOrder2(Node*root)//非递归用栈实现

{

Stack<Node>stack;

if(root!=NULL)

stack.push(*root);

while(!stack.isEmpty())

{

Node*rNode=&stack.pop();;

cout<<rNode->chValue<<endl;

if(rNode->pLeft!=NULL)

preOrder2(rNode->pLeft);

if(rNode->pRight!=NULL)

preOrder2(rNode->pRight);

}

}

intmain()

{

charpPreOrder[7]="abdcef";

charpInOrder[7]="dbaecf";

intnTreeLen=strlen(pPreOrder);

Node*pRoot=NULL;

Rebuild(pPreOrder,pInOrder,nTreeLen,&pRoot);

preOrder1(pRoot);

//preOrder2(pRoot);//非递归实现

return0;

}

?

/*

*编程之美重建二叉树,扩展问题1,2

*扩展问题1:如果前序和中序的字母可能是相同的,怎么重构出所有可能的解?

*扩展问题2:如何判断给定的前序和中序遍历的结果是合理的?

*问题1思路:搜索所有可能的情况,并调用扩展问题2的解决方案,判断此情况是否合理(剪枝操作),如果合法,则构造解

*问题2思路:递归判断左右子树是否合理,递归的返回条件是到达叶子节点。

*

**/

#include<iostream>

#include<string>

usingnamespacestd;

structNode

{

Node*left;

Node*right;

charvalue;

};

voidpre_travel(Node*p)

{

if(p==NULL)

return;

cout<<p->value<<endl;

pre_travel(p->left);

pre_travel(p->right);

}

//枚举所有的情况,递归判断是否合法,如果递归到只剩一个叶子节点

//则肯定是合法的

boolisvalid(constchar*preorder,constchar*inorder,intlen)

{

constchar*leftend=inorder;

if(len==1)

returntrue;

for(inti=0;i<len;i++,leftend++){

if(*leftend==*preorder){

intleftlen=leftend-inorder;

intrightlen=len-leftlen-1;

boollres=false,rres=false;

if(leftlen>0){

lres=isvalid(preorder+1,inorder,leftlen);

}

if(rightlen>0){

rres=isvalid(preorder+leftlen+1,inorder+leftlen+1,rightlen);

}

//如果leftlen和rightlen都大于零,则lres和rres必须都为true,此分割方法才算合法

if((leftlen>0&&rightlen>0&&lres&&rres)||

(leftlen>0&&rightlen<=0&&lres)||(left<=0&&rightlen>0&&rres)){

returntrue;

}

}

}

returnfalse;

}

//枚举法,在枚举的同时使用isvalid函数,排除非法情况

voidrebuild(constchar*preorder,constchar*inorder,intlen,Node**root)

{

if(preorder==NULL||inorder==NULL)

return;

if(*root==NULL){

Node*temp=newNode;

temp->left=NULL;

temp->right=NULL;

temp->value=*preorder;

*root=temp;

}

if(len==1)

return;

constchar*leftend=inorder;

for(inti=0;i<len;i++,leftend++){

if(*leftend==*preorder){

intleftlen=leftend-inorder;

intrightlen=len-leftlen-1;

if(leftlen>0&&rightlen>0){

if(isvalid(preorder+1,inorder,leftlen)&&isvalid(preorder+leftlen+1,inorder+leftlen+1,rightlen)){

rebuild(preorder+1,inorder,leftlen,&((*root)->left));

rebuild(preorder+leftlen+1,inorder+leftlen+1,rightlen,&((*root)->right));

}

}elseif(leftlen>0&&rightlen<=0){

if(isvalid(preorder+1,inorder,leftlen))

rebuild(preorder+1,inorder,leftlen,&((*root)->left));

}elseif(leftlen<=0&&rightlen>0){

if(isvalid(preorder+leftlen+1,inorder+leftlen+1,rightlen))

rebuild(preorder+leftlen+1,inorder+leftlen+1,rightlen,&((*root)->right));

}

}

}

}

intmain()

{

stringpre1="abdefc";

stringmid1="dbfeac";

stringpre2="abdefc";

stringmid2="dcfeab";

//有重复的字母

stringpre3="aadcef";

stringmid3="daaecf";

boolvalid=isvalid(pre1.c_str(),mid1.c_str(),pre1.length());

cout<<valid<<endl;

valid=isvalid(pre2.c_str(),mid2.c_str(),pre2.length());

cout<<valid<<endl;

valid=isvalid(pre3.c_str(),mid3.c_str(),pre3.length());

cout<<valid<<endl;

Node*root=NULL;

rebuild(pre3.c_str(),mid3.c_str(),6,&root);

pre_travel(root);

return0;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: