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.