机试算法讲解: 第16题 练练你的推理:前序和中序,你能推出后序吗?

来源:互联网 发布:淘宝app功能介绍 编辑:程序博客网 时间:2024/06/08 19:32
/*利用前序和中序,求后续遍历结果输入:FDXEAG(前序)XDE F AG(中序):例如找到F=3(i),则前序的左子树遍历范围是:s1+1到s1+3(i),右子树遍历范围是:s1+3(i)+1到e1输出:XEDGAF(后序)关键:1前序要划分,中序也要划分,前序划分长度为iRootIdx-s2,而中序就是以iRootIdx进行左右划分2每次划分得到的是一个节点的指针3最后用后续遍历打印即可4需要判断左子树不空,递归遍历左子树,得到的是左子树的指针5进行测试数组长度的时候用strlen,它返回实际长度,sizeof返回申请长度6 //getOrder(sFront,sMid,s1 + 1,s1 + (iRootIdx - s2),s2,s2 + iRootIdx - 1);,得到的是左子树的指针,并且得到的中序是不需要加上s2作为基底*/#include <stdio.h>#include <string.h>#include <queue>using namespace std;//typedef struct Nodetypedef struct Node{Node* lchild;Node* rchild;char cNodeName;}Node;Node Tree[50];//}Node;int loc;//易错:静态数组中已经分配的节点个数//后续遍历void backOrder(Node* T){if(NULL!=T->lchild){backOrder(T->lchild);}if(NULL!=T->rchild){backOrder(T->rchild);}printf("%c",T->cNodeName);}//后续遍历void levelOrder(Node* T){queue<Node*> queueNode;queueNode.push(T);while(!queueNode.empty()){Node* node = queueNode.front();queueNode.pop();if(NULL!=node->lchild){queueNode.push(node->lchild);}if(NULL!=node->rchild){queueNode.push(node->rchild);}printf("%c",node->cNodeName);}}//创建新节点Node* createNode(){//Tree[loc]->lchild = NULL;//lchild是成员变量,因此用Tree[loc].lchild//Tree[loc]->rchild = NULL;//Tree[loc]->cNodeName = ;//节点名无法设置,返回的指针肯定是取地址Tree[loc].lchild = Tree[loc].rchild = NULL;return &Tree[loc++];//注意返回的时候还需要将loc进行累加}//从前序中寻找根节点在中序中的位置,然后确定左右子树的长度,Node* getOrder(char* sFront,char* sMid,int s1,int e1,int s2,int e2){//需要为根节点申请空间,且他的节点名就是前序第一个字母Node* root = createNode();root->cNodeName = sFront[s1];//寻找前序根节点在中序位置int iRootIdx;//for(int i = s2 ; i < e2 ; i++)//范围应该是在s2与e2之间,且必须能取到e2for(int i = s2 ; i <= e2 ; i++){if(sFront[s1]==sMid[i]){iRootIdx = i;break;}}//易错,如果左子树不空,就递归遍历左子树。左子树为空时:iRootIdx=s2,不空iRootIdx!=s2if(iRootIdx!=s2){//前序要划分成左右2个子序列,中序不需要划分。前序的长度是iRootIdx - s2//getOrder(sFront,sBack,s1+1,s1+iRootIdx,s2,e2);//getOrder(sFront,sMid,s1 + 1,s1 + (iRootIdx - s2),s2,s2 + iRootIdx - 1);,得到的是左子树的指针,并且得到的中序是不需要加上s2作为基底//root->lchild = getOrder(sFront,sMid,s1+1,s1+iRootIdx-s2,s2,s2+iRootIdx-1);root->lchild = getOrder(sFront,sMid,s1+1,s1+iRootIdx-s2,s2,iRootIdx-1);}//如果右子树不空,就递归遍历右子树if(iRootIdx!=e2){//getOrder(sFront,sBack,s1+iRootIdx+1,e1,s2,e2);//getOrder(sFront,sMid,s1 + (iRootIdx - s2) + 1,e1,s2 + iRootIdx + 1,e2);//root->rchild = getOrder(sFront,sMid,s1+iRootIdx-s2+1,e1,s2+iRootIdx+1,e2);root->rchild = getOrder(sFront,sMid,s1+iRootIdx-s2+1,e1,iRootIdx+1,e2);}return root;}void process(){char sFront[27],sMid[27];while(EOF!=scanf("%s",sFront)){scanf("%s",sMid);//strlen与sizeof的区别,strlen是有多少算多少实际,sizeof是你申请//getOrder(sFront,sMid,0,sizeof(sFront)-1,sizeof(SMid)-1);Node* T = getOrder(sFront,sMid,0,strlen(sFront)-1,0,strlen(sMid)-1);backOrder(T);//levelOrder(T);printf("\n");}}void process2(){char sFront[27],sMid[27];int iCaseNum;while(EOF!=scanf("%d",&iCaseNum)){for(int i = 0 ; i < iCaseNum ; i++){scanf("%s %s",sFront,sMid);Node* T = getOrder(sFront,sMid,0,strlen(sFront)-1,0,strlen(sMid)-1);levelOrder(T);printf("\n");}}}int main(int argc,char* argv[]){process2();getchar();return 0;}

0 0
原创粉丝点击