How Does In Order Binary Tree Traversal Work? C++ - c++

void IntBinaryTree::insert(TreeNode*& tree, int num) {
//[1] Base Case: is the node empty?
if (!tree) { // if node is empty, create one
tree = new TreeNode(num);
return;
}
//[2] Does the value already exist in the tree?
if (tree->value == num)
return;
//[3] node passed not empty? If less than head pass left otherwise right
if (tree->value > num)
insert(tree->left, num);
else
insert(tree->right, num);
}
void IntBinaryTree::displayInOrder(TreeNode* root) {
if (root) {
displayInOrder(root->left);
std::cout << root->value << " ";
displayInOrder(root->right);
}
}
I want to understand why the displayInOrder function works?
Let's say there's a tree that looks like this:
5
/ \
3 7
/ \ / \
1 4 6 8
In order to display this tree in numerical order, you're going to want to read the leftmost values on the left first, then the root, and then the leftmost values on the right, and then the rightmost value last.
Now, the displayinorder function starts of with an if conditional. Simply saying, if the input doesn't equate to false, then keep going left. My question is, once we get to the leftmost value (1, in my example above) wouldn't the next call of "displayInOrder(root->left);" equate to the leftmost value of 1 (Which is NULL by default) and wouldn't NULL make the if conditional false?
How is it that this function seemingly knows to not call the leftmost value of 1?

this is because of the recursion. In the recursive call of displayInOrder(root->left) , the current root pointer is set to point to root->left. But we know that root (for this context it is root->left from the previous call) is pointing to null. So, the if block is not executed and the recursion does backtrack and go to its caller function (when the root was not null and had value of 1).
Then it executes the next line of code which prints 1 to the console. Then similar goes on until the recursion terminates.
Hope this helps!

It actually calls to display the left child of node(1), but that's NULL or nullptr, we know that if(NULL) is equiv to if(false) and thus the call of displayinorder(node1->left) will not enter the if and straightly return to the caller displayinorder(node1).
// stack of function calls
display(5)
->display(3)
-> display(1)
-> display(NULL)
print 1
-> display(NULL)
print 3
-> display(4)
-> display(NULL)
print 4
-> display(NULL)
print 5
-> display(7)
// ...

Related

Linked list operation on nodes (floyd cycle detection)

Structure
SinglyLinkedListNode {
int data;
SinglyLinkedListNode* next;
};
Function
bool has_cycle(SinglyLinkedListNode* head) {
SinglyLinkedListNode* s=head,*f=head->next;
while(s != NULL && f != NULL && f->next != NULL)
{
s = s->next;
f = f->next->next;
if(s->data == f->data)
return true;
}
return false;
}
According to the algorithm, if the slow pointer s and fast pointer f arrive on the same node the list is said to have a cycle. I'm assuming the same node will have the same data but then why am I getting failed test cases?
When I change (s->data = f->data) to (s == f) it works fine.
What is the difference between s == f and s->data == f->data?
The main issue here is your final checking condition. This will fail in a test case where there can be duplicates present (in the loop). When you are checking for the "same node" checking if the pointer value is same is better because it will always be unique, i.e., every node has an unique address but it is not necessary for it to be true for the value the node contains. For example:
1 -> 3 ->4 ->5 -> 6 -> 4 -> 7 -> NULL
//Note giving relative indexing(0th, 1st, .. and random addressing for understanding)
Iter 1: s is at 1(0th node, 1000010092) while f is at 3(1st node, 21983193)
Iter 2: s is at 3(1st node, 21983193) while f is at 5(3rd node, 129764714)
Iter 3: s is at 4(2nd node, 12984124) while f is at 4(5th node, 149284124)
See the ambiguity!!
Even though your algorithm is giving a TRUE a cycle doesn't exist.
But if you checked by the addressing, this false positive wouldn't have happened.
Tip: check if there are duplicates in any problem, they tend to be added to bring up such issues.

Building a binary tree from a string

I'm trying to build a tree from a string. The string is of the form: ((. (.A.E))(.I.O)), where the 5 leaf nodes of the tree are represented with a period.
I'm unable to determine how to solve this problem; I've tried tweaking the solution to a similar problem offered on this website: https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/.
Would really appreciate any help you could provide, as I prepare for coding interviews.
Thanks!
As I see this, there are just some rules to be followed. Based on the character being processed you have the following options:
If it's a "(", it means you must build your tree deeper, either to the left or to the right, based on the actions you took prior to this one
If it's a ".", you should read the next element in the string to determine the node value and after that you should go back one step in the recursion as the "." represents a leaf
If it's a ")", that means you finished building the subtree of a node and so you must go back one step in the recursion again
Some advices about how to implement this:
Write a recursive function that takes a string as input
The function should also return a string representing the string that remains to be further processed
If at any step your string is empty it means that the string given to be processed is not valid
You should check for the ")" every time you finish building the left or right subtree of a node
Hope this helps and good luck at your interviews!
The solution that I came up with is an iterative solution based on a stack. It has a few rules to follow:
push anything that comes to the stack
If you encounter ) of the stack, start removing elements untill you encounter a (, and then pop that out too.
When you pop the elements in step 2, store them in a vector, except ) and (.
Create a tree Node and mark the parent's children as all the elements in the vector.
push the parent Node back onto the stack.
Let's see with your example:
S = "((a($Z))(An))", changed ' ' -> 'a' for clarity.
Note: Stack growing towards the right.
Stack["((a($Z"]
encounter ')'
Stack["((a"], vector<"Z$">
reverse vector -> vector<"$Z">
Parent Node -> N(id='1'), children -> <N(id='$'), N(id='Z')>
push N(1) to stack
Stack["((a1]
encounter ')'
Stack["("], vector<"1a">
reverse vector -> vector<"a1">
Parent Node -> N(id='2'), children -> <N(id='a'), N(id=1)>
push N(2) to stack
Stack["(2(An"]
encounter ')'
...
you can continue this to get to the top. When you are done, i.e. the string is exhausted, you will get exactly one element left in the stack which would be your parent element or the root of the tree.
Code:
Node* solve(string s) {
stack<Node *> st;
int idx = 0, rt = 1;
while (idx < s.size()) {
Node *n = get_node(s[idx]);
st.push(n);
++idx;
if (st.top()->v == ')') {
st.pop();
vector<Node *> child;
while (st.size() && st.top()->v != '(') {
child.push_back(st.top()); st.pop();
}
if (st.top()->v == '(') st.pop();
Node *par = get_node('0' + rt++);
reverse(child.begin(), child.end());
for (Node *t : child) {
t->parent = par;
par->child.push_back(t);
}
st.push(par);
}
}
return st.top();
}
Full Working code
This code is a general implementation, so any node can have as many children, so n-arry tree construction.
eg:
input: ((a($Zk))(An))
output:
Parent: 4: 2 3
Parent: 2: a 1
Parent: 3: A n
Parent: 1: $ Z k

How binary search tree insertion works using recursion?

I'm having some trouble understanding the recursive part of binary search tree insertion.
bstnode* insert(bstnode* root,int data)
{
if(root==NULL){
bstnode* tmp= new bstnode();
tmp->data=data;
tmp->left=tmp->right=NULL;
return tmp;
}
if(data<root->data)
root->left = insert(root->left, data);
else
root->right = insert(root->right, data); //can't understand the logic here
return root;
}
/* consider following BST with their addresses[]:
15 [100]
/ \
10 20 [200]
\
tmp [300]
*/
According to me root->right = insert(root->right, data); should store the address of the newly created node in root->right so this code shouldn't work for tree with height>2.
However, it is working perfectly for any number of nodes.
I must be missing some crucial details here.
suppose I want to insert 25 in BST i.e. insert(root,25);
as 25>15:- I'm breaking down the recursive part here:
root->right = insert(root->right, 25);
or 15->right = insert(15->right,25); Here, recursively calling it again because 25>20
insert(root->right, 25) => root->right->right = insert(root->right->right, 25);
or insert(15->right, 25) => 20->right = insert(20->right, 25);
insert(20->right,25) is NULL so a new node tmp is created.
insert(20->right,25); returns tmp.
unwinding the recursion now.
//20->right = insert(20->right, 25);
so,
20->right= 300 (tmp address);
//insert(15->right, 25) => 20->right
//and 15->right = insert(15->right,25);
15->right = 20->next;
therefore 15->right = [300] address.
or
root->right = [300] address.
what's wrong with my approach?
Again an overview of recursive calls:
15->right = insert(15->right,25);
15->right = [20->right = insert(20->right,25)]; //20->right is NULL so creating new node
15->right = [20->right= 300 address of tmp];
15->right = [20->right or 300]
15->right = [300] // but in reality 15->right = [200]
you are forgetting that root->right is the root->right of the address you are passing into the function as root. every call to insert passes in root->right or root->left depending on which way you traverse.
This statement is incorrect:
root->right = root->right->right = tmp;
once an iteration of the function is returned it is removed from the stack so in this case we have 3 calls I will put your numbers in place of the pointer value.
insert(15->right,25)
insert(20->right,25)
the last one is null so it creates the node with 25 and returns it to the call insert(20->right,25) and sets 25 as 20->right so you have a tree that looks like this
/* consider following BST with their addresses[]:
20 [200]
\
25 [300]
*/
it then returns this tree to the call insert(15->right,25) and sets that trees right to the tree we just returned which so we get your final tree
/* consider following BST with their addresses[]:
15 [100]
/ \
30 20 [200]
\
25 [300]
*/
EDIT: let me see if I can clarify. Lets look at your tree again
/* consider following BST with their addresses[]:
15 [100]
/ \
10 20 [200]
\
tmp [300]
*/
we want to insert 25 so we call (again I will use the value at that node of the tree to represent the pointer we are passing)
insert(15, 25)
this then calls insert on root->right which happens to be 20
insert(20, 25)
this calls insert again on 20 right node now which happens to be null
insert(null,25)
so lets now look at the returns
insert(null,25) returns a node with 25 in it and then is remove from the stack
return 25;
insert(20,25) gets its return of a node with 25. it sets its right child to 25 which looks like this
20->right = 25;
return 20;
now we are back to the original call of insert(15,25). it got returned 20. so it does
15->right = 20;
return 15;
I think the confusion may be coming from two different sources for you.
First the tree commented into your code would not be possible. Second is that a new node is only created when the function is passed in a null pointer. Only values less than 15 can go to the left. It would be something like this instead (depending on add order):
15
/ \
20
/ \
30
When you go to add 25 to this it will end up as follows:
15
/ \
20
/ \
30
/
25
I will try and step through the code on this to explain. When adding 25 to the original tree on the first function call the first node is not NULL and 25 > 15 so the
else
{
root->right = insert(root->right, data);
}
is called. This calls the same insert function recursively but is now using the 20 node as it's comparison. Again not null and 25 > 20 so call insert on right node as above. This again calls the recursive function but now on 30. 25<30 so it calls the function on the left node. At this point the function as been passed in a NULL pointer as there is nothing there and a new node is created and placed in this spot.
Note that insert() always returns the root that was passed to it as an argument unless root == NULL. There's therefore no way for the new node you insert to "walk up the tree". What happens in the recursive call doesn't matter -- you always return the same root that you were passed in the non-NULL case.
Despite the way some people teach recursion, I think it helps (for my brain anyway) to not try to unroll the recursion, and instead consider whether the logic makes sense:
If you are passed a non-NULL node and data < root->data, would you get the correct result if you do root->left = insert(root->left, data) and assume the insert() magically "just works" (i.e., that it inserts data into the left tree and returns the root of that tree)?
If the logic checks out for both the left and right case, you then consider the base case: If you are passed a NULL node, will you return the correct one-element tree?
If the logic checks out for the base case too, then you know your code must be correct, since the recursive steps make sense and you know that you will land in a base case that also makes sense (since you will eventually reach a NULL node as you walk down the tree).
In a way you are correct. You can never have a sub-tree (not tree) of height >2.
In this code, you will never have a root->right->right because, as far as the code is concerned, when you call
root->left = insert(root->left, data);
the (local) root pointer is now pointing to the node you just inserted. the (local) root is pointing to root->left.
Therefore, you CAN have a tree of any height(However, the local root pointer is pointing to a sub-tree of height <2)

clarification on recursion concept

I am having doubt on recursion, if I write the code like shown below
inorder(p){
if(p!=NULL){
inorder(p->link); //step 1
cout<<p->info<<" "; //step 2
inorder(p->link); //step 3
}
}
Here, my doubt is that when step 1 is executed the control goes back to the function and then again the step 1 executes and again the control will go back to the function up to p is NULL, if this is the process then how control will come to step 2 which is "cout" and to step 3 ...
I am unable to cycle the code in my brain...
Before the "control goes back to the same function" in step 1, CPU makes an important step: it marks the place in code of inorder where it needs to restart execution once "the second level" of inorder returns (that's the spot right after step 1). There, the "second level" marks the return position again before going to the "third level", the "fourth level", and so on. Eventually, the N-th level gets a NULL, so it returns right away. Then the N-1-th level gets to print the info, and proceed to call inorder for the second time. Now the return location is different - it's right after step 3. Once N-th level finishes, N-1-st level finishes as well, going back to N-2-nd level, then to N-3-rd, and so on, until the very first level exits.
Here is an example tree:
A
/ \
B C
/ \
D E
The process of inorder traversal goes like this:
inorder(A) -- step 1, level 1
inorder(B) -- step 1, level 2
inorder(NULL) -- returns
cout << B -- step 2, level 2
inorder(NULL) -- returns
return -- level 2 returns
cout << A -- step 2, level 1
inorder(C) -- step 3, level 2
inorder(D) -- step 1, level 3
inorder(NULL) -- returns
cout << D -- step 2, level 3
inorder(NULL) -- returns
return -- level 3 returns
cout << C -- step 2, level 2
inorder(E) -- step 1, level 3
inorder(NULL) -- returns
cout << E -- step 2, level 3
inorder(NULL) -- returns
return -- level 3 returns
return -- level 2 returns
return -- level 1 returns
you should learn about call stack if you want to understand how the recursion works. Here is the link.
Hope this will help...
Suppose p points to A, p->link (that is, A.link) is called q and points to B, and q->link (which is to say B.link) is NULL, call it r.
p q r
----->A----->B----->0
Now we call inorder(p).
p is not NULL, so inorder(p) calls inorder(q) (step 1)
q is not NULL, so inorder(q) calls inorder(r) (step 1)
r is NULL, so inorder(r) skips the block and returns control to inorder(q)
inorder(q) prints B.info (step 2)
inorder(q) calls inorder(r) (step 3) which again returns control to inorder(q), which returns control to inorder(p)
inorder(p) prints A.info (step 2)
inorder(p) calls inorder(q) (step 3), which runs through 2-5 again (printing B.info again), then inorder(p) returns control to whatever called it.
The first time I bumped into recursion was with a factorial function.
Factorial is a basic function in maths, given a number N, it returns a number equal to the product of all positive integers less than N.
Consider this simple code in C++ which nicely demonstrates recursion.
int fact(int x)
{
if(x==1)
return 1;
x = x*fact(x-1);
return x;
}
This inputs an integer, and then calls itself after decrementing the integer until the integer is 1, and returns x. Note that the line 'return x;' is not called until the line before it finishes.
When the first call to inorder(p->link) is made, consider it as a checkpoint. It will keep calling to a point it reaches NULL. Then line 2 is executed and the same is followed for the second call to inorder(p->link). So this forms a tree
inorder(p->link) -> coutinfo -> inorder(p->link)
/ ^ / ^
V / V /
inorder()->cout->inorder() inorder()->cout->inorder()
. ^ / \ . ^ / \
. | . . . | . .
. | . |
inorder(p->link) //(p->link is NULL) inorder(p->link) //(p->link is NULL)
I assume that your code is correct. You are trying to print out a linked list in the below fashion:
inorder(p){
if(p!=NULL)
{
inorder(p->link); //step 1 to navigate to next link
cout<<p->info<<" "; //step 2 as main operation
inorder(p->link); //step 3 to navigate to next link
}
}
Translate into English
inorder(p)
{
if p points to a linked list
{
print the list p points to;
print content of p;
print the list p points to again;
}
if p points to a null linked list
{
do nothing;
}
}
Then a linked list of 1 -> 2 -> 3 will output ((3) 2 (3)) 1 ((3) 2 (3))
As you can see, the control will only pass to step 2 once step 1 encounters a null linked list. After the info is printed out, it is then passed to step 3.
Therefore,
When linked list at node "3",
step 1 encounters null and return;
step 2 prints out 3;
step 3 encounters null and return;
When linked list at node "2"
step 1 performs whatever it does at node "3"; // print 3
step 2 prints out 2;
step 3 performs whatever it does at node "3"; // print 3
when linked list at node "1"
step 1 performs whatever it does at node "2"; // print 3 2 3
step 2 prints out 1;
step 3 performs whatever it does at node "2"; // print 3 2 3
Consider a game, were you have 5 messages left at different places in your house. Each message leads you to the next. To win the game, you must find all 5 messages and return them to the game host. However, you cannot pick up the messages as you find them... you must remember their location and pick them up in the opposite order you found them.
You would walk to the first item, make a note of where it is and follow the clue; keeping a mental note to where you need to return later to pick up the clue. You would do the same with the next 4 clues.
When you find the last clue, so no more exist, you would then start to work backwards, returning to where you found each clue, retrieving them.
Finding the first clue is like your first call to "inorder()". Following the clue to the second clue is like your call to "inorder(p->link)". Picking up the clue after all clues have been found is like when you return to "step2" in your code.
Each time the function inorder is called, data (referred to as an activation frame or frame) is put on data structure referred to as a call stack. Each frame keeps track of data local to the function, such as parameters passed into the function, a pointer to the activation frame of the function caller and, importantly, the address of the next line of code to be executed in the calling function. So as you recursively call inorder, you are recursively adding frames to this stack and each frame contains an address to the next line of code that should be executed when the corresponding function is finished and control is returned to the function caller.
In other words, when you call inorder from line referred to as step 1 and the passed in parameter p is NULL, when the function exits, the calling function will start execution at the line referred to as step 2.
See the wikipedia page http://en.wikipedia.org/wiki/Call_stack for more info.
Understanding the concepts related to call stacks will help in understanding what is going on with recursion.

How to print out a BST in C++

My C++ program creates a binary search tree. I know how to print out the values in pre-order, post-order, and in-order.
However, I want to do something a little more difficult. I want to print out the values the way they would look if someone drew the tree on paper. It would have the root at the center at the top, it's left child right under and to the left of it, and it's right child right under and to the right of it. The rest of the nodes would be drawn accordingly.
How can I do that?
This article contains code for what you need, it seems:
alt text http://www.cpp-programming.net/wp-content/uploads/2007/12/ascii_tree.jpg
Edit: that site went offline
Here's another one exploring some other options.
Here's approximate pseudo-code to do it. The basic idea is walk the tree layer-by-layer, printing all the node in each layer on one line. Each node is separated by twice as much space as the nodes below it. Since the tree is not all of uniform depth, it is artificially padded with virtual nodes to take up the blank spaces where nodes don't exist.
measure the depth of the tree, call that D
have two queues, called Q1 and Q2
enque the top node of the tree in Q1
for (i = D; --i>=0; ){
foreach node in Q1 {
on first iteration of this inner loop, print 2^i - 1 spaces,
else print 2^(i+1) - 1 spaces.
if node == null print blank
else print node.value
if node.left exists enque node.left in Q2
else enque null in Q2
if node.right exists enque node.right in Q2
else enque null in Q2
}
copy Q2 to Q1
clear Q2
print end-of-line
}
Each space that is printed is the width of one numeric field. Suppose the tree has depth D = 4. Then the printing goes like this:
// it looks like this, and the space sequences are
i = 3: -------n 7
i = 2: ---n-------n 3 7
i = 1: -n---n---n---n 1 3 3 3
i = 0: n-n-n-n-n-n-n-n 0 1 1 1 1 1 1 1
void print(node *p,int start)
{
start++;
if (p->right != NULL)
{
print(p->right,start);
}
for (int i = 0; i <= start; i++)
{
cout<<" ";
}
cout << p->value<<endl;
if (p->left != NULL)
{
print(p->left, start);
}
}
One way is to use graphviz. Specifically, use its "dot" program, but getting the output to look exactly as you describe may not be possible.
well, in a terminal it's hard...since it may not fit. But there are graph drawing libraries out there that can make nice pictures for you. There is graphvis that is one of the most popular.
edit:
if you really just wan to print text, graphvis has a markup language that a user can pass to graphvis that in turn makes the nice pictures.