Binary Search Tree Recursion Confusion - pointers

I think its a stupid question but sorry to say it will clear my Confusion.
If you just look into this code
void printInOrder(){
printPrivateInOrder(root);
}
void printPrivateInOrder(Node* n){
if (root != NULL){
if (n->left != NULL){
printPrivateInOrder(n->left);
}
cout << n->val << " ";
if (n->right != NULL){
printPrivateInOrder(n->right);
}
}
else{
cout << "Tree is Empty\n";
}
}
In this Traversal if we go to the extreme left child, then how this function is called again? Suppose just see the picture
BST Example
we have moved to node 4, then how this function is called again? if both child's are null I am not calling this function again, but this function is called again and printing all the nodes in InOrder Traversal? How?

When you recurse down to the next level, that basically involves taking a snapshot of exactly where you are, then going off to do something else. Once that "something else" is complete, you return to your snapshot and carry on.
It's very similar to calling non-recursive functions. When a function calls xyzzy(), it knows exactly where to carry on from when the call returns. Recursive functions are identical except that they're all passing through the same pieces of code on the way down and back up.
So, when you come back up a level (having processed the node on the left, for example), you will then print the current node, then go down the right side of the sub-tree.
Consider the sample tree:
2
/ \
1 4
/ \
3 5
\
6
To process this tree, for each node (starting at two), you process the left node, print the current node value, then process the right node.
However, you need to understand that "process the left/right node" is the entire "process left, print current, process right" set of steps over again on one of the children. In this sense, there is no difference between processing the root node and processing any other node.
The "processing" is the printing out, in order, of all nodes under a given point (including that point). It's just a happy effect that if you start at the root node, you get the entire tree :-)
So, in terms of what's actually happening, it's basically following the recursive path:
2, has a left node 1, process it:
| 1, has no left node.
> | 1, print 1.
| 1, has no right node.
| 1, done.
> 2, print 2.
2, has a right node 4, process it.
| 4, has a left node 3, process it.
| | 3, has no left node.
> | | 3, print 3.
| | 3, has no right node.
| | 3, done.
> | 4, print 4.
| 4, has a right node 5, process it.
| | 5, has no left node.
> | | 5, print 5.
| | 5, has a right node 6, process it.
| | | 6, has no left node.
> | | | 6, print 6.
| | | 6, has no right node.
| | | 6, done.
| | 5, done.
| 4, done.
2, done.
If you examine each of the printing lines (see the > markers), you'll see they come out in the desired order.

Related

Is is possible to deconstruct a vector?

I am toying around with Rust, and am trying to take in some input, and then splitting it by white space in to a vector of strings.
I then want to destructure these inputs again in to separate values. What I have so far is this:
use std::io;
fn main() {
println!("___Calculator___");
let mut buffer = String::new();
println!("What would you like to calculate?");
io::stdin()
.read_line(&mut buffer)
.unwrap();
let elements = buffer
.split_whitespace()
.collect::<Vec<&str>>();
let [first, second, third] = elements[0..2];
}
Again, I know I could just read input 3 times, but I want to see how I can do different things with the language.
Edit
Here's the error from cargo run:
Compiling calculator v0.1.0 (E:\code\rust\calculator)
error[E0005]: refutable pattern in local binding: `[]`, `[_]`, `[_, _]` and 1 more not covered
--> src\main.rs:18:9
|
18 | let [first, second, third] = elements[0..2];
| ^^^^^^^^^^^^^^^^^^^^^^ patterns `[]`, `[_]`, `[_, _]` and 1 more not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `[&str]`
help: you might want to use `if let` to ignore the variants that aren't matched
|
18 | let (first, second, third) = if let [first, second, third] = elements[0..2] { (first, second, third) } else { todo!() };
| +++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++
For more information about this error, try `rustc --explain E0005`.
error: could not compile `calculator` due to previous error
Thanks
Rust doesn't understand that elements[0..2] is always going to be three elements. In fact, it potentially won't be, if the user enters fewer than three words. So you need to handle that case.
if let [first, second, third] = &elements[0..2] {
...
} else {
println!("Enter three words plz :(");
}
EDIT: From a comment on the question, you also want elements[0..3]. Ranges are half-open in Rust.
The compiler is telling you what the problem is, and even suggests a fix:
error[E0005]: refutable pattern in local binding: `[]`, `[_]`, `[_, _]` and 1 more not covered
--> src/main.rs:18:9
|
18 | let [first, second, third] = elements[0..2];
| ^^^^^^^^^^^^^^^^^^^^^^ patterns `[]`, `[_]`, `[_, _]` and 1 more not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `[&str]`
help: you might want to use `if let` to ignore the variants that aren't matched
|
18 | let (first, second, third) = if let [first, second, third] = elements[0..2] { (first, second, third) } else { todo!() };
| +++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++
Patterns in variable declarations are required to be irrefutable, i.e. always succeed. What if the vector has less than three elements? You have to use match or if let to cover that possibility.

How does null move up the call stack in recursive functions, if a return value of null is not specified?

Hi I'm currently learning about recursive Inorder Binary Tree Traversal using C#. There's one main aspect I cannot understand, in particular with this code below.
public void InOrder(BinaryTreeNode node)
{
if (node != null)
{
InOrder(node.Left);
Console.WriteLine(node.Value);
InOrder(node.Right);
}
}
If I had a Binary tree that looked like this...
9
/ \
4 20
/ \ / \
1 6 15 170
I know that eventually by recursively calling Inorder(node.left) I will get to the left leaf of the binary tree i.e. the very end of the tree, where node.left will equal null as there are no more nodes.
The tree would look like this...
9
/ \
4 20
/ \ / \
1 6 15 170
/
null
Because node.left = null, the first recursive function
InOrder(node.left)
will terminate, and
Console.Writeline(node.left)
will execute
Printing a value of 1
Eventually these null values move up the call stack after each node is analysed, and all nodes are printed, the tree starts to look like this, as null value moves up the tree..
9
/ \
4 20
/ \ / \
null 6 15 170
/ \ / \
null null null
Eventually all the nodes in the tree are equal to null, and all nodes are printed in order to an output of ...
1, 4, 6, 9, 15, 20, 170
What I don't understand is how this null value is moving up the tree, and changing all the nodes that have been analysed to null when there is no return value. Normally there would be a base case like...
if (node == null)
{
return null;
}
For this, I understand that null is being returned so will persist/return up the call stack. But for fist block of code above, there is no return statement.
I also find it just as confusing when there is only a return statement without a return value like...
if (node == null)
{
return;
}
Again there is no return of null specified, so how does this null value move up the tree as each node is evaluated?
There isn't a problem with any of this code, it works as expected, and prints all the nodes of the Binary Tree InOrder. This is more about understanding Recursion, and why the first block of code still works even though a return null value is not specified.
Thanks in Advance for the help.
there is no return of null specified, so how does this null value move up the tree as each node is evaluated?
The function will still return, even if there is no value to return. It's done executing, so control is passed back to the caller.
if (node != null) <- skipped entirely when the node is null
{
InOrder(node.Left);
Console.WriteLine(node.Value);
InOrder(node.Right);
}
For the tree you gave, this is what happens at the node with value=1:
It's not null, so we go into the if block.
We evaluate InOrder(node.Left) which is just InOrder(null):
It's null, so the if block is skipped.
We return to the caller, InOrder(node with value=1)
Console.WriteLine(node.Value) prints 1.
etc...
Although you can't 'see' the base case in the code, it's still there :) just implicitly.

Fulltext Search in Neo4j

I have question on full text search using neo4j. Followed the instruction in the webpage, i enabled the full text search.
Full Text Search Guide
CREATE (p:Place {name:"Chicago"})
1) Run the command: START n=node:node_auto_index("name:*C*") RETURN n;
Result:
+------------------------------+
| n |
+------------------------------+
| Node[65263]{name:"Chicago"} |
+------------------------------+
1 rows
2) Run the command: START n=node:node_auto_index("name:Chicago") RETURN n;
Result:
+---+
| n |
+---+
+---+
0 row
3) START n=node:node_auto_index("name=Chicago") RETURN n;
Result:
null
My question is: How can modify the search (2) START n=node:node_auto_index("name:Chicago") RETURN n; to give the result Chicago ?
Also, would we not specify the field name in the command, (i.e. search all fields which contains "Chicago" keyword in all nodes) ?
Thanks.
You can use schema indexes for exact matches.
CREATE INDEX ON :Place(name)
For more info see
http://neo4j.com/docs/developer-manual/current/cypher/schema/index/
If you, for some reason, still need to do an exact match try this syntax:
START n=node:node_auto_index(name="Chicago") RETURN n;
Can you try like this ?
Exact match Chicago -
START n=node:node_auto_index('(name:(Chicago))') RETURN n;
Match all nodes with name property containing Chicago -
START n=node:node_auto_index('(name:(Chicago)') RETURN n;

fork() understanding, about execution and children

I'm just starting to fork() and I'm having some difficulties understanding the parallel execution. I've found this example code and I want to know if the first time it will go true or false (I know if pid1==0 it means it's a child, etc). I also want to know how many copies (children will be created) and some details on the general execution.
I have tried to run it and added the return 0; (my original source didn't have it) just to see if exits... but as you can see it "waits"
http://i.imgur.com/D3XEFgs.png
int main(void)
{
int pid1, pid2, pid3, pid4;
pid1=fork();
if (pid1!=0)
{
pid2=fork();
pid3=fork();
printf("\t\t IF(TRUE) pid1=%d and pid2=%d and pid3=%d\n",
pid1, pid2, pid3);
}
else
{
pid4=fork();
printf("\nIF(False) FATHER is talking with pid1=%d and pid4=%d\n",
pid1, pid4);
}
return 0;
}
This program creates five descendant processes, and makes six calls to printf, of which four will be the IF(TRUE) message and two will be IF(FALSE). Here is an ASCII-art diagram of the control flow; every time it branches, both sides are executed, with the parent going straight down and the child to the right. The numbers are the fork calls initializing the pid1, pid2, ... variables, the letters T and F are the IF(TRUE) and IF(FALSE) messages, and the _ is the return 0 at the end of the function. This program does not wait for anything; all control flow paths reach the return 0 eventually.
|
1
|\------\
2 4
|\--\ |\
3 3 | |
|\ |\ | |
T T T T F F
| | | | | |
_ _ _ _ _ _
The output messages may appear in any order. And it's possible that the topmost parent process will exit (returning control to the shell) before all of the descendant processes have written their messages, so (as is visible in your screeenshot) the shell prompt may get jumbled up with the messages, too.
Note that, going by the text of the messages, you have your if conditional backward: pid1 != 0 is true in the parent, not the child.
Both true and false will be used on the first time.
fork() copies the program (creates 1 child) and both programs continue execution from that point. The child process will take one branch and the parent the other.
The number of fork()s is as follows:
You start with 1 process
After pid1 -> +1 processes
Parent Branch
After pid4 -> +1 processes
Child Branch
After pid2 -> +1 processes
BOTH of the newly created processes run fork() for pid3, so after pid3 -> +2 processes
You get 5 children + the original process.

Needed help understanding insertion sort

In this code how does this work (java):
/** Move A[A.length-1] to the first position, k, in A such that there
* are no smaller elements after it, moving all elements
* A[k .. A.length-2] over to A[k+1 .. A.length-1]. */
static void moveOver (int A[]) {
moveOver (A, A.length-1);
}
/** Move A[U] to the first position, k<=U, in A such that there
* are no smaller elements after it, moving all elements
* A[k .. U-1] over to A[k+1 .. U]. */
static void moveOver (int A[], int U) {
if (U > 0) {
if (A[U-1] > A[U]) {
/* Swap A[U], A[U-1] */
moveOver (A, U-1);
}
}
}
I got this from a berkeley cs class I am going through online, teaching myself. it is not homework (i wish was but not that fortunate). what I don't understand is the following:
suppose the numbers in A[] are 8, 2, 10, 5, 4, 12. When I use them above I get this in my iterations, tracing it.
the upper most subscript is U, or in
this case 12, U-1 is 4, no swap is
done
U is now 4 (recursive U-1) and the number above it is 5 (the other U-1). they get swapped.
U is now 4 because four just moved up and 10 is U-1 they get swapped.
My sequence is now 8,2,4,10,5,12.
My question is how do I get the numbers I already passed by? how will I get five, for example, to move up if I never go back to that subscript to test with.
I don't think I am tracing the program correctly and my be getting confused with the recursion. For the sake of this please assume the swap is done correctly.
Thank you.
se
I think the key to your mis-understanding of the problem is actually hidden in the title of your question
Needing help understanding insertion sort
The algorithm indeed only sorts the current element, but the idea is that its run every time an element is added to the array. That way each time its called the rest of the array is already in order. In other words you are only trying to sort into position that last element.
So using your example numbers (8, 2, 10, 5, 4, 12) and adding/sorting them into the array one at a time in order, the sequence would be as follows (the sorting at each step happens exactly how you already describe):
To be added | old array | after push | Result (after moveOver())
(8, 2, 10, 5, 4, 12)| [] | [8] | [8]
(2, 10, 5, 4, 12) | [8] | [8,2] | [2,8]
(10, 5, 4, 12) | [2,8] | [2,8,10] | [2,8,10]
(5, 4, 12) | [2,8,10] | [2,8,10,5] | [2,5,8,10]
(4, 12) | [2,5,8,10] | [2,5,8,10,4] | [2,4,5,8,10]
(12) | [2,4,5,8,10] | [2,4,5,8,10,12]| [2,4,5,8,10,12]
As to your trace: you are going wrong at point 2, because the if condition does not hold, so no recursive call is ever made.
If the recursion confuses you, it may help to rewrite into an iterative form:
static void moveOver (int A[], int U) {
while (U > 0 && A[U-1] > A[U]) {
/* Swap A[U], A[U-1] */
--U;
}
}
Now it's easy to see that the loop will stop as soon as a smaller element is encountered. For this to be a complete sorting algorithm, more work is needed. Either way, this is not insertion sort; it looks more like a partial bubble sort to me.
Now where did you say you got this code from?

Resources