原理是,比如
先序序列决定二叉树的根结点(比如上图的“1”),后序序列决定二叉树的左右子结点(比如上图的“4”,“7”,“2”为左子树的那部分,而“8”,“5”,“9”,“3”,“6”为右子树的那部分),先看根节点,再看左右子结点。
怎么用呢?
比如左子树那部分
先看先序的数组,因为“1”已经使用了,故遍历到“2”,"2"为左子树的第一个根节点(也是“1”的左子结点),然后看中序数组,先找到“2”,”2“的右边是”1“(”2“的父节点),故”2“只有左子节点部分(”4”,“7“);再遍历先序的数组,遍历到”4“,故”4“为”2“的左子节点,然后看中序数组,”4“只有右边有数,故”7“为”4“的右子树部分,最后看先序序列,遍历到”7“,将”7“设为”4“的右子节点;在此已经将”1“的左边部分解决了!!
C语言代码部分:
#include <stdio.h>
#include <stdlib.h>
int pre[23],in[23];
int k=0;int t=1;
typedef struct binarytree
{int data;struct binarytree *rChild;struct binarytree *lChild;
}binarytree,*tree;
void buildtree(int l,int r,tree *root);
void postorder (tree root);
void buildtree(int l,int r,tree *root)
{int flag=-1;
int i;
for ( i = l; i <=r; i++){if (in[i]==pre[t]){flag=i;break;}}
if(flag==-1) {return ;}
t++;
*root=(binarytree *)malloc(sizeof(binarytree));
(*root)->data=in[i];
(*root)->lChild=NULL;
(*root)->rChild=NULL;
if(flag>l)buildtree(l,flag-1,&((*root)->lChild));
if(flag<r)buildtree(flag+1,r,&((*root)->rChild));}
void postorder (tree root){ //求后序序列if(root){postorder(root->lChild);postorder(root->rChild);printf("%5d",root->data); }
}void preorder (tree root){ //求前序序列if(root){printf("%5d",root->data);postorder(root->lChild);postorder(root->rChild);}
}
int main(){int n;int i;tree root;printf("请输入二叉树的结点数:\n");scanf("%d",&n);//fflush(stdin);printf("请输入二叉树的前序遍历数组的各个值:\n");for ( i = 1; i <=n; i++){scanf("%d",&pre[i]);}//fflush(stdin);printf("请输入二叉树的中序遍历数组的各个值:\n");for ( i = 1; i <=n; i++){ scanf("%d",&in[i]);}printf("后序遍历为:\n");buildtree(1,n,&root);
postorder(root);}
/*对于指针 用来改变值 使用方法:(*变量名)普通变量用来遍历
二叉树在建立时要确保左右子树是否已经为空不然在遍历时会出现bug
*/
我个人觉得这代码难理解的也只有这部分了
第一段正是上面所说的解决左子树部分的,flag是从中序数组查找的与此时需要设置的前序序列数值相等的对应的下标,如果flag<l的话,那么下个节点是右子节点或者空结点,而flag加1是让需要安排的对象向前移,而flag减1是让需要安排的对象向后移。
如果解释的不足或者有误的请各位大佬指出,我也好改正!!
赞赞赞!!