题目分析:
前序遍历的顺序是:根节点,左节点,右节点
中序遍历的顺序:左节点,根节点,右节点
假设前序遍历的顺序是:1 2 4 7 3 5 8 9 6
中序遍历的顺序是:4 7 2 1 8 5 9 3 6
1.根据前序遍历的规则,前序遍历的第一个节点一定是根节点。
2.从中序遍历中找到第1步根节点所在的位置,在中序序列中根节点所在位置的左边序列就是二叉树的左子树,右边序列就右子树。
3.假设第2步找到的根节点在中序序列中的第k个位置,那么在前序序列的第[2,k]位置的序列是二叉树的左子树,第[k+1,end]位置的序列是二叉树右子树的序列。
4.根据1,2,3的描述,递归生成左子树和右子树。
题目中最大节点数是1000,如果使用数组,考虑到单侧树,则数组至少需要2^1000的空间。所以使用链式结构存储二叉树的结构。
实现代码如下:
#include<stdio.h> #include<malloc.h> struct Node{ int data; Node *lchild,*rchild; Node(){ lchild=NULL; rchild=NULL; } }node[1010]; int n,cnt; int preorder[1010],inorder[1010]; Node *root=&node[0]; //清空左,右子树的指针 void init(){ int i; for(i=0;i<2020;i++){ node[i].lchild=NULL; node[i].rchild=NULL; } } //根据前序和中序序列生成二叉树 void create(Node *temp,int prest,int preed,int inst,int ined){ int i; if(prest>preed)return; temp->data=preorder[prest]; if(prest==preed)return; int index = -1; //找到根节点在中序序列中的位置 for(i=inst;i<=ined;i++){ if(preorder[prest]==inorder[i]){ index=i; break; } } if(index==-1)return; int distance=index-inst; //只存在左子树的情况 if(index==inst){ temp->rchild=&node[cnt++]; create(temp->rchild,prest+1,preed,inst+1,ined); }else if(index==ined){//只存在右子树的情况 temp->lchild=&node[cnt++]; create(temp->lchild,prest+1,preed,inst,ined-1); }else{ //左右子树都存在 temp->rchild=&node[cnt++]; temp->lchild=&node[cnt++]; create(temp->lchild,prest+1,prest+distance,inst,index-1); create(temp->rchild,prest+distance+1,preed,index+1,ined); } } //打印二叉树后序遍历的序列 void print(Node *temp){ if(temp==NULL){ return; } print(temp->lchild); print(temp->rchild); printf("%d",temp->data); if(temp!=root){ printf(" "); } } int main(){ int i; while(scanf("%d",&n)!=EOF){ cnt=1; init(); //获得前序遍历序列 for(i=0;i<n;i++){ scanf("%d",&preorder[i]); } //获得中序遍历序列 for(i=0;i<n;i++){ scanf("%d",&inorder[i]); } create(root,0,n-1,0,n-1); print(root); printf("\n"); } return 0; }