abnercoimbre
Check out this chapter from author V. Anton Spraul (pages 24-27) for some arguments to think about.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | node*
TreeSearchSingleAlt2(node TreeRoot, bool32 (*Predicate)(node, void*), void* PredicateArg, int Depth = -1)
{
node* Result = null;
array<node*> NodeCheckStack = {};
PushArray<node*>(&NodeCheckStack, &TreeRoot);
node* TestNode = null;
while (NodeCheckStack.Length > 0)
{
TestNode = PopArray<node*>(&NodeCheckStack);
if (Predicate(*TestNode, PredicateArg)) { Result = TestNode; break; }
PushAllArrayIndirected<node>(&NodeCheckStack, TestNode->Children);
}
FreeArray(&NodeCheckStack);
return Result;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | node* TreeSearchSingleAlt4(node TreeRoot, bool32 (*Predicate)(node, void*), void* PredicateArg, int Depth = -1) { node* Result = null; std::stack<node *> nodes; nodes.push(&TreeRoot); node* TestNode = null; while(nodes.size() > 0) { TestNode = nodes.top(); nodes.pop(); if (Predicate(*TestNode, PredicateArg)) { Result = TestNode; break; } for(uint i = 0; i < TestNode->Children.Length; ++i) { nodes.push(TestNode->Children.Values + i); } } return Result; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | node* TreeSearchSingleAlt3(node TreeRoot, bool32 (*Predicate)(node, void*), void* PredicateArg, int Depth = -1) { node* Result = null; std::vector<node *> nodes; nodes.push_back(&TreeRoot); node* TestNode = null; while(nodes.size() > 0) { TestNode = nodes.back(); nodes.pop_back(); if (Predicate(*TestNode, PredicateArg)) { Result = TestNode; break; } for(uint i = 0; i < TestNode->Children.Length; ++i) { nodes.push_back(TestNode->Children.Values + i); } } return Result; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | node*
TreeSearchSingle(node TreeRoot, bool32 (*Predicate)(node, void*), void* PredicateArg, int Depth = -1)
{
node* Result = null;
foreach(node, ChildNode, TreeRoot.Children.Length, TreeRoot.Children.Values)
{
if (Predicate(*ChildNode, PredicateArg))
{
Result = ChildNode;
break;
}
else
{
if (Depth == 0) { return null; }
node* ChildResult = TreeSearchSingle(*ChildNode, Predicate, PredicateArg, Depth - 1);
if (ChildResult != null)
{
Result = ChildResult;
break;
}
}
}
return Result;
}
|
1 | PushAllArrayIndirected<html_node>(&NodeCheckStack, TestNode->Children); |
1 | TestNode = PopArray<html_node*>(&NodeCheckStack); |
1 2 3 4 5 6 7 8 9 10 | template<typename T>
void //?
PushAllArrayIndirected(array<T*>* Array, array<T> Items)
{
foreach(T, Item, Items.Length, Items.Values)
{
// Item is actually a pointer (T*), my foreach macro is bad.
PushArray<T*>(Array, Item);
}
}
|
JohnL
Yes, you are absolutely right that not every recursive solution will use tail calls (the wikipedia article states why and when).
I should have been more clear I suppose, I meant to comment on the statements that recursion will always put pressure on the stack. Which with the right algorithm and a compiler applying tail calls must not be always true.