I am doing a simple binary search tree implementation in C++. I found that it works for most test cases but I am confused with a test case where I create a tree and add 1,2,3,4,5,6,7,8,9,10 in that order. The inorder traversal comes out to be 1,10,2,3,4,5,6,7,8,9. My understanding is that the inorder traversal will print the elements in sorted order which would be 1,2,3,4,5,6,7,8,9,10. However, either this assumption is incorrect or my code is printing an incorrect output. Please let me know if my output is correct or incorrect, and why if it is correct. Thank you.
If you are not sure about how in order binary tree traversal works then look at the below tree and the explanation.
(NOTE: I have this done only for 5 number's).
/* Constructed binary tree is
1
/ \
2 3
/ \
4 5
*/
Step 1 Creates an empty stack: S = NULL
Step 2 sets current as address of root: current -> 1
Step 3 Pushes the current node and set current = current->left until current is NULL
current -> 1
push 1: Stack S -> 1
current -> 2
push 2: Stack S -> 2, 1
current -> 4
push 4: Stack S -> 4, 2, 1
current = NULL
Step 4 pops from S
a) Pop 4: Stack S -> 2, 1
b) print "4"
c) current = NULL /*right of 4 */ and go to step 3
Since current is NULL step 3 doesn't do anything.
Step 4 pops again.
a) Pop 2: Stack S -> 1
b) print "2"
c) current -> 5/*right of 2 */ and go to step 3
Step 3 pushes 5 to stack and makes current NULL
Stack S -> 5, 1
current = NULL
Step 4 pops from S
a) Pop 5: Stack S -> 1
b) print "5"
c) current = NULL /*right of 5 */ and go to step 3
Since current is NULL step 3 doesn't do anything
Step 4 pops again.
a) Pop 1: Stack S -> NULL
b) print "1"
c) current -> 3 /*right of 5 */
Step 3 pushes 3 to stack and makes current NULL
Stack S -> 3
current = NULL
Step 4 pops from S
a) Pop 3: Stack S -> NULL
b) print "3"
c) current = NULL /*right of 3 */
Traversal is done now as stack S is empty and current is NULL.
Related
Anyone can help me with finding out the error with this code? This is for a hackerrank question MAXIMUM ELEMENT. For the case 2, the line "maxes.pop()" keeps giving me segmentation fault. Commenting that line out actually allows the code to compile.
QUESTION:
You have an empty sequence, and you will be given queries. Each query is one of these three types:
1 x -Push the element x into the stack.
2 -Delete the element present at the top of the stack.
3 -Print the maximum element in the stack.
Function Description
Complete the getMax function in the editor below.
getMax has the following parameters:
string operations[n]: operations as strings
Returns
int[]: the answers to each type 3 query
Input Format
The first line of input contains an integer, . The next lines each contain an above mentioned query.
Constraints
Constraints
All queries are valid.
Sample Input
STDIN Function
----- --------
10 operations[] size n = 10
1 97 operations = ['1 97', '2', '1 20', ....]
2
1 20
2
1 26
1 20
2
3
1 91
3
Sample Output
26
91
vector<int> getMax(vector<string> operations) {
stack<int> nums;
stack<int> maxes;
vector<int> maxnums;
int max = INT_MIN;
//int top = -1;
for(long unsigned int i=0; i<operations.size(); i++){
switch(operations[i][0]){
case('1'):
cout<<"Operation 1"<<endl;
nums.push(stoi(operations[i].substr(2)));
if(nums.top() > max){
max = nums.top();
maxes.push(max);
}
break;
case('2'):
cout<<"Operation 2"<<endl;
if(max==nums.top()){
//cout<<"top element in maxes"<<maxes.top()<<endl;
maxes.pop();
max = maxes.top();
}
nums.pop();
break;
case('3'):
cout<<"Operation 3"<<endl;
maxnums.push_back(maxes.top());
break;
}
}
return maxnums;
}
Consider the following input sequence:
1 1 // push 1. Pushes 1 into nums and maxes
1 1 // push 1. Pushes 1 into nums, but not into maxes, since max = 1.
3 // delete top stack element
3 // delete top stack element
Before processing the first 3 line, your state will be this:
nums = {1, 1}
maxes = {1}
max = 1
Now, on the first pop, everything will be fine, so after the first pop, you will end up with this state:
nums = {1}
maxes = {}
max = 1
However, on on the second pop, max == nums.top() is still true, so you pop from your maxes stack, which is already empty. That is why it gives you the segmentation fault.
I need to construct a tree given its depth and postorder traversal, and then I need to generate the corresponding preorder traversal. Example:
Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4
I've defined two arrays that contain the postorder sequence and depth. After that, I couldn't come up with an algorithm to solve it.
Here's my code:
int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
postorder[idx1] = stoi(tokenString1);
idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
depth[idx2] = stoi(tokenString2);
idx2++;
}
Tree tree(1);
You can do this actually without constructing a tree.
First note that if you reverse the postorder sequence, you get a kind of preorder sequence, but with the children visited in opposite order. So we'll use this fact and iterate over the given arrays from back to front, and we will also store values in the output from back to front. This way at least the order of siblings will come out right.
The first value we get from the input will thus always be the root value. Obviously we cannot store this value at the end of the output array, as it really should come first. But we will put this value on a stack until all other values have been processed. The same will happen for any value that is followed by a "deeper" value (again: we are processing the input in reversed order). But as soon as we find a value that is not deeper, we flush a part of the stack into the output array (also filling it up from back to front).
When all values have been processed, we just need to flush the remaining values from the stack into the output array.
Now, we can optimise our space usage here: as we fill the output array from the back, we have free space at its front to use as the stack space for this algorithm. This has as nice consequence that when we arrive at the end we don't need to flush the stack anymore, because it is already there in the output, with every value where it should be.
Here is the code for this algorithm where I did not include the input collection, which apparently you already have working:
// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);
int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
while (depth[i] < stackSize) {
preorder[--j] = preorder[--stackSize]; // flush it
}
preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
std::cout << preorder[i] << " ";
}
std::cout << "\n";
This algorithm has an auxiliary space complexity of O(1) -- so not counting the memory needed for the input and the output -- and has a time complexity of O(n).
I won't give you the code, but some hints how to solve the problem.
First, for postorder graph processing you first visit the children, then print (process) the value of the node. So, the tree or subtree parent is the last thing that is processed in its (sub)tree. I replace 10 with 0 for better indentation:
2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1
As explained above, node of depth 0, or the root, is the last one. Let's lower all other nodes 1 level down:
2 1 3 3 3 2 2 1 1 0
-------------------
1
5 2 8 9 0 6 7 3 4
Now identify all nodes of depth 1, and lower all that is not of depth 0 or 1:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 8 9 0 6 7
As you can see, (5,2) is in a subtree, (8,9,10,6,7,3) in another subtree, (4) is a single-node subtree. In other words, all that is to the left of 2 is its subtree, all to the right of 2 and to the left of 3 is in the subtree of 3, all between 3 and 4 is in the subtree of 4 (here: empty).
Now lets deal with depth 3 in a similar way:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 6 7
8 9 0
2 is the parent for 2;
6 is the parent for 8, 8, 10;
3 is ahe parent for 6,7;
or very explicitly:
2 1 3 3 3 2 2 1 1 0
-------------------
1
/ / /
2 3 4
/ / /
5 6 7
/ / /
8 9 0
This is how you can construct a tree from the data you have.
EDIT
Clearly, this problem can be solved easily by recursion. In each step you find the lowest depth, print the node, and call the same function recursively for each of its subtrees as its argument, where the subtree is defined by looking for current_depth + 1. If the depth is passed as another argument, it can save the necessity of computing the lowest depth.
I was trying to learn Binary search tree,I have one doubt related to BST insertion.This is not my code I have taken this from http://cslibrary.stanford.edu/110/BinaryTrees.html
struct node* insert(struct node* node, int data) {
// 1. If the tree is empty, return a new, single node
if (node == NULL) {
return(newNode(data));
}
else {
// 2. Otherwise, recur down the tree
if (data <= node->data) node->left = insert(node->left, data);
else node->right = insert(node->right, data);
return(node); // return the (unchanged) node pointer-->THIS LINE
}
}
My doubt As mentioned in the code I don't understand that why root doesn't get changed on insertion(last line).Why it is the same root everytime ?
recursive call in this code doesn't affect root node because you send root node
at first time ( at that time root is NULL) and will enter the if condition
otherwise will not affect root consider the following tree and call
2 -- (call insert and gave it root node, data -4)
/ \
1 10
/
5
first call will check if root == NULL
---this if false
will test whatever -4 greater or smaller than 2 and will make recursive call on left node
2
/ \
1-- 10 (call insert and gave it left child of root node, data -4)
/
5
and this node again not NULL will make anther recursive call of left of left of root this node is NULL
2
/ \
1 10
/ /
NULL 5 (call insert and gave it left child of left child root node, data -4)
here will create new node and with returning will assign this node to left of left of root and return pointer on it to first call
2
/ \
1 10
/ /
-4 5
just ...
my advice read about recursive functions good before studying BST
If you have a BST and want to insert the stream 3, 2, 8, 5, 7 you will do as follows:
3
3
/
2
3
/ \
2 8
3
/ \
2 8
/
5
3
/ \
2 8
/
5
\
7
As you can see the root never changes. Each element you insert gets added as a leaf in the correct position.
Sorry for my bad english.
I need to print the levels of a general tree or n-ary tree.
The struct of the tree is:
struct GTnode{
int data;
nodeGT *fc; //first child
nodeGT *nb; //next brother
}
The difficulty of the algorithm is when you have 2 different node in the same level and each one have a child.
Editing
If I have this tree for example:
1
2 7 8
3 6 9 12
4 5 10 11
I have to print:
1
2 7 8
3 6 9 12
4 5 10 11
Each endl represents a different level in the tree
Editing
An idea of my code is the next:
void printLevel(GTnode *root){
GTnode *aux = root;
if(root != NULL){
cout<<aux->data;
printLevel(aux->nb);
cout<<end; //Print the space between levels
printLevel(aux->fc);
}
}
I know this is wrong but is just an idea of what I have.
You need to do a level-order/breadth-first traversal of the tree (wp). To do that you need a queue. Put the root in the queue. Then do this until the queue is empty: Take the first out, add its ->fc to the queue and go to its ->nb (go through all the ->nb's until there are nomore and each time you add its ->fc to the queue).
I'm reading Nicolai M. Josuttis's "The C++ standard library, a tutorial and reference", ed2.
He explains the heap data structure and related STL functions in page 607:
The program has the following output:
on entry: 3 4 5 6 7 5 6 7 8 9 1 2 3 4
after make_heap(): 9 8 6 7 7 5 5 3 6 4 1 2 3 4
after pop_heap(): 8 7 6 7 4 5 5 3 6 4 1 2 3
after push_heap(): 17 7 8 7 4 5 6 3 6 4 1 2 3 5
after sort_heap(): 1 2 3 3 4 4 5 5 6 6 7 7 8 17
I'm wondering how could this be figured out? for example, why the leaf "4" under path 9-6-5-4 is the left side child of node "5", not the right side one? And after pop_heap what's the tree structure then? In IDE debugging mode I could only see see the content of the vector, is there a way to figure out the tree structure?
why the leaf "4" under path 9-6-5-4 is the left side child of node "5", not the right side one?
Because if it was on the right side, that would mean there is a gap in the underlying vector. The tree structure is for illustrative purposes only. It is not a representation of how the heap is actually stored. The tree structure is mapped onto the underlying vector via a simple mathematical formula.
The root node of the tree is the first element of the vector (index 0). The index of the left child of a node is obtained from its parent's index by the simple formula: i * 2 + 1. And the index of the right child is obtained by i * 2 + 2.
And after pop_heap what's the tree structure then?
The root node is swapped with the greater of its two children1, and this is repeated until it is at the bottom of the tree. Then it is swapped with the last element. This element is then pushed up the tree, if necessary, by swapping with its parent if it is greater.
The root node is swapped with the last element of the heap. Then, this element is pushed down the heap by swapping with the greater of its two children1. This is repeated until it is in the correct position (i.e. it is not less than either of its children).
So after pop_heap, your tree looks like this:
----- 8 -----
| |
---7--- ---6---
| | | |
-7- -4- -5- x5
| | | | | | x
3 6 4 1 2 3 9
The 9 is not actually part of the heap anymore, but it is still part of the vector until you erase it, via a call pop_back or similar.
1. if the children are equal, as in the case of the adjacent 7's in the tree in your example, it could go either way. I believe that std::pop_heap sends it to the right, though I'm not sure if this is implementation defined
The first element in the vector is the root at index 0. Its left child is at index 1 and its right child at index 2. In general: left_child(i) = 2 * i + 1 and right_child(i) = 2 * i + 2 and parent(i) = floor((i - 1) / 2)
Another way to think about it is the heap fills each level from left to right in the tree. Following the elements in the vector the first level is 9 (1 value), second level 8 6 (2 values) and third level 7 7 5 5 (4 values), and so on. Both these ways will help you draw the heap in a tree structure when given a vector.