logic behind traversing a tree to achieve this goal
Use either Depth First or Breadth First search to visit each node in the tree.
Start a new search at each node.
Because this tree is a recursive data structure, I would use recursion to perform search.
and end the recursion: - update 03/14
1) at the leaf node.
NOT when target sum is found, because negative values exist
NOT when when sum exceeds target sum, because negative values exist
Note: I think this simplifies the 'summing' action a lot. It is now a DF search terminating at the leafs with simple output at specific nodes.
NO 'decurse' actions are required, as all branches will be explored by DF/BF visit.
update 3/18
Some sample outputs from my code.
An 'on-its-side' tree display (top-to-the-left)
'-3'
'-2'
'-1'
'0'
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'10'
'11'
'12'
'13'
'14'
'42'
Sample 'targetSum' findings: (5 of 41)
BTree_t::dfVisit(-2)
start level 3: -2
start level 2: 0 -2
BTree_t::dfVisit(-1)
start level 4: -1
BTree_t::dfVisit(0)
start level 2: 0
start level 1: 5 0 -2 -3
BTree_t::dfVisit(1)
start level 4: 1
update 2017/03/22
There are plenty of examples of depth-first-searches code on the web. In my approach, the tree contribution is simply to start the search at the root (or explain why it can't).
// depth-first-visit of all nodes in tree
void BTree_t::dfVisitSum(const int targetSum)
{
std::cout << "\n\n BTree_t::dfVisitSum(" << targetSum << ") ";
if(m_root)
{
int reportCount = m_root->dfVisitSum(targetSum);
if(0 == reportCount)
std::cout << "none";
}
else
{
std::cerr << "\n dfVisitSum() Note: tree has no elements.."
<< std::endl;
}
}
If we now look at the node dfVisitSum(), we note it has a limited duration 'nodeLog' passed into the sumSearch():
// depth-first-visit of all nodes below the current node
int Node_t::dfVisitSum(const int targetSum)
{
int reportCount = 0;
// dfs search left, then do something, then search right
if(m_left) { reportCount += m_left->dfVisitSum(targetSum); }
{
// while visiting this node, create a vector for logging
NVec_t nodeLog;
nodeLog.reserve(nodeDepthMax());
// start a new depth-first-search called "sumSearch()
reportCount += sumSearch(targetSum, nodeLog);
} // nodeLog terminates here
if(m_right) { reportCount += m_right->dfVisitSum(targetSum); }
return (reportCount);
}
Finally,
// target-sum-search
int Node_t::sumSearch(const int targetSum, NVec_t& nodeLog)
{
int reportCount = 0;
// capture visit of this node to log
nodeLog.push_back(this);
// in dfs style, first search down the left
if(m_left) { reportCount += m_left->sumSearch(targetSum, nodeLog); }
{ // now do something in this node
size_t startLvl = nodeLog[0]->m_lvl; // for report
int accumulateSum = 0;
for (size_t i = 0; i < nodeLog.size(); ++i)
accumulateSum += nodeLog[i]->m_payLoad;
// sure, sure, use std::accumulate with a lambda, if you wish
if (targetSum == accumulateSum)
{
std::stringstream reportLabelSS; // convenience
reportLabelSS << "\n @ level " << startLvl << ":";
std::cout << showNVec(nodeLog, reportLabelSS.str());
// this output displays start level and nodes-visited payloads
reportCount += 1; // report occurrence north bound to caller
}
}
// in dfs style, search down the right
if(m_right) { reportCount += m_right->sumSearch(targetSum, nodeLog); }
// discard / clear this node visit from log, we are out-a-here
nodeLog.pop_back(); // removes last nodeLog element
return(reportCount); // report count
}