how to extract a tree iteration in C++ - c++

I've been repeating a chunk of similar code for several times. This how it's like in pseudo code:
stack.push(root)
while stack size > 0
node = stack.pop()
if condition_1
if node is leaf
if condition_2
// do something,
// for example, push node into a vector and return the vector
else
stack.push(children of node)
or like this:
stack.push(root)
while stack size > 0
node = stack.pop()
if condition_1
if node is leaf
if condition_2 // or no condition_2 and return true directly
return true
else
stack.push(children of node)
return false
The difference between this two snippets is that the first one iterates all leaf nodes, while the second one has a break logic. And usually the main work I do is condition_2 and what's in its scope. Other lines are just repeating themselves.
So is there a way to extract this kind of tree iterating loop, in C++ or any other language?

As I understood correctly, you want to have a generic version of this algorithm.
I don't know which parts you do want to make generic, so here is a very simple solution where everything is generic.
template <class NodeType, class TraversalPredicate, class LeafPredicate,
class TerminalPredicate, class ChildrenGetter>
bool findIf(NodeType *root, TraversalPredicate shouldTraverse,
LeafPredicate isLeaf, TerminalPredicate shouldFinish,
ChildrenGetter getChildren) {
std::stack<NodeType *> stack;
stack.push(root);
while (not stack.empty()) {
auto *node = stack.top();
stack.pop();
if (not shouldTraverse(node))
continue;
if (isLeaf(node)) {
if (shouldFinish(node)) {
return true;
}
} else {
for (auto *child : getChildren(node)) {
stack.push(child);
}
}
}
return false;
}
I hope that is what you were looking for!

Related

Check if 2 nodes are adjacent in binary tree using linkedlish C++

Sorry for the bad English.
I'm creating a binary tree project by using a linked list in C++. And Im trying to make a boolean method to check if 2 nodes are adjacent or not?
And I'm trying to use the recursion method as I'm using the linked list to do this, but it seems I did it wrong.
Here is how I declare the Node
Struct Node{
string name;
int data;
Node *right, *left;
}
And here is how I declare the checking function:
bool checkadjacent(node* Node, string& u, string& v) {
if(!Node){
return false;
}
if (Node && Node->right) {
string current = Node->name;
string right = Node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
}
if (Node && Node->left) {
string current = Node->name;
string left = Node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
}
if (Node->left){
if(checkadjacent(Node->left, u, v)){
return true;
}
}
if (Node->right){
if(checkadjacent(Node->right, u, v)){
return true;
}
}
}
Note: "it seems I did it wrong" is not an explanation of how your code fials. Always describe what your code is SUPPOSED to do and what it is ACTUALLY doing.
Having said that, I'm assuming your code does not compile. I put together a (possibly non-comprehensive) list of errors and other problems with your code, aswell as a corrected version of your code. However, I would advise you to watch some tutorials about C++ (or C if you want, since your code is basically C code), because your code shows some serious misunderstandings and neglection. Apart from that, your basic idea seems correct except for the last bullet point in the following list.
List of problems:
It's struct not Struct (capitalization matters in C++). (This is necessary for correctness/syntax)
In the declaration of Node you capitalize the name of the Node. Later, you call it node and instead capitalize the name of the object which instantiates Node (to be consistent, I called the struct Node and it's instantiation node). (This is necessary for correctness/syntax)
First you check whether Node is actually pointing to a struct: if(!Node). This is good, but there is no need to check the same thing again later: if (Node && Node->right) and if (Node && Node->left) just leave out the first part in both conditions: if (node->right) and if (node->left). (This is for style)
Then you can also leave out the 3rd and 4th if statements and put their block into the 1st and 2nd if blocks respectively. (This is for style)
Do not declare the variables current, right and left inside the if blocks, instead declare them at the beginning of the function. (This is for style)
For the algorithm to work you have to return false if none of the if none of the if statements are executed (this is a guess; I did not test this and you WILL have to try that yourself). (This is necessary for correctness/semantics)
Here's the full code (note that I did NOT test this code, as your problem was clearly faulty syntax and not algorithm design.
bool checkadjacent(Node* node, string& u, string& v) {
string current, left, right;
if (!node) {
return false;
}
if (node->right) {
current = node->name;
right = node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
// recursion
if (checkadjacent(node->right, u, v)) {
return true;
}
}
if (node->left) {
current = node->name;
left = node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
// recursion
if (checkadjacent(node->left, u, v)) {
return true;
}
}
return false;
}
Also note:
I did not change the definition of Node.
Apart from string your code is just C code. In C++ you have the possibility to create a class for the binary tree which would be a lot more readable.
There are no linked lists in any parts of the code above (neither in the code you posted). The fact that the node have left and right child nodes, does not make it a linked list (in particular it's not a list because it is not 1-dimensional).
Again, I did NOT test this code; you can do that yourself.

Function that checks if a tree has only odd numbers C++

So, we have a tree with nodes that store numbers.
{
int data;
treeNode* child;
treeNode* sibling;
treeNode(int data) :data(data), child(nullptr), sibling(nullptr) {}
treeNode() {}
};
I'm trying to check if every node stores an odd number.
Example:
1 -- 3
/ \
5 7
Here 1 is the root and the others are its children and the function is meant to return true.
private:
bool isOdd(treeNode* node)const
{
if (!node) //I think the problem might be here but I don't really know how to fix it
return true;
if (node->data % 2 == 0)
return false;
return isOdd(node->child);
return isOdd(node->sibling);
}
public:
bool isOdd()const
{
if (root->data % 2 == 0)
return false;
return isOdd(root->child);
}
As shown above, I'm using recursion, but I'm willing to use iterative approach too.
Thanks in advance!
After this line
return isOdd(node->child);
the follwoing one is ingored, because as Yksisarvinen has commented, after one return statement has been executed, the function is done, nothing else will be executed.
I.e.
return isOdd(node->sibling);
will not influence the result, i.e. the sibling is ignored.
In order to always return something influeced by both parts, you need a logic operation
return (isOdd(node->sibling) && isOdd(node->child));
On the other hand your code
if (!node) return true;
seems fine to me. If you analyse a pointer which points to nothing (without dereferencing it, good) then it makes sense to say "Nothing" cannot break the "all odd", so returning true makes sense to me.

Maintaining context of current node in a iterative DFS vs a recursive DFS

I am facing a problem, where I am looking for a special type of node in a graph.
The algorithm works in following way:
bool findSpecial(Node n)
{
if(isSpecial(n))
return true;
bool isSpecial = false;
vector<Node> childs = getChildren(n);
foreach(child, childs)
{
isSpecial |= findSpecial(child);
}
if(isSpecial)
markCurrentNodeSpecial(n);
return isSpecial;
}
Above is a template of the algorithm, assuming that the input is DAG.
It looks for special nodes in the graph and marks current node special if any node in its the DFS tree is special.
The algorithm is basically populating this special attribute wherever it is reachable.
It can however lead to Stack Overflow in some rare cases.
I am trying to figure out if the same thing can be done iteratively or not.
The problem with iterative approach is that the information whether all the children of a Node are processed is not readily available.
Any suggestion?
1) The simplest solution - would std::stack<Node> work? You should make it work like a program stack works - push the starting Node there, then pop a node, check if it's special, if not - push its children, repeat.
2) You don't check if you have already visited a node - maybe you can speed it up a bit. (Edited: I can't read)
Update: yes, this was an interesting beast. How about this code? I didn't test it though, but the main idea should work: split visitation into two steps - before and after recursion.
struct StackNodeEntry
{
Node cur;
optional<Node> parent;
enum class Pos
{
before_recursion, after_recursion
} pos;
};
bool findSpecial(Node root)
{
stack<StackNodeEntry> stack;
stack.push({ root, {}, StackNodeEntry::Pos::before_recursion });
while (!stack.empty())
{
auto& e = stack.top();
switch (e.pos)
{
case StackNodeEntry::Pos::before_recursion:
if (isSpecial(e.cur))
{
if (e.parent)
markCurrentNodeSpecial(*e.parent);
stack.pop();
break;
}
for (auto n : getChildren(e.cur))
stack.push({ n, e.cur, StackNodeEntry::Pos::before_recursion });
e.pos = StackNodeEntry::Pos::after_recursion;
break;
case StackNodeEntry::Pos::after_recursion:
if (isSpecial(e.cur))
{
if (e.parent)
markCurrentNodeSpecial(*e.parent);
}
stack.pop(); // don't use e below this line
break;
}
}
return isSpecial(root);
}

Checking for a cycle in an undirected graph using DFS?

So, I made the following code for DFS:
void dfs (graph * mygraph, int foo, bool arr[]) // here, foo is the source vertex
{
if (arr[foo] == true)
return;
else
{
cout<<foo<<"\t";
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
if (arr[k] == false)
{
//cout<<k<<"\n";
dfs(mygraph,k,arr);
//cout<<k<<"\t";
}
it++;
}
}
//cout<<"\n";
}
Now, I read up that in an undirected graph, if while DFS, it returns to the same vertex again, there is a cycle. Therefore, what I did was this,
bool checkcycle( graph * mygraph, int foo, bool arr[] )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
result = checkcycle(mygraph,k,arr);
it++;
}
}
return result;
}
But, my checkcycle function returns true even if their is no cycle. Why is that? Is there something wrong with my function? There is no execution problem, otherwise I would have debugged, but their seems to be something wrong in my logic.
Notice that your function doesn't quite do what you think it does. Let me try to step through what's happening here. Assume the following relationships: (1,2), (1,3), (2,3). I'm not assuming reflexibility (that is, (1,2) does not imply (2,1)). Relationships are directed.
Start with node 1. Flag it as visited
Iterate its children (2 and 3)
When in node 2, recursively call check cycle. At this point 2 is also flagged as visited.
The recursive call now visits 3 (DEPTH search). 3 is also flagged as visited
Call for step 4 dies returning false
Call for step 3 dies returning false
We're back at step 2. Now we'll iterate node 3, which has already been flagged in step 4. It just returns true.
You need a stack of visited nodes or you ONLY search for the original node. The stack will detect sub-cycles as well (cycles that do not include the original node), but it also takes more memory.
Edit: the stack of nodes is not just a bunch of true/false values, but instead a stack of node numbers. A node has been visited in the current stack trace if it's present in the stack.
However, there's a more memory-friendly way: set arr[foo] = false; as the calls die. Something like this:
bool checkcycle( graph * mygraph, int foo, bool arr[], int previousFoo=-1 )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
// This should prevent going back to the previous node
if (k != previousFoo) {
result = checkcycle(mygraph,k,arr, foo);
}
it++;
}
// Add this
arr[foo] = false;
}
return result;
}
I think it should be enough.
Edit: should now support undirected graphs.
Node: this code is not tested
Edit: for more elaborate solutions see Strongly Connected Components
Edit: this answer is market as accepted although the concrete solution was given in the comments. Read the comments for details.
are all of the bools in arr[] set to false before checkcycle begins?
are you sure your iterator for the nodes isn't doubling back on edges it has already traversed (and thus seeing the starting node multiple times regardless of cycles)?

Tree search function

Any node can have any number of children. To search this tree i wrote something like this
function Search(key, nodes){
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].key == key) {
return nodes[i];
}
if (nodes[i].hasOwnProperty('children')) {
return this.Search(key, nodes[i].children);
}
}
which doesn't quite work...any input?
You only recursively search the first node that has children.
You should rewrite that last conditional to something like this:
if (nodes[i].hasOwnProperty('children')) {
var node = this.Search(key, nodes[i].children);
if(node != null)
return node;
}
You also need to add a case for if the node is not found - for example, a return null at the very bottom of the function.
You seem to be missing a base case. What happens when you encounter a node that has no children and also is not the node you're looking for?
If this is Javascript, this in your code this.Search is probably what's giving you the problem. this means "the current Function object." Try replacing this.Search with just Search.