在二元树中查找和为某一值的所有路径

百度面试题目:

        输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
        例如输入整数 22 ,如下图二元树:
                                            10
                                           /     \
                                          5     12
                                        /    \   
                                       4     7 

   则打印出两条路径:10, 12和10, 5, 7。

    分析:看到该题目的第一反应是:递归+回溯。首先当然要保存搜索的路径,并记录当前路径上所有元素的和。如果累积和与当前节点值的和大于输入的整数data,则将不进行加法运算,直接回退;如果与当前节点值的和刚好等于sum,且当前节点为叶子节点,则打印该路径,然后回退;如果与当前节点值得和小于data,则继续向下计算……,这样的做法似乎很合理,其实呢?很显然,如果这样做,我们就为问题添加了一个条件:即二元树上的元素值均为正数!!!题目显然没有给出这个条件。自然算法就错了……

    正确的做法应该是这样的:首先当然仍要保存搜索的路径,并记录当前路径上所有元素的和sum。如果当前节点为叶子节点,并且当前节点值与sum的和等于data,则满足条件,打印后递归返回到父节点,注意在打印后、递归返回之前要先减去当前节点元素的值;如果当前节点不是叶子节点,则不必判断当前节点值与sum的和是否等于data,继续访问子节点……

    另一种类似的方法不用录当前路径上所有元素的和sum,而是使用期望的和依次减去访问到的节点的值……最后是判断到达叶子节点时期望和是否减为0,其实时类似的……看代码实现:

[html]  view plain copy
  1. #include <stdafx.h>  
  2. #include<stdlib.h>  
  3. #define MAX 20  
  4.   
  5. struct BiTreeNode  
  6. {  
  7.     int data;  
  8.     struct BiTreeNode *left;  
  9.     struct BiTreeNode *right;  
  10. };  
  11.   
  12. /*递归创建二叉排序树,以'-1'结束*/  
  13. BiTreeNode * CreateBSTree(int *data,int pos,int len)  
  14. {  
  15.     BiTreeNode * tr;  
  16.     if(pos>=len)  
  17.     {  
  18.         return NULL;  
  19.     }  
  20.     else  
  21.     {  
  22.         tr = (BiTreeNode *)malloc(sizeof(BiTreeNode));  
  23.         tr->data=data[pos];  
  24.         tr->left = CreateBSTree(data,2*pos+1,len);  
  25.         tr->right = CreateBSTree(data,2*pos+2,len);    
  26.           
  27.         return tr;  
  28.     }  
  29. }  
  30.   
  31. //中序遍历二叉树  
  32. void InOrderTraverse(BiTreeNode * root)  
  33. {  
  34.     if(root!=NULL)  
  35.     {  
  36.         InOrderTraverse(root->left);   
  37.         printf("%d  ",root->data);  
  38.         InOrderTraverse(root->right);  
  39.     }  
  40. }  
  41.   
  42. //打印路径  
  43. void printPath(int path[],int top)  
  44. {  
  45.     printf("第一组:");  
  46.     for(int i=0;i<top;i++)  
  47.         printf("%d ",path[i]);  
  48.     printf("\n");  
  49. }  
  50.   
  51. //查找和为sum的路径,path数组存放路径的值,top代表每个可行的路径中的元素个数  
  52. void findPath(BiTreeNode *root, int sum,int top,int path[])  
  53. {  
  54.     path[top++] = root->data;  
  55.     sum -root->data;  
  56.       
  57.     if (root->left == NULL && root->right==NULL)   
  58.     {  
  59.         if (sum == 0)   
  60.         {  
  61.             printPath(path, top);  
  62.         }  
  63.     }   
  64.     else   
  65.     {  
  66.         if (root->left != NULL)   
  67.             findPath(root->left, sum, top,path);  
  68.         if (root->right!=NULL)   
  69.             findPath(root->right, sum, top,path);  
  70.     }  
  71.     top --;  
  72.     sum += root->data;  
  73. }  
  74.   
  75. int main()  
  76. {  
  77.     int data[]={1,2,3,1,2,3,2,1,3,2,1,2,1,2,1};  
  78.     int len=sizeof(data)/sizeof(int);  
  79.   
  80.     BiTreeNode * root=CreateBSTree(data,0,len);   
  81.     InOrderTraverse(root);  
  82.     printf("\n");  
  83.       
  84.     int sum=6;  
  85.     int top=0;  
  86.     int path[MAX]={0};  
  87.     findPath(root,sum,top,path);  
  88.       
  89.     return 0;  
  90. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值