C语言强化(四) 求和为某个值的二叉树路径

递归究竟有多强大,看看这道题就知道了。

通过这道题,你可以掌握

  • 如何使用递归
  • 递归的本质
  • 如何跳出递归死循环

题目:输入一个整数和一棵二元树。

从树的【根结点】开始往下访问一直到【叶结点】所经过的所有结点形成一条路径。

打印出和与输入整数相等的所有路径。

例如,输入20和如下二叉树

打印出路径  10 6 4

思路

  • 当访问到某一结点时,把该结点添加到路径上,并累加当前结点的值。
  • 如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求, 我们把它打印出来。
  • 如果当前结点不是叶结点, 则继续访问它的子结点。

对于子结点,我们会发现,要执行的操作跟我们上面三点一模一样!这就是在暗示你,该使用递归啦!

在遍历的时候,我们把一个个结点压入栈中。这就要求我们,在遍历后要让节点出栈,否则函数将永远不能跳出来。

因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是根结点到父结点的路径。

源代码

#include <stdio.h>
#include<stdlib.h>
#include <iostream>
#include<sstream>
#include <VECTOR>

using namespace std;

/**
在二叉树中找出和为某一值的所有路径

题目:输入一个整数和一棵二叉树。
从树的【根结点】开始往下访问一直到【叶结点】所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径

思路
当访问到某一结点时,把该结点添加到路径上,并累加当前结点的值。
如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求, 我
们把它打印出来。
如果当前结点不是叶结点, 则继续访问它的子结点。
因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,
以确保返回父结点时路径刚好是根结点到父结点的路径。
我们不难看出保存路径的数据结构实际上是一个栈结构,因为路径要与递归调用状态一致,
而递归调用本质就是一个压栈和出栈的过程。
*/
struct BinaryTreeNode // a node in the binary tree
{
	int m_nValue; // value of node
	BinaryTreeNode *m_pLeft; // left child of node
	BinaryTreeNode *m_pRight;  // right child of node
};

//求和等于某个值的路径
void findPath(BinaryTreeNode * node,int expectAdd,vector<int> path,int sum){
	if(NULL==node)//结点为空
		return;
	path.push_back(node->m_nValue);
	sum+=node->m_nValue;
	//如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,
	//则当前的路径符合要求,我们把它打印出来。
	if(NULL==node->m_pLeft&&NULL==node->m_pRight&&sum==expectAdd){
		cout<<"找到路径:"<<endl;
		for(int i =0;i<path.size();i++){
			cout<<path[i]<<"  ";
		}
		cout<<endl;
	}
	//如果当前结点不是叶结点, 则继续访问它的子结点。
	if(NULL!=node->m_pLeft)
		findPath(node->m_pLeft,expectAdd,path,sum);
	if(NULL!=node->m_pRight)
		findPath(node->m_pRight,expectAdd,path,sum);

	//在函数退出之前要在路径上删除当前结点并减去当前结点的值,
	//以确保返回父结点时路径刚好是根结点到父结点的路径。
	path.pop_back();
	sum-=node->m_nValue;
}

void main()
{
	//生成二叉树,这里使用一种比较愚蠢的做法,各位同学可以自行设计
	BinaryTreeNode * root=new BinaryTreeNode();
	root->m_pLeft=new BinaryTreeNode();
	root->m_pRight=new BinaryTreeNode();
	root->m_pLeft->m_pLeft=new BinaryTreeNode();
	root->m_pRight->m_pRight=new BinaryTreeNode();
	root->m_nValue=10;
	root->m_pLeft->m_nValue=6;
	root->m_pRight->m_nValue=2;
	root->m_pLeft->m_pLeft->m_nValue=4;
	root->m_pRight->m_pRight->m_nValue=7;

	//设置参数
	int expectAdd = 20;
	vector<int> path;
	int sum=0;
	//寻找路径
	findPath(root,expectAdd,path,sum);

	system("pause");
}

运行

对于递归,记住这么一句话,递归调用本质就是一个压栈和出栈的过程

时间: 2024-10-08 14:43:52

C语言强化(四) 求和为某个值的二叉树路径的相关文章

python3实现在二叉树中找出和为某一值的所有路径

在二叉树中找出和为某一值的所有路径请写一个程序创建一棵二叉树,并按照一定规则,输出二叉树根节点到叶子节点的路径.规则如下:1.从最顶端的根结点,到最下面的叶子节点,计算路径通过的所有节点的和,如果与设置的某一值的相同,那么输出这条路径上的所有节点.2.从根节点遍历树时,请请按照左到右遍历,即优先访问左子树的节点.二叉树创建规则:从上到下一层一层的,按照从左到右的顺序进行构造输入"10,5,12,4,7"值,构造的树如下:1) 102) 10      /    5 3) 10     

C语言强化(二)设计可以求最小元素的栈

上一篇详解了二叉树转双向链表,此篇作为[C语言强化]系列第二篇,来聊聊有关栈的一道题, 通过这道题,你可以掌握 如何使用栈"先进后出"的特性 如何巧妙地借助辅助栈 如何在结构体中定义可共享的静态成员变量 题目 看似很简单的求最小值函数,思路有很多很多.笔者首先想到每次push入栈都进行一次排序,使这个栈的栈顶永远是最小元素,然后就发现这是一个很蠢很蠢的想法,第一这样做会改变了栈的结构,第二不满足题目对时间复杂度的要求. 愚蠢归愚蠢,还是有点用的.既然不能改变原来栈的结构,那为何不弄俩栈

嵌入式linux C++语言(四)——类与对象

嵌入式linux C++语言(四)--类与对象 类的设计和使用如下: #include <iostream>#include <stdlib.h>#include <stdio.h>#include <string.h>using namespace std;class Stack{public:    Stack(int size=1024);    ~Stack();    void init();    bool isEmpty();    bool

Swift语言指南(四)--类型安全和类型推断

Swift是一门类型安全语言,类型安全语言需要代码里值的类型非常明确.如果你的代码中有部分值需要String类型,你就不能错误地传递Int. 鉴于Swift的类型安全,编译代码时,Swift会执行类型检查并将任何类型不匹配的地方标记为错误,使你在开发当中尽可能早的捕获并修正错误. 类型检查有助于你在操作不同值的类型时避免犯错.但这并不意味着你必须在声明每一个常量或变量时去检查类型,如果你不检查所需值的类型,Swift会执行类型推断来计算出相应地类型. 类型推断让编译器在编译代码时,根据你提供的值

IOS学习笔记---C语言第四天

1 //?生成2个数组,每个数组都有10个元素,元素取值范围20-40之间,数组对应元素相 加,放到另外?一个数组中 2 #import <Foundation/Foundation.h> 3 4 int main(int argc, const char * argv[]) 5 { 6 7 int num1[10]={0},num2[10]={0},num3[10]={0}; 8 for (int i = 0; i<10; i++) { 9 num1[i]=arc4random()%2

iOS学习笔记---oc语言第四天

字符串 数组 一.使用苹果帮助文档 学会使?用苹果帮助?文档是开发者的?一项技能 Inherits from 继承?自 Conforms to 遵循什么协议 Framework 属于哪个框架 Availability 什么时候可?用的 Declared in 声明在什么头文件?里 Related documents 相关文档 Sample code ?示例代码 快速打开帮助文档 在代码中,将?鼠标停留在 类名或者?法名上,option+?鼠标左键,点击 Reference的超链接进?入帮助?文档

C语言强化(一)二叉排序树转成排序的双向链表

几乎每一位码士的编程起点都是C,在玩过了Java.C#.PHP.Python之后,重回C语言,又是什么样的一种感觉呢? 此篇博文作为 [C语言强化]系列文章的第一篇,来聊聊曾让许多码士抓耳挠腮的二叉树. 通过这道题,你可以掌握 如何创建二叉树 如何遍历二叉树 如何创建二叉链表 怎样使用递归算法 这是一道非常老土但又十分经典的数据结构题,或许很多人会说自己之前已经做过了,但又有多少人回过头来做的时候,可以不借助任何参考资料把解题思路写出来? 题目要求:二叉排序树->双向链表排序 不能新增结点,只能

嵌入式Linux C语言(四)——指针与数组

嵌入式Linux C语言(四)--指针与数组 数组是C语言内建的数据结构,彻底理解数组及其用法是开发高效应用程序的基础.数组和指针紧密关联,但又不是完全可以互换. 一.数组简介 数组是能用索引访问的同种类型元素的连续集合.数组的元素在内存中是相邻的,中间不存在空隙,数组的元素是相同类型的. 1.数组的解读 数组的定义:int a[10] = {0,1,2,3,4,5}; a[0]:数组的第一个元素,首元素(做左值时表示第0个元素的内存空间) &a:数组的首地址,是常量,不能做左值,类型等同int

rwkj 1332 C语言实验四(函数):题目1、数字根

C语言实验四(函数):题目1.数字根 时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte总提交:305            测试通过:185 描述 正整数的数字根是将数位上的数字求和进行计算而来.如果各位数字之和为一位的整数,那么这个整数就是这个数的数字根:如果之后为多位数,那么重复运用此规则进行计算直至求出一个一位数.例如12,那么它的数字根就为1+2=3:例如39那么它的数字根就为3+9=12,1+2=3,最终为3. 输入 每行输入