在学习树中有这样一个问题,如何根据一颗二叉树的先序序列及中序序列确定二叉树,或是根据后序序列和中序序列确定二叉树。(只有先序和后序是无法唯一确定一颗二叉树的)
在网上查资料的时候很少看到将两个合起来写的,但其实其过程有相似性,用结构相似的代码更能体现其算法本质。书中给出了先序加中序的解法,解法的思想是递归,基本上就是模拟人思维解这个问题,重点在于角标的确定。
先序+中序
调用时传入的参数为:先序序列,中序序列,先序起点,先序终点,中序起点,中序终点,下一步的根节点位置
public void reConstructBinaryTreeCore_xianxu(int[] pre, int[] in, int preStart, int preEnd, int inStart, int inEnd,Node tree) { //创建当前节点 tree = new Node(pre[preStart]); int m = inStart; //在中序中定位根 while (in[m] != pre[preStart]){ m++; } //递归建立左子树 if (m == inStart){ tree.leftchild = null; }else { reConstructBinaryTreeCore_xianxu(pre,in,preStart+1,preStart+m-inStart,inStart,m-1,tree.leftchild); } //递归建立右子树 if (m == inEnd){ tree.rightchild = null; }else { reConstructBinaryTreeCore_xianxu(pre,in,preStart+m-inStart+1,preEnd,m+1,inEnd,tree.rightchild); } }
中序加后序
可以看到只有脚标不同,程序结构完全相同,参数意义相同,理解脚标时根据人工过程来模拟就比较好理解
public void reConstructBinaryTreeCore(int[] pre, int[] in, int preStart, int preEnd, int inStart, int inEnd,Node tree) { tree = new Node(pre[preEnd]); int m = inStart; //在中序中定位根 while (in[m] != pre[preEnd]){ m++; } //递归建立左子树 if (m == inStart){ tree.leftchild = null; }else { reConstructBinaryTreeCore(pre,in,preStart,preStart+m-inStart-1,inStart,m-1,tree.leftchild); } //递归建立右子树 if (m == inEnd){ tree.rightchild = null; }else { reConstructBinaryTreeCore(pre,in,preStart+m-inStart,preEnd-1,m+1,inEnd,tree.rightchild); } }
我实现的树的结构如下:
class Node{//节点的数据结构 int data; Node leftchild; Node rightchild; public Node(int num){ this.data = num; this.leftchild = null; this.rightchild = null; } } class mytree_Linkedlist{//树的结构就是一个头指针就够了,没有采用递归的方式定义树 private Node head; public mytree_Linkedlist(){ this.head = null; } ...//后续就是一些方法,详细见我另一篇博客(目前还在写)
正确性通过先序遍历,中序遍历,后续遍历等可以验证。