经常有面试题就是知道一棵树的前序遍历和中序遍历让你写出后序遍历,这个慢慢画是能画出来的,但是要很快的弄出来还是要懂原理。
首先说一下三种遍历:所谓的前序后序和中序都是遍历时遍历根节点的顺序。子树的话依照从做左到右的顺序,比如前序就是:中-》左-》右,中序就是:左-》中-》右。
现在前序是:ABDGCEFH
中序是:DGBAECHF
想要求后序就要把树重建出来,我们理一下思路。
1.由前序遍历的性质可以知道A必然是树的根节点
2.中序遍历中A之前的就肯定是A的左子树,A后面的就是A的右子树。
好的,我们现在可以把中序分一下,变成:DGB | A | ECHF
同样左子树和右子树在前序上也是连续的,所以我们可以分成 A | BDG | CEFH
你一定已经想到递归了,对,如果只看左子树的话又当成一个新的树,题目变成已知前序为:BDG,中序为:DGB,求原来的树。右子树同理。
上代码,自己瞎写的。。。。多多包涵
#include <iostream> #include <string> using namespace std; struct Node { char val ; Node *rc , *lc ; } ; Node* rebuild(string pre,string mid) { int i , len ; Node *head = new Node() ; head->val = pre[0] ; //cout << pre<< " " << mid << endl ; len = mid.length() ; for(i=0;i<len;i++) { if(pre[0]==mid[i]) { if(i!=0) { head->lc = rebuild(pre.substr(1,i),mid.substr(0,i));//左子树 } else{ head->lc = NULL ; } if(i!=len-1) { head->rc = rebuild(pre.substr(i+1,len-1-i),mid.substr(i+1,len-1-i));//右子树 } else{ head->rc = NULL ; } } } return head ; } void after(Node *head) { if(head==NULL) { return ; } else{ if(head->lc!=NULL) after(head->lc) ; if(head->rc!=NULL) after(head->rc) ; cout << head->val << endl ; } } int main() { string pre , mid ; Node *head = NULL ; while(cin>>pre>>mid) { Node * head ; head = rebuild(pre,mid) ; after(head) ; } return 0; }
注意substr这个函数的参数的意思是substr(start,length),递归左子树的时候,左子树子串前序和中序的length等于i,并不是到i那个位置结束。
时间: 2024-10-24 23:20:07