Is there a way to find the number of elements in the binary search tree?
struct node
{
node *p, *left, *right;
int key;
};
This is my node's structure, p pointer is pointing to the parent element.
I need to find that number to allocate memory for searching the tree and returning an array with all elements.
I've came up with something like this:
int numberOfElements(node *root, int count = 0)
{
if(root)
{
numberOfElements(root->left, ++count);
numberOfElements(root->right, ++count);
}
return count + 1;
}
But well, it shows some random results :P For "1, 2" is displays 2, for "1, 2, 3, 4, 5, 6, 7" it displays 3 etc...
I want to do this inside one function, that's why count is an argument here.
How can I do this?
You don't need the second argument:
int numberOfElements(node *root) {
if (root) {
return 1 + numberOfElements(root->left) + numberOfElements(root->right);
} else {
return 0;
}
}
You don't seem to use the return value of numberOfElements at all.
This version might work:
int numberOfElements(node *root)
{
if(root)
{
return numberOfElements(root->left) +
numberOfElements(root->right) + 1;
}
return 0;
}
Generally, the size of such a tree should be recorded in a field, and gets updated every time you modify the tree. No one expects O(N) running time just to find the size of a tree.
Related
I have tasks and I want to calculate the most profitable order to arrange them.
Instead of checking every permutation and doing n*n! calculations, I want to build a tree of permutations, that is, the number of children at each level decreases by 1, and at each node the sub-permutation that has already been calculated will be saved and not recalculated.
For example, if I have 4 tasks, the tree will look like this:
My attached code is missing. I don't know how to build the tree and the give nodes the indexes as in the figure. I know how to deal with a binary tree, but not with a tree where the number of children is different at each lavel.
(The value of each task depends on its location.
I know how to do that, so I didn't include it in the question).
int n = 4;
struct node
{
int task_index = -1;
double value;
struct node **next;
};
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
void print_tree(node *current_node, int current_level = 0)
{
// print indexes
}
void delete_tree(node *current_node, int current_level = 0)
{
// delete nodes
}
int main()
{
struct node *root = new node;
build_tree(root);
print_tree(root);
delete_tree(root);
delete root;
return 0;
}
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
When called with the default parameter of current_level = 0, as you illustrate in your code below, this function exits on the first line without doing anything. You need to decide whether you are indexing starting from 0 or from 1.
Other than that, the general outline of the algorithm looks okay, although I did not explicitly check for correctness.
Now, more broadly: is this an exercise to see if you can write a tree structure, or are you trying to get the job done? In the latter case you probably want to use a prebuilt data structure like that in the boost graph library.
If it's an exercise in building a tree structure, is it specifically an exercise to see if you can write code dealing with raw pointers-to-pointers? If not, you should work with the correct C++ containers for the job. For instance you probably want to store the list of child nodes in a std::vector rather than have a pointer-to-pointer with the only way to tell how many child nodes exist being the depth of the node in the tree. (There may be some use case for such an extremely specialized structure if you are hyper-optimizing something for a very specific reason, but it doesn't look like that's what's going on here.)
From your explanation what you are trying to build is a data structure that reuses sub-trees for common permutations:
012 -> X
210 -> X
such that X is only instantiated once. This, of course, is recursive, seeing as
01 -> Y
10 -> Y
Y2 -> X
If you look at it closely, there are 2^n such subtrees, because any prefix can have any one of the n input tasks used or not. This means you can represent the subtree as an index into an array of size 2^n, with a total footprint O(n*2^n), which improves on the vastly larger >n! tree:
struct Edge {
std::size_t task;
std::size_t sub;
};
struct Node {
std::vector<Edge> successor; // size in [0,n]
};
std::vector<Node> permutations; // size exactly 2^n
This will have this structure:
permutations: 0 1 2 3 4 ...
|-^
|---^
|-------^
|---^
|-^
Where the node at, e.g., location 3 has both task 0 and 1 already used and "points" to all (n-2) subtrees.
Of course, building this is not entirely trivial, but it compressed the search space and allows you re-use results for specific sub-trees.
You can build the table like this:
permutations.resize(1<<n);
for (std::size_t i = 0; i < size(permutations); ++i) {
permutations[i].successor.reserve(n); // maybe better heuristic?
for (std::size_t j = 0; j < n; ++j) {
if (((1<<j) & i) == 0) {
permutations[i].successor.push_back({j,(1<<j)|i});
}
}
}
Here is a live demo for n=4.
The recursive way to generate permutations is if you have n items then all of the permutations of the items are each of the n items concatenated with the permutations of the n-1 remaining items. In code this is easier to do if you pass around the collection of items.
Below I do it with an std::vector<int>. Once using a vector it makes more sense to just follow the "rule of zero" pattern and let the nodes have vectors of children and then not need to dynamically allocate anything manually:
#include <vector>
#include <algorithm>
#include <iostream>
struct node
{
int task_index = -1;
double value;
std::vector<node> next;
};
std::vector<int> remove_item(int item, const std::vector<int>& items) {
std::vector<int> output(items.size() - 1);
std::copy_if(items.begin(), items.end(), output.begin(),
[item](auto v) {return v != item; }
);
return output;
}
void build_tree(node& current_node, const std::vector<int>& tasks)
{
auto n = static_cast<int>(tasks.size());
for (auto curr_task : tasks) {
node child{ curr_task, 0.0, {} };
if (n > 1) {
build_tree(child, remove_item(curr_task, tasks));
}
current_node.next.emplace_back(std::move(child));
}
}
void print_tree(const node& current_node)
{
std::cout << "( " << current_node.task_index << " ";
for (const auto& child : current_node.next) {
print_tree(child);
}
std::cout << " )";
}
int main()
{
node root{ -1, 0.0, {} };
build_tree(root, { 1, 2, 3 });
print_tree(root);
return 0;
}
I've been trying to create a function that turns an array into a linked list. It creates an array of nodes the same length as the array and stores each value in the array into the data field of each node, and sets up the pointers similarly. I quickly realized it wasn't working since print() is giving undefined results after printing the data value of the first node. I used some cout calls to see what's going on and found that the two cout calls in main, even though exactly the same, produce different results on the MSVC2019 compiler. The first one produces 2 (as it should) and the second one produces an undefined result. Below is the full program:
#include <iostream>
struct Node {
int data;
Node* next;
};
void print(Node n);
Node toNode(int ar[], int size);
int main(void) {
int ar[] = { 1, 2, 3, 4, 5 };
Node n = toNode(ar, 5);
std::cout << (*(n.next)).data << std::endl;
std::cout << (*(n.next)).data << std::endl;
// print(n);
}
Node toNode(int ar[], int size) {
Node nodes[100];
for (int i = 0; i < size; i++) {
Node n;
n.data = ar[i];
nodes[i] = n;
}
for (int i = 1; i < size; i++) {
nodes[i-1].next = &nodes[i];
}
nodes[size-1].next = NULL;
for (int i = 0; i < size; i++) {
Node n = nodes[i];
}
return nodes[0];
}
void print(Node n) {
std::cout << n.data << std::endl;
if (n.next != NULL)
print(*n.next);
}
here's the output on MSVC 2019:
I tried the same code on an online compiler and it gave a consistent 2 each time:
this is what I get when I call print(n) on MSVC2019:
is there something wrong with the toNode() function? I tried printing out the values for each node in the nodes[] array and they were 1, 2, 3, 4, and 5. I also tried printing out the value of the node that's being pointed by each node in the nodes[] array, and the results were 2, 3, 4, and 5 as expected.
also do take note there is a warning on the line
nodes[size-1].next = NULL;
in the toNode() function. The warning message is:
C6386: Buffer overrun while writing to 'nodes': the writable size is '552' bytes, but '-8' bytes might be written.
This is a very common problem.
The issue is that your code is using pointers to objects which have been destroyed. Take a look at your toNode function (with comments)
Node toNode(int ar[], int size) {
Node nodes[100];
...
for (int i = 1; i < size; i++) {
nodes[i-1].next = &nodes[i]; // pointers to 'nodes' being saved here
}
...
return nodes[0]; // object containing pointers to 'nodes' returned here
}
The problem is that the nodes array is destroyed when toNode is exited. So all those pointers you have saved are pointing to objects that have been destroyed. This explains the inconsistent behaviour. It also explains why you can sucessfully print out all the values when you are still inside the toNode function, at that point the nodes array has not been destroyed.
When you use pointers it's up to you to make sure that the object being pointed to is not destroyed before the pointer is. C++ does not do this for you. The usual way to ensure this is to use dynamic memory allocation (i.e. to use new). This is the normal technique for creating linked lists.
I am struggling to count nodes in a B-tree. Here keys refer to an array of values and num_keys refers to the valid number of keys currently. How do I approach this to make it work?
int BTree::count_nodes(shared_ptr<btree> root){
int count = 0;
int i =0;
if (root == NULL) {
return 0;
}
for (i = 0; i < root->num_keys; i++) {
count +=root->keys[i];
}
return count;
}
Here, you can iterate over all nodes in the tree, incrementing the counter each time.
int BTree::count_nodes(shared_ptr<btree> root) {
int count = 0;
std::stack<shared_ptr<btree> > traversal_stack;
traversal_stack.push(root);
while (!traversal_stack.empty()) {
shared_ptr<btree> top = traversal_stack.top();
traversal_stack.pop();
++count;
for (shared_ptr<btree> child : top->children) {
traversal_stack.push(child);
}
}
return count;
}
This uses depth-first search. To do breadth-first search, change the std::stack into an std::queue and use .peek() instead of .top().
Note that it may be more efficient to have each node keep track of its subtree's number of nodes, and for the counts to be updated whenever nodes move around, instead of having a function like this.
I'm trying to count total of leaves that have even numbers in a BST.
Example: root--> 2 4 6 8 9
Output: 4 leaf that have even numbers.
Here is what I have done:
struct BSTNode
{
BSTNode* left;
BSTNode* right;
int data;
};
int CountingTotalEven(BST* root)
{
int count = 0;
count++;
CountingTotalEven(BST* root);
return count;
}
My program output wrong number, I don't know what I'm doing wrong.
int count = 0;
count++;
CountingTotalEven(BST* root);
return count;
There are three main issues in this code currently. Firstly, you're initializing count in your recursive function as a non-static variable. So what happens is count gets initialized as 0 every time this recursive function is called.
Secondly, you've called the recursive function on the root again. What you want to do is call the function recursively for its right and left subtrees(read: Tree Traversals).
Thirdly, you're not checking if the value is actually even.Change your function to
static int count = 0;
if(count%2 == 0)
count++;
CountingTotalEven(root->left);
CountingTotalEven(root->right);
return count;
Trying to write a program which will sum all odd elements of binary tree. But my code (function odd_sum) returns only first odd element. Where is my mistake?
/*Creating abd printing tree*/
int odd_sum(node *root)
{ if (root == NULL) return 0;
return root->info % 2 != 0 ? root->info:0 + odd_sum(root->left) +
odd_sum(root->right);
}
int main()
{
int k,sum,h=0;
node *der=tree();
if (!der) printf ("No tree");
else
{
node *root=der,*qwe=der;
sum=odd_sum(root);
print_tree(der,h);
printf ("\nOdd sum :%d\n\n\n",sum);}
return 0;
}
If you meet an odd value in the tree you are just returning its value without branching down the tree, that's why you get only the first odd number.
The corrected version of your code is on the line of:
int odd_sum(node *root){
if (root == NULL) {
return 0;
}
else {
int add = 0;
if(root->info % 2 != 0) add = root->info;
return add + odd_sum(root->left) + odd_sum(root->right);
}
}
You need to traverse down the tree and whenever you find the node with odd value you can update your Sum variable.
void oddSum(node *root, int &Sum){
if(!root)
return;
if((root->val) & 1)
Sum += root->val;
oddSum(root->left, Sum);
oddSum(root->right, Sum);
}
Pass the root and Sum variable with reference, at the end of the recursion, you will find the sum of the odd values of tree stored in Sum.