数据结构和算法经典100题-第4题

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


题目分析

  1. 可以看到在一棵二元树的各个路径上遍历。由于都是先访问各子树的根节点,所以确定是前序遍历;
  2. 由于输出要求中要求输出路径上值的和为输入值的各个结点上的值,所以自然联想到这是一个栈结构;
  3. 确定是栈结构和前序遍历后,自然而然会想到要用到递归;
  4. 递归的两个关键因素就是递归条件和返回;
  5. 由于是一棵二叉树的前序遍历,那么递归条件自然就是左右子树非空;
  6. 返回之前要处理的就是栈上的缓存值。

头文件:

  • 定义二叉树结点的基本结构;
  • 定义二叉树:其中traverse方法提供给用户调用;

//
//  4th.h
//  100-alg-tests
//
//  Created by bobkentt on 15-3-24.
//  Copyright (c) 2015年 bobkentt . All rights reserved.
//

#ifndef ___00_alg_tests___th__
#define ___00_alg_tests___th__

#include <stdio.h>
#include <vector>

class binaryTreeNode {
    int m_value;
    binaryTreeNode * m_left;
    binaryTreeNode * m_right;
public:
    binaryTreeNode(int value) : m_value(value), m_left(NULL), m_right(NULL) {}
    ~binaryTreeNode() {};

    int getValue() { returnm_value; };
    binaryTreeNode * getLeft() { returnm_left; };
    binaryTreeNode * getRight() { returnm_right; };

    /* Set the left value of the node */
    void setLeft(binaryTreeNode * left) { m_left = left; return;}

    /* Set the right value of the node */
    void setRight(binaryTreeNode * right) {m_right = right; return;}
};

class binaryTree {
    int m_value;                               /* 用户输入值. */
    int m_sum;                                 /* 当前路径各结点值的和. */
    std::vector<int> m_stack;                  /* 存储当前路径上各结点的值. */
    binaryTreeNode * m_root;                   /* 二叉树的根结点. */
    void traverseTree(binaryTreeNode * node);  /* 遍历二叉树. */
public:
    binaryTree(int value);

    ~binaryTree();

    /* Methold for traverse the binaryTree. */
    void traverse();
};


#endif /* defined(___00_alg_tests___th__) */

定义二叉树的方法:


// 定义二叉树的方法:
//
//  4th.cpp
//  100-alg-tests
//
//  Created by bobkentt on 15-3-24.
//  Copyright (c) 2015年 bobkentt. All rights reserved.
//
#include <iostream>
#include "4th.h"

usingnamespacestd;

binaryTreeNode * node_5 = newbinaryTreeNode(5);
binaryTreeNode * node_12 = newbinaryTreeNode(12);
binaryTreeNode * node_4 = newbinaryTreeNode(4);
binaryTreeNode * node_7 = newbinaryTreeNode(7);

/* 为方便测试在此构造了一棵二叉树 */
binaryTree::binaryTree(int value) {
    m_value = value;
    m_sum = 0;
    m_root = newbinaryTreeNode(10);
    m_root->setLeft(node_5);
    m_root->setRight(node_12);
    node_5->setLeft(node_4);
    node_5->setRight(node_7);

};

binaryTree::~binaryTree() {
#define delete_t(a)   do { if (NULL != (a)) { delete (a); (a) = NULL; } } while(0)
    delete_t(m_root);
    delete_t(node_5);
    delete_t(node_7);
    delete_t(node_4);
    delete_t(node_12);
}

/*
 4.在二元树中找出和为某一值的所有路径
 题目:输入一个整数和一棵二元树。
 从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
 打印出和与输入整数相等的所有路径。
 例如输入整数 22 和如下二元树
 10
 / \
 5 12
 / \
 4 7
 则打印出两条路径:10, 12 和 10, 5, 7。
 */
voidbinaryTree:: traverseTree(binaryTreeNode * node) {
    if (NULL == node) {
        return;
    }
    bool isLeafNode = (NULL == node->getLeft() && NULL == node->getRight()) ? true : false;
    int currentSum = m_sum + node->getValue();
#if 0
    cout<<"isLeafNode "<<isLeafNode<<" m_sum "<<m_sum<<" currentSum = "<<currentSum<<endl;
    printf("stack:");
    for (int i = 0; i < (int)m_stack.size(); i++) {
        printf("%d ",m_stack[i]);
    }
    printf("\n");
#endif
    /* 这是一个递归方法,主要逻辑:
     * 1.若当前累加值小于输入值,且是页结点则返回其父结点。
     * 不是页结点则依次遍历其左右子树;
     * 2.若当前累加值等于输入值,则输出;
     * 3.若当前值累加值超过输入值,则返回其父结点。
     */
    //printf(" come %d\n",node->getValue());
    if (currentSum < m_value) {
        if (isLeafNode) {
            return;
        }

        m_sum = currentSum;
        m_stack.push_back(node->getValue());

        if (NULL != node->getLeft()) {
            traverseTree(node->getLeft());
        }
        if (NULL != node->getRight()) {
            traverseTree(node->getRight());
        }

        m_stack.pop_back();

    } elseif (currentSum == m_value) {
        m_stack.push_back(node->getValue());
        printf("Output values num(%d): ",(int)m_stack.size());
        for (int i = 0; i < (int)m_stack.size(); i++) {
            printf("%d ",m_stack[i]);
        }
        printf("\n");

        m_stack.pop_back();
        m_sum = m_sum - m_stack.back();
    }

    return;

}

voidbinaryTree::traverse() {
    traverseTree(m_root);
    return;
}

测试程序:


//
//  main.cpp
//  100-alg-tests
//
//  Created by bobkentt on 15-3-24.
//  Copyright (c) 2015年 kedong. All rights reserved.
//

#include <iostream>

#include "4th.h"

int test_4() {
    binaryTree * obj = newbinaryTree(22);

    obj->traverse();

    if (NULL != obj) {
        delete obj;
    }
    obj = NULL;

    return0;
}

int main(int argc, constchar * argv[]) {
    test_4();
    return 0;
}

测试结果及屏幕打印:


屏幕打印输出:
Output values num(3): 10 5 7
Output values num(2): 10 12
Program ended with exit code: 0


路漫漫其修远兮,吾将上下而求索…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值