【剑指offer】面试题25:二叉树中和为某一值的路径

本文介绍了如何通过先序遍历和栈数据结构,解决二叉树中查找路径和为特定值的问题。通过递归遍历二叉树,每当路径和匹配目标值时,输出路径并使用栈保存路径信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目描述:

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。



题目解析:

首先,养成画图的习惯。我们可以用下图来分析,要求和为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,进行递归。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值