zoukankan      html  css  js  c++  java
  • 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");
    }

    运行



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


  • 相关阅读:
    Jmeter实现ajax异步同时发送请求
    数据构造技术框架的搭建及使用
    Maven安装与使用
    TFS2008安装环境
    ORACLE隐式提交导致的ORA01086错误:SAVEPOINT“丢失”
    关于记忆与学习
    ORACLE中异常处理
    【笔记:ORACLE基础】正则表达式
    malloc()和relloc()的用法【转】
    【笔记:ORACLE基础】用户管理
  • 原文地址:https://www.cnblogs.com/javdroider/p/5184298.html
Copyright © 2011-2022 走看看