EricYang

Tech Spot of Eric

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

zz http://blog.csdn.net/vividonly/article/details/6688327

编程之美3.9:重建二叉树

扩展问题1:如果前序和中序遍历的字母有重复的,那么怎么构造所有可能的解呢?

扩展问题2:如何判断给定的前序遍历和中序遍历的结果是合理的?

 

思路:

问题1:搜索所有可能的情况,并调用扩展问题2的解决方案,判断此情况是否合理(剪枝操作),如果合法,则构造解

问题2:递归判断左右子树是否合理,递归的返回条件是到达叶子节点。

代码及测试情况如下:

  1 /*
  2  * 编程之美重建二叉树,扩展问题1,2
  3  * 扩展问题1:如果前序和中序的字母可能是相同的,怎么重构出所有可能的解?
  4  * 扩展问题2:如何判断给定的前序和中序遍历的结果是合理的?
  5  *
  6  * */
  7 
  8 #include <iostream>
  9 #include <string>
 10 using namespace std;
 11 
 12 struct Node
 13 {
 14         Node *left;
 15         Node *right;
 16         char value;
 17 };
 18 
 19 void pre_travel(Node *p)
 20 {
 21         if(p == NULL)
 22                 return;
 23         cout << p->value << endl;
 24         pre_travel(p->left);
 25         pre_travel(p->right);
 26 }
 27 
 28 
 29 //枚举所有的情况,递归判断是否合法,如果递归到只剩一个叶子节点
 30 //则肯定是合法的
 31 bool isvalid(const char *preorder, const char *inorder, int len)
 32 {
 33         const char *leftend = inorder;
 34 
 35         if(len == 1)
 36                 return true;
 37 
 38         for(int i=0; i<len; i++, leftend++){
 39                 if(*leftend == *preorder){
 40                         int leftlen = leftend - inorder;
 41                         int rightlen = len - leftlen - 1;               
 42 
 43                         bool lres = false, rres = false;
 44                         if(leftlen > 0){
 45                                 lres = isvalid(preorder+1, inorder, leftlen);
 46                         }               
 47                         if(rightlen > 0){
 48                                 rres = isvalid(preorder+leftlen+1, inorder+leftlen+1, rightlen);
 49                         }
 50         
 51                         //如果leftlen和rightlen都大于零,则lres和rres必须都为true,此分割方法才算合法           
 52                         if((leftlen > 0 && rightlen >0 && lres && rres) || 
 53                         (leftlen > 0 && rightlen <=0 && lres) || (left <=0 && rightlen > 0 && rres)){
 54                                 return true;    
 55                         }
 56                 }
 57         }
 58 
 59         return false;   
 60 }
 61 
 62 
 63 //枚举法,在枚举的同时使用isvalid函数,排除非法情况
 64 void rebuild(const char *preorder, const char *inorder, int len, Node **root)
 65 {
 66         if(preorder == NULL || inorder == NULL)
 67                 return;
 68 
 69         if(*root == NULL){
 70                 Node *temp = new Node;
 71                 temp->left = NULL;
 72                 temp->right = NULL;
 73                 temp->value = *preorder;
 74                 *root = temp;
 75         }
 76 
 77         if(len == 1)
 78                 return;
 79 
 80         const char *leftend = inorder;
 81 
 82         for(int i=0; i<len; i++, leftend++){
 83                 if(*leftend == *preorder){
 84                         int leftlen = leftend - inorder;
 85                         int rightlen = len - leftlen - 1;
 86 
 87                         if(leftlen > 0  && rightlen >0){
 88                                 if(isvalid(preorder+1, inorder, leftlen) && isvalid(preorder+leftlen+1, inorder+leftlen+1, rightlen)){
 89                                         rebuild(preorder+1, inorder, leftlen, &((*root)->left));
 90                                         rebuild(preorder+leftlen+1, inorder+leftlen+1, rightlen, &((*root)->right));
 91                                 }
 92                         }else if(leftlen > 0 && rightlen <= 0){
 93                                 if(isvalid(preorder+1, inorder, leftlen))
 94                                         rebuild(preorder+1, inorder, leftlen, &((*root)->left));
 95                         }else if(leftlen <=0 && rightlen >0){
 96                                 if(isvalid(preorder+leftlen+1, inorder+leftlen+1, rightlen))
 97                                         rebuild(preorder+leftlen+1, inorder+leftlen+1, rightlen, &((*root)->right));
 98                         }
 99                         
100                 }
101         }
102 }
103 
104 int main()
105 {
106         string pre1 = "abdefc";
107         string mid1 = "dbfeac";
108 
109         string pre2 = "abdefc";
110         string mid2 = "dcfeab";
111 
112         //有重复的字母
113         string pre3 = "aadcef";
114         string mid3 = "daaecf";
115 
116         bool valid = isvalid(pre1.c_str(), mid1.c_str(), pre1.length());
117         cout << valid << endl;
118 
119         valid = isvalid(pre2.c_str(), mid2.c_str(), pre2.length());
120         cout << valid << endl;
121         
122         valid = isvalid(pre3.c_str(), mid3.c_str(), pre3.length());
123         cout << valid << endl;
124        
125         Node *root = NULL;
126         rebuild(pre3.c_str(), mid3.c_str(), 6, &root);
127         pre_travel(root);
128  
129         return 0;
130 }
posted on 2012-08-12 21:35  Eric-Yang  阅读(372)  评论(0编辑  收藏  举报