题目描述:
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
题目解析:
首先,养成画图的习惯。我们可以用下图来分析,要求和为22的路径。
那么输出有10、5、7和10、12。访问一个二叉树,找路径等问题,均涉及到对树进行遍历。根据该题意,我们要求一个从根开始的路径,那么肯定要用先序遍历来实现。既然要输出一个路径信息,就要有保存遍历过程中的根结点的信息:当遍历10、5后,然后遍历4,已经到达叶节点但不满足,就要删除4遍历7;当遍历过7以后,5这个结点算是遍历完整,这时就要遍历12。根据这个过程,满足后进先出的特点,所以用栈来实现其功能。
完整代码如下:
/*题目的要求是从根节点到叶节点一条完整的路径上的节点和等于要查询的值,则返回
但是我写的只要遍历的过程中满足了根节点到该节点的路径上之和等于查询的值,就输出;不一定非要遍历到叶节点
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
int g_Find = 0;
typedef struct BiTNode{
int data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{
int *base;
int *top;
}SqStack;
void CreateBiTree(BiTree *T);
void FindPath(BiTree T,SqStack *S,int n);
void StackTraverse(SqStack *S);
void InitStack(SqStack *S);
void Push(SqStack *S,int e);
void Pop(SqStack *S);
void DestoryBiTree(BiTree *T);
int main(void)
{
int n;
BiTree head;
SqStack stack;
InitStack(&stack);
printf("please input the number you want search:");
while(scanf("%d",&n) == 1){
g_Find = 0; //定义全局变量,判断是否找到路径
printf("input the bitree:");
CreateBiTree(&head);
FindPath(head,&stack,n);
if(!g_Find)
printf("FALSE!\n");
DestoryBiTree(&head);
printf("\nplease input the number you want search:");
}
return 0;
}
void CreateBiTree(BiTree *T)
{
int n;
scanf("%d",&n);
if(n == 0)
*T = NULL;
else{
*T = (BiTree)malloc(sizeof(BiTNode));
if(!*T)
exit(-1);
(*T)->data = n;
CreateBiTree(&((*T)->lchild));
CreateBiTree(&((*T)->rchild));
}
}
void FindPath(BiTree T,SqStack *S,int n)
{
if(!T || T->data > n) //如果传入指针和数据不符合,直接退出
return ;
if(n < 0)
return ;
if(T->data == n){ //如果得到了想要的数组和,就遍历栈,并返回
g_Find = 1;
Push(S,T->data);
StackTraverse(S);
Pop(S);
}else{ //由于上面已经判断了T->data > n,所以这里进入else的知识T->data < n
Push(S,T->data); //其实是先序遍历
FindPath(T->lchild,S,n - T->data); //递归遍历左右子树
FindPath(T->rchild,S,n - T->data);
Pop(S); //当遍历完该节点后退出,有右兄弟的话,返回后遍历右兄弟
}
}
void StackTraverse(SqStack *S)
{
int *p = S->base;
while(p < S->top){
printf("%d ",*p);
++p;
}
printf("\n");
}
void InitStack(SqStack *S)
{
S->base = (int *)malloc(MAXSIZE * sizeof(int));
if(!S->base)
exit(-1);
S->top = S->base;
}
void Push(SqStack *S,int e)
{
if(S->top - S->base >= MAXSIZE)
return ;
*(S->top++) = e;
}
void Pop(SqStack *S)
{
if(S->top == S->base)
return ;
--S->top;
}
void DestoryBiTree(BiTree *T)
{
if(*T){
DestoryBiTree(&((*T)->lchild));
DestoryBiTree(&((*T)->lchild));
*T = NULL;
}
}
总结:
1:要注意题目的鲁棒性,尽量考虑完整的情况。
2:其实这道题与《寻找满足和为定值的两个或多个数》颇有些相似。当我们看到本文这道题,就容易想到,遍历根结点的时候,利用子节点递归时,传入n - T->data。但在求和为定值的多个数这道题的时候,就不容易这么想;这道题当中也是利用遍历,选择i或者不选择i,进行递归。