Binary Search Tree with size 7 and height 3 - ocaml

I am constructing a binary search tree of size 7 and height 3. I only have to hard-code it, not generate it through a function.
This is the tree that I have hard-coded
Node (Node (Node (Empty, 0, Empty), 1,
Node (Empty, 3, Empty)), 5
Node (Empty, 7, Node (8, 9, Empty))))
What I want is for Node 9 to have two children (8 and Empty). However, I keep on getting an error on 8 that says "this expression has type int but an expression of was expected of type int tree". How can I correct this?
Thanks!

You cannot write 8 for the leaf. You have to write Node (Empty, 8, Empty).
type tree = Empty | Node of tree * int * tree
(* the tree
5
/ \
/ \
1 7
/ \ \
0 3 9
/
8
*)
let t =
Node (
Node (Node (Empty, 0, Empty),
1,
Node (Empty, 3, Empty)),
5,
Node (
Empty,
7,
Node (Node (Empty, 8, Empty),
9,
Empty)
)
)
(* With an auxliary function we can do this to get the same tree: *)
let leaf k = Node (Empty, k, Empty)
let t' =
Node (
Node (leaf 0, 1, leaf 3),
5,
Node (Empty, 7, Node (leaf 8, 9, Empty)))

The first element of a Node has to be a tree, not something else like an int.
Therefore, you can't put 8 in a place where a tree is expected. Probably, you meant to have Node (Empty, 8 Empty) instead of 8.

Related

Is there any way to determine the node which has maximum amount of leaf-to-leaft node go through it on tree?

Here I have a dp-on-tree problem needs helped. So, the tree has N node and N - 1 edges, and a leaf-to-leaf path is a path from a leaf-node to another leaf-node on tree. Therefore, if the tree has M leaf, the total path will be M * (M + 1) / 2.
How can I find the node which has maximum leaf-to-leaf path go through it? For example, if I have the tree like this, the answer will be node 2. All the paths go through node 2 are: {1 -> 6, 1 -> 7, 6 -> 7, 1 -> 4, 4 -> 6, 4 -> 7, 1 -> 5, 5 -> 6, 5 -> 7}.
I think it's a dp-on-tree problem, but I can't find out the function and dp-formula.
Thks you so much! Also, pls show me some line of code if available.
Example Here
Given a suitable struct node { int id; node *left, *right;} and pre-created tree:
std::tuple<node*, int> max_candidate{nullptr, -1};
void report(node *root, int paths) {
if (paths > std::get<1>(max_candidate)) {
max_candidate = {root, paths};
}
}
int visit(node *root) {
if (!root)
return 0;
if (!root->left && !root->right)
return 1;
int leaves_left = visit(root->left);
int leaves_right = visit(root->right);
report(root, leaves_left * leaves_right);
return leaves_left + leaves_right;
}

Populating a binary tree

I can't wrap my head around what's missing in my function to populate a binary tree vs the manual input.
Printing the head value along with its left & right node value doesn't seem to help me as well since it looks correct to me. However, printing out all the values after auto populating it produces a strange result.
The values of this binary tree will be coming from an array:
std::vector<ValueType> values = {
3,
7,4,
2,4,6,
8,5,9,3
};
Here is the tree relation:
3
(7,4)
7 4
(2,4) (4,6)
2 4 6
(8,5) (5,9) (9,3)
As you can see, the parent node is located above and its children is below enclosed in parenthesis.
row1: the root node 3 have left:7, right:4
row2: parent 7 have left:2, right:4
row2: parent 4 have left:4, right:6
...
This may seem not be a binary tree as mentioned from the comments, but look at it as a tree having null left or right node or a node having a shared children from its sibling (same row).
Below is the function to automatically populate the binary tree:
// ValueType is defined as an alias of int
void populateTree(BinaryTree* node, int rowCount, int lastIndex, std::vector<ValueType> values) {
for (int i = 0; i < rowCount; ++i) {
iterCount++;
int currentRow = (i * (i + 1)) / 2;
int x = i + 1;
int nextRow = (x * (x + 1)) / 2;
bool toggle = false;
for (int j = nextRow; j < nextRow + x; ++j) {
auto value = values[currentRow++];
node->value = node->parent != nullptr ? value : node->value;
if (j >= values.size())
continue;
auto leftValue = values[j + 0];
auto rightValue = values[j + 1];
node->left = new BinaryTree(node, leftValue);
node->right = new BinaryTree(node, rightValue);
if (j != currentRow)
std::cout << ", ";
std::cout << node->value << "(" << node->left->value << "," << node->right->value << ")";
node = toggle ? node->right : node->left;
toggle = !toggle;
}
std::cout << std::endl;
}
}
I have used the triangular number formula to map the array into row and column.
Now, to confirm if the code is working, starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom should be 23.
I've done this by traversing bottom-up and add all the adjacent node combinations. Here's the output of the result:
3(7,4)
7(2,4), 4(4,6)
2(8,5), 4(5,9), 6(9,3)
iter count: 14
============
[4, 4, 7, 3]:18
[5, 4, 2, 4, 7, 3]:25
[3, 6, 4, 2, 4, 7, 3]:29
[3, 6, 4, 2, 4, 7, 3]:29
[5, 2, 4, 7, 3]:21
[4, 7, 3]:14
[4, 3]:7
pair total sum: 54
There supposed to be a combinations of [n1, n2, n3, ...nX]:23.
However, if I build the binary tree manually, there is a correct combination:
3(7,4)
7(2,4), 4(4,6)
2(8,5), 4(5,9), 6(9,3)
iter count: 14
============
[8, 2, 7, 3]:20
[5, 2, 7, 3]:17
[5, 4, 7, 3]:19
[9, 4, 7, 3]:23 <--- this is the correct combination.
[5, 4, 4, 3]:16
[9, 4, 4, 3]:20
[9, 6, 4, 3]:22
[3, 6, 4, 3]:16
pair total sum: 83
Link to full source code: https://gist.github.com/mr5z/8249a9101e5bfdce4850602c3ea7ebf3
This is part of my solution to project euler#18
I’m not exactly sure about why your implement a tree structure an your own, but if your goal is visualisation of a certain tree structure: I would suggest you to use the boost cpp graph library in combination with graphiz
See an example here, which shows the construction of a family tree, in a more "graph orientated" way. Every graph (like a tree) has nodes and edges.
If you want to train your programming skills, please go ahead: I found the following example for a b-tree quite useful in my past.
Couldn’t you use a “normal” insertIntoTree function instead of you populateTree function ? Or is this a matter of performance for you ?
What you do here is an example of an XY problem (see here: Meta StackExchange: What is the XY problem? or there: GreyCat's Wiki: XyProblem) – you're trying to put your data into a tree structure just because they are presented in a way resembling a tree-like pyramid, but you did not check if such structure will actually help you solve the problem.
And the answer is: NO, it will not; it doesn't even fit the actual problem structure.
Your problem structure is a pyramid-like triangle of integer numbers, each of which has two nearest descendants (except those in the bottom row) and two nearest ancestors (except those on side edges, which have just one ancestor, and the top item, which has no ancestors at all). And you have already mapped that structure into a linear array by your 'triangular formula':
given a row number r in a range of 0 .. N-1 and a position in the row p in a range of 0 .. r and an array with indices 0 .. N*(N+1)/2-1,
the item (r,p) is stored in the array at index r*(r+1)/2 + p,
and its 'children' are (r+1,p) and (r+1,p+1).
That's all, the mapping allows you to access data in a 'triangular' manner, you need no tree to handle it.

Level by level traversal of parent array n-ary tree?

Given an n-ary tree stored in a parent array, with the children stored in an array of pointers to arrays where the first value is the number of children:
(childArray[2][0] shows that node 2 has 2 children, childArray[2][1] shows that its first child is 5, etc.)
parentArray = {3, 0, 3, -1, 3, 2, 2};
childArray = {{1, 1}, {0}, {2, 5, 6}, {3, 0, 2, 4}, {0}, {0}, {0}};
produces a tree that looks like this:
3
/|\
0 2 4
| |\
1 5 6
Using a queue, how can I output the tree level by level like so:
Level 1: 3
Level 2: 0, 2, 4
Level 3: 1, 5, 6
Levels 1 and 2 are easy, because level 1 is just the root and level 2 is just its children, but after that I can't figure out how to get it to get the children of the children.
One way of doing so would be using a queue data structure.
Start with some queue q, and place in the index of the (unique) item whose parent is -1. Now, at each step, until q is empty,
Perform v <- pop(q) (popping the head)
Print out v
For each child w of v, do push(q, v) (pushing ot the tail)
For example, here are the first steps for your case:
Initially, q = [3] (3 is the index of the item whose parent is -1).
We pop q, print out 3, and push 0, 2, and 4, so q = [0, 2, 4].
Now we pop q, print out 0, and push 1, so q = [2, 4, 1].
Almost by definition, since q is popped from the front and added to the back, the nodes will be processed level by level.
The complexity is linear in the number of nodes.
You will have to perform a BFS (Breadth First Search) on the tree, while maintaining the number of nodes pushed into the next level. Outline:
q.push(root); nodesInCurrentLevel = 1; nodesInNextLevel = 0; currentLevelIndex = 1;
while q is not empty do:
u = q.pop()
print currentLevelIndex and u
decrement nodesInCurrentLevel
for every child v of u do:
increment nodesInNextLevel
q.push(v)
if nodesInCurrentLevel is 0 do:
nodesInCurrentLevel = nodesInNextLevel
nodesInNextLevel = 0
increment currentLevelIndex
Of course, this would print the output as Level 2:0 Level 2:2, etc. You can store current level nodes in a temporary list within the loop and print as appropriate.

BST-Insertion explaination

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.

How to output the nodes' values of a BST from highest to lowest?

This is a question I thought it would be easy but I found I'm wrong in the last. I can finish the program without recursive but I want to ask whether this problem can be finished in recursive version or not?
A recursive binary search tree traversal is basically (pseudo-code in case this is coursework):
def traverse (node):
if (node == NULL):
return
traverse (node.left)
doSomethingWith (node.payload)
traverse (node.right)
:
traverse (root)
That's all there is to it really, just replace doSomethingWith() with whatever you want to do (such as print).
That will traverse in left to right order so, if your BST is ordered in such a way that left means lower, simply swap over the two traverse calls.
By way of example, consider the following tree:
20
/ \
10 25
/ / \
5 24 27
/ /
2 28
as embodied in this example C program:
#include <stdio.h>
typedef struct s {
int payload;
int left;
int right;
} tNode;
tNode node[] = { // Trust me, this is the tree from above :-)
{20, 1, 4}, {10, 2, -1}, { 5, 3, -1}, { 2, -1, -1},
{25, 5, 6}, {24, -1, -1}, {27, -1, 7}, {28, -1, -1}};
static void traverse (int idx) {
if (idx == -1) return;
traverse (node[idx].right);
printf ("%d ", node[idx].payload);
traverse (node[idx].left);
}
int main (void) {
traverse (0);
putchar ('\n');
return 0;
}
Running that program gives you the following output:
28 27 25 24 20 10 5 2
Sure. Assuming the BST is sorted such that "greater than" nodes are on the right and "less than" nodes are on the left, a recursive function like this would work:
void recurse(Node* node)
{
if (node == nullptr) return;
recurse(node->right); // Explore all the "greater than" nodes first
std::cout << node->value << std::endl; // Then print the value
recurse(node->left); // Then explore "less than" nodes
}