知道二叉树的前序遍历和中序遍历重建二叉树
知道二叉树的前序遍历和中序遍历,可以唯一确定一颗二叉树,在实现的细节是判断当前结点是否 存在左子树和右子树,比如下面一棵二叉树包含了所有情况
前序遍历为:A BCD EFGH
中序遍历为:CDB A FEHG
先是前序遍历的第一个结点为根节点A, BCD为左子树,EFGH为右子树,依次类推分解左右子树。但怎么判断是否有左子树或者右子树呢,
第一种情况,必有左子树,此时又可分为是否有右子树
1.有右子树
以结点A为例子
前序遍历为:A BCD EFGH
中序遍历为:CDB A FEHG
先得找到中序遍历中A的位置,然后与前序遍历的位置比较,如果不重叠就说明A必有左子树,因为在中序遍历中,出现在自己面前的必是左子树,然后A中中序遍历中不是最后一个结点,所以必有右子树
2.没有右子树
以结点D为例子
当分解到G时
前序遍历为GH
后续遍历为HG
因为G位置不重叠,但是G在中序遍历中已经是最后一个结点,所以没有右子树
再比如B结点
前序遍历为BCD
中序遍历为CDB
第二种情况只有右子树
以结点C为例子
前序遍历为CD
中序遍历为CD
因为C的位置重叠了,所以可能有右子树,但是因为C后面还有一个结点,所以C必有右子树
第三种情况左右子树都没有
以结点D为例子
前序和中序都只有一个结点D,当然没有左右子树了
总结:理解上面三种情况后就行了,还有一个细节是确定当前结点前序中中序遍历结点的过程,我利用递归的思想,先确定函数入口,当前结点P,以P为分界点,传入此时P子树的前序和中序遍历的数组,比如第一个点是A,那么前序遍历是ABCEFGH,中序遍历为:CDB A FEHG, 然后再递归调用,如果有左子树就传入P-.>lchild,然后接着是了child的前序遍历和中序遍历比如B,前序遍历为BCD,中序遍历为CDB,然后在判断P又没有右子树,再调用自身传入P->rchild,以此类推。难点在判断当前结点是否存在左右子树,然后是确定当前结点下的前序和中序的遍历数组,下面看具体实现
#include <iostream> using namespace std; typedef struct node { int data; struct node *l; struct node *r; }node; int pre[1000], mid[1000], n; int find_pos(int arr[], int data, int n) //找到当前结点在中序遍历数组 中的位置 { int i = 0; for (; i < n; i++) { if (arr[i] == data) return i; } return -1; } void built(node &p, int pre[], int mid[], int n) { p.data = pre[0]; p.l = NULL; p.r = NULL; if (n == 1) //叶子结点 return; int i = 0; int j = 0; j = find_pos(mid, pre[0], n); if (i < j) //必有左子树,未必有右子树 { p.l = (node *) malloc(sizeof(node)); built(*p.l, &pre[1], &mid[0], j); if (j != n-1) //必有右子树 { p.r = (node *) malloc(sizeof(node)); built(*p.r, &pre[j+1], &mid[j+1], n-j-1); } } else //只有右子树 { p.r = (node *) malloc(sizeof(node)); built(*p.r, &pre[1], &mid[1], n-1); } } void print_pre(node *p) //前序遍历 { if (!p) return; cout<<p->data<<" "; print_pre(p->l); print_pre(p->r); } void print_mid(node *p) //中序遍历 { if (!p) return; print_mid(p->l); cout<<p->data<<" "; print_mid(p->r); } void print_post(node *p) //后续遍历 { if (!p) return; print_post(p->l); print_post(p->r); cout<<p->data<<" "; } void destroy(node *p) //销毁链表 { node *l,*r; if (!p) return; l = p->l; r = p->r; if (!l) destroy(l); if (!r) destroy(r); free(p); } int main() { node *root; int i; while(cin>>n) { for (i = 0; i < n; i++) cin>>pre[i]; for (i = 0; i < n; i++) cin>>mid[i]; root = (node *) malloc(sizeof(node)); built(*root, pre, mid, n); print_mid(root); cout<<endl; destroy(root); } return 0; }