Is there any way to insert a new node in a binary tree (not bst) without comparing key values? The following code only works for the very first three nodes.
node *insert (node *root, int *key) {
if (root==NULL) {
root=newNode(root, key);
return root;
}
else if (root->left == NULL)
root->left=insert(root->left,key);
else if (root-> right == NULL)
root->right=insert(root->right,key);
return root;
}
If you change
else if (root-> right == NULL)
to just
else
Then it would have the effect of always adding to the right.
If you want it to randomly pick, add a call to srand outside this function.
srand(time(NULL));
Then in this function, call
else if (rand() > MAX_RAND / 2) {
root->right = insert(root->right, key);
} else {
root->left = insert(root->left, key);
}
at the end of your existing if/else structure.
See also:
Lack of randomness in C rand()
If your tree tracks its height at each node, you could add after your null checks something like
else if (root->left->height <= root->right->height) {
root->left = insert(root->left, key);
} else {
root->right = insert(root->right, key);
}
That would keep the tree balanced automatically. But it requires additional code to manage the height. E.g.
root->height = 1 + ((root->left->height > root->right->height) ? root->left->height : root->right->height);
I leave it up to you whether that additional overhead is worth it.
The people suggesting using a heap are suggesting using the indexes as the ordering. This is kind of useless as a heap, but it would make a balanced binary tree. So the root node would be the first inserted and the most recent inserted would be the rightmost leaf.
You could just keep track of the height of each node, and always insert it into the side with fewer children:
node *insert (node *root, int *key) {
if (root==NULL) {
root=newNode(root, key);
root->height = 0
}
else if (root->left == NULL) {
insert(root->left,key);
}
else if (root->right == NULL) {
insert(root->right,key);
}
else if (root->left->height <= root->right->height) {
insert(root->left,key);
} else {
insert(root->right,key);
}
root->height++
}
Comparing values is actually irrelevant, the only think you need to do is set a pointer. Since you didn't specify any real requirements, one solution could be as follows:
Changing the signature a bit so now you have a pointer to an already allocated node:
void insertNode(node *&root, node *newNode) {
if (root == NULL) {
root = newNode;
return;
}
if (root->left == NULL) {
root-left = newNode;
return;
}
helperInsert(root->left, newNode);
return;
}
This will set the head (assuming I got the signature right), and otherwise check the left child.
void helperInsert(node *it, node *newNode) {
if (it->left == NULL) {
it->left = newNode;
return;
}
helperInsert(it->left, newNode);
return;
}
This is obviously a flawed approach (the tree will not be balanced at the slightest), almost treating the tree as a linked list, but to my best understanding of the question, this is an example of how it can be done.
In
else if (root->left == NULL)
root->left=insert(root->left,key);
you know root->left is NULL so why to do the recursive call ?
Of course same for the next else
The following code only works for the very first three nodes.
If both left and right are non NULL you do not insert, that time it was necessary to do the recursive call on one of the two branches, and you will consider the key (so insert ordered) to decide which one. Note that the 2 tests to NULL you did are not correct if you insert to have a sorted tree ...
The heap advice is most sound. You don't need to heapify anything, just follow the rules that an element at index k has children at 2*k + 1 and 2*k + 2.
Another approach, useful when there is no array, but the nodes are generated on the fly, is to fill the tree level-wise. Notice that at level k there are 2 ** k slots, conveniently indexed by a k-bit integer. Interpret the index as a path down the tree (clear bit tells to follow left child, set bit tells to follow a right one), along the lines of:
void insert_node(struct node * root, struct node * node, unsigned mask, unsigned path)
{
while ((mask >> 1) != 1) {
root = mask & path? root->right: root->left;
}
if (mask & path) {
assert (root->right == NULL);
root->right = node;
} else {
assert (root->left == NULL);
root->left = node;
}
}
void fill_level_k(struct node * root, unsigned k)
{
unsigned slots = 1 << k;
for (unsigned slot = 0; slot < slots; slot++) {
struct node * node = generate_new_node();
insert_node(root, node, slots, slot);
}
}
Related
I am trying to find the depth of a specific node noted by a pointer in c, but I cant seem to get it right
int depth(Node *root, Node *N){
// Need to find the root N
// At the same time count how many depths you can go down
// If the root is NULL, then no tree and return -1
if (root == NULL){
return -1;
}
// If the root node equals the node N, then return 0
if (root->data == N->data){
return 0;
}
// Search the tree and add one each time recursion called
int count = -1;
if (N->data < root->data){
root->left->data = depth(root->left, N);
count++;
}
else if (N->data > root->data){
root->right->data = depth(root->right, N);
count++;
}
else{
}
return count;
}
Any help in solving this would be appreciated.
The pseudo code for such a function is along the lines of this, assuming root = level 0:
int search (const node_t* node, int level)
{
if(node == NULL)
return -1;
if(node->data == key)
return level;
const node_t* node next;
if(node->data < key)
next = node->right;
else if(node->data > key)
next = node->left
return search (next, level+1);
}
First called as search(root, 0);
Though as usual, recursion in C is almost certainly the wrong solution to any problem. The above can rather trivially be rewritten as sane, readable, fast loops instead.
I have a function that deletes all words starting with the same first letter in a avl binary tree(letter is given by user).
node_t* delete_from_tree(node_t* root, char search, int *deleted)
{
int cmp;
node_t* new_node = NULL;
if (root == NULL)
return root;
else
{
cmp = root->data[0] - search;
if (cmp == 0)
{
*deleted += 1;
new_node = delete_node(root, root->data);
return delete_from_tree(root, search, deleted);
}
else if (cmp > 0)
{
new_node = delete_from_tree(root->left, search, deleted);
}
else
{
new_node = delete_from_tree(root->right, search, deleted);
}
}
return root;
}
It deletes the words from tree but i cannot understand why unnecessary characters are printing when i call tree traversal.
void print_inorder(node_t* node)
{
if (node == NULL)
return;
print_in(node->left);
printf("%s ", node->data);
print_in(node->right);
}
Example: words in a tree: life, value, administation, advantage, add, son.
Expected output:
life, son, value.
Real output:
{t life, son, value.
Note: This is not a definite answer, but it's too long for a comment space.
You didn't show what new_node = delete_node(root, root->data); does to the tree structure, but most probably it deletes the node pointed at by the root variable.
If so, the root pointer becomes invalid on the return from delete_node(), hence the recursive call in the return statement
return delete_from_tree(root, search, deleted);
makes the called function to operate on a non-NULL, anyway invalid root pointer.
Hello stackoverflowers,
i am facing a problem with my function in C, i want to create a function that give me the min and max value in BST.
The problem is when i use this function it returns the same value for min and max:
void Find_Min_Max(node *bt,int* maxint,int* minint)
{
node *tmp = bt;
if( bt == NULL)
{
*maxint = 0; // Only if the tree contains nothing at all
*minint = 0; // Only if the tree contains nothing at all
}
if( bt->left)
return Find_Min_Max(bt->left,&(*maxint),&(*minint));
*minint = bt->data;
if( tmp->right)
return Find_Min_Max(tmp->right,&(*maxint),&(*minint));
*maxint = tmp->data;
}
But when i use it to give me just one result max/min, i delete this part of code, everything work perfectly:
if( tmp->right)
return Find_Min_Max(tmp->right,&(*maxint),&(*minint));
*maxint = tmp->data;
Any idea how this will work?.
Thank you in advance.
It's not really easy / intuitive to recursively compute max and min at the same time in the same function. I would even say it's not possible, because those are two completely different traversals.
You should have a function to get the minimum, a function to get the maximum, and call each of them inside Find_Min_Max.
This would be a possible approach:
int find_min(node *n) {
if (n == NULL) {
return 0;
}
while (n->left != NULL) {
n = n->left;
}
return n->data;
}
find_max is similar, but traverses right links only:
int find_max(node *n) {
if (n == NULL) {
return 0;
}
while (n->right != NULL) {
n = n->right;
}
return n->data;
}
Then, find_min_max() is easy to code:
void find_min_max(node *bt, int *min, int *right) {
*min = find_min(bt);
*max = find_max(bt);
}
find_min() and find_max() could be recursive, but the iterative approach has the desirable property of using constant memory (and consequently avoids stack overflows).
To find the minimum value in a BST, you follow the chain of left children from the root until you reach a node with no left child. That node contains the minimum value (even if it does have a right child).
The algorithm to find the maximum is exactly the mirror image: follow the chain of right children until you reach a node with no right child. That node contains the maximum value.
It does not make sense to try to perform both traversals at the same time, because they follow completely different paths. If you want a single function to discover both the minimum and the maximum value, then it doesn't make much sense for that function itself to be recursive. It could, however, wrap calls to two separate recursive functions, one to find the minimum, and the other to find the maximum.
Finding min and max value in a BST are very easy. Please check both code snippet below I explain how these codes work.
public int minValueInBST(Node node){
if (node == null) throw new IllegalStateException();
Node current = node;
while (current.leftChild != null) {
current = node.leftChild;
}
return current.value;
}
To find the minimum value in BST we have to find the leftmost leaf node because that node contains the minimum value. So at first, we check the root node is null or not if null we throw IllegalStateException otherwise we find the left node, at last, we return the left node value.
public int maxValueInBST(Node node){
if (node == null) throw new IllegalStateException();
Node current = node;
while (current.rightChild != null) {
current = node.rightChild;
}
return current.value;
}
To find the maximum value in BST we have to find the rightmost leaf node because that node contains the maximum value. So at first, we check the root node is null or not if null we throw IllegalStateException otherwise we find the right node, at last, we return the right node value.
// try this
tree_node *min(tree_node *root)
{
if (!root)
{
printf("Tree is empty");
exit(1);
}
tree_node *ret_val;
if (root->left == NULL)
{
ret_val = root;
}
else
{
ret_val = min(root->left);
}
return ret_val;
}
tree_node *max(tree_node *root)
{
if (!root)
{
printf("Tree is empty");
exit(1);
}
tree_node *ret_val;
if (root->right == NULL)
{
ret_val = root;
}
else
{
ret_val = max(root->right);
}
return ret_val;
}
complete code
Well, I've been at it for a while...trying to figure out an algorithm to insert my list of random numbers into a binary tree.
This is what I have gotten so far:
NodePtr and Tree are pointers to a node
NodePtr CreateTree(FILE * fpData)
{
int in;
fscanf(fpData, "%i", &in);
Tree T = (NodePtr)malloc(sizeof(Node));
T->Left = NULL;
T->Right = NULL;
T->value = in;
while((fscanf(fpData, "%i", &in)) != EOF)
{
InsertInTree(in, T);
printf("\n %p", T);
}
return T;
}
void InsertInTree(int value,Tree T)
{
if(T == NULL)
{
T->Left = (NodePtr)malloc(sizeof(Node));
T->Left->Left = NULL;
T->Left->Right = NULL;
T->Left->value = value;
printf("\n %i ", value);
return;
}
if(T->Left == NULL)
{
InsertInNull(value, T->Left);
}
else if(T->Right == NULL)
{
InsertInNull(value, T->Right);
}
else
{
if(T->Left->Left == NULL || T->Left->Right == NULL) InsertInTree(value, T->Left);
else InsertInTree(value, T->Right);
}
}
I'm lost on what to do if the both children of a particular node are not null. What I did here works for a small amount of numbers (1,2,3,5,6) but if the list is larger it becomes unbalanced and wrong.
Is it meant to be a search-tree? I don't see any if (value < T->Value) conditions.
And you have an InsertNull (not shown). That shouldn't be necessary, 1 function should be enough.
To address your main problem, use a pointer-to-pointer parameter or, more elegant, always return a new Tree:
//untested, no balancing
Tree InsertValue(Tree t, int value)
{
if (t == null)
t = // create and return new node
else
{
if (value < t->Value)
t->Left = InsertValue(t->Left, value);
else
t->Right = InsertValue(t->Left, value);
}
return t;
}
And in CreateTree:
Tree t = InsertValue(null, in);
Since the assignment is not for a sorted tree, you can populate it in a breadth-first manner. This means the first thing inserted is always the root, the next is the first node at the next level so it looks like this:
0
1 2
3 4 5 6
Here is an article that explains it further:
http://www.cs.bu.edu/teaching/c/tree/breadth-first/
Simple insertion in a binary tree and keeping a binary tree balanced are different problems. I suggest you start with the first problem and just focus on keeping order properties correct within the tree. Your are not far from that.
Then you should have a look at classical implementations for red-black trees, well studied and efficient way of keeping trees balanced, but with a cost, it's more complex.
I'm trying to insert nodes into a tree in order. My function works fine... when there's only three nodes.
I have this code:
typedef struct _Tnode Tnode;
struct _Tnode {
char* data;
Tnode* left;
Tnode* right;
};
Along with this:
Tnode* add_tnode(Tnode* current_node, char* value) {
Tnode* ret_value;
if(current_node == NULL) {
current_node = (Tnode*) malloc(sizeof(Tnode));
if(current_node != NULL) {
(current_node)->data = value;
(current_node)->left = NULL;
(current_node)->right = NULL;
ret_value = current_node; }
else
printf("no memory");
}
else {
if(strcmp(current_node->data,value)) { //left for less than
ret_value = add_tnode((current_node->left), value);
current_node -> left = (Tnode*) malloc(sizeof(Tnode));
(current_node -> left) -> data = value;
}
else if(strcmp(current_node->data,value) > 0) {
ret_value = add_tnode((current_node -> right), value);
current_node -> right = (Tnode*) malloc(sizeof(Tnode));
(current_node -> right) -> data = value;
}
else {
printf("duplicate\n");
ret_value = current_node;
}
}
return ret_value;
}
I know what's wrong here, I just don't know how to fix it. This just overwrites the two nodes attached to the root node. i.e.
|root_node|
/ \
|node_2| |node_3|
I can't add a node four. It just overwrites node 2 or 3 depending on the input. After debugging and a little research, I'm not quite sure where to go from here...
If anyone can help, I'd really appreciate it.
You should leave the mallocing only to the case where the insertion reaches a leaf node (ie NULL). In the other cases, all you should do is to traverse to the next level depending on your comparison. In your case, you're traversing to the next level, and then killing it with a new malloc. Because of this you're never getting past the first level.
eg.
if (current_node == NULL) // Do initialization stuff and return current_node
if (strcmp(current_node->data, value) < 0) {
current_node->left = add_tnode((current_node->left), value);
} else if (strcmp(current_node->data, value) > 0) {
current_node->right = add_tnode((current_node->right), value);
}
return current_node;
This would appear to just be a school project.
Where to begin.
1) You are clobbering left/right all the way down the tree. I'm not sure why you would expect them to be preserved since:
a) You always write to these nodes.
b) The only time you return an existing node is on a strcmp match.
2) You really need to check strcmp < 0 on your first compare.
3) For a non-balanced tree, there's no reason to use recursion - you can just use a loop until you get to a leaf and then hook the leaf. If you really want recursion...
4) Recursive... Return NULL in all cases except when you create a node (ie: the first part where you have current == NULL).
5) In the left/right, store the return value in a temp local Node*. Only if the return value is not NULL should you assign left/right.
Even this doesn't feel right to me, but if I started from scratch it just wouldn't look like this at all. :) We won't even get into the memory leaks/crashes you probably will end up with by just pushing 'char *' values around all willy nilly.
struct _Tnode {
char* data;
struct _Tnode * left, * right;
};
typedef struct _Tnode Tnode;
void addNode(Tnode ** tree, Tnode * node){
if(!(*tree)){
*tree = node;
return;
}
if(node->data < (*tree)->val){
insert(&(*tree)->left, node);
}else if(node->data>(*tree)->data){
insert(&(*tree)->right, node);
}
}
for starters - the first strcmp
if(strcmp(current_node->data,value))
is probably not right - this is true for both less than and greater than, and then the second if does not make sense
I guess that you'll need to add a pointer to the parent node to the _Tnode struct.
The problem is that after making your recursive function call to add_tnode, on the left branch, say, you are obliterating that same branch with your malloc. The malloc should only happen when you have recursed down to the point where you will be adding the node, not when you are making a recursive call.
Essentially, in a particular function call, you should either make a recursive call OR malloc a new node, not both.
This also produces a memory leak, probably.
If you aren't implementing this for your own edification, I would just use libavl
You don't need to know the parent of the node. just the value at the current node.
Pseudocode:
add_treenode(root, value)
{
//check if we are at a leaf
if root == null
allocate space for new node.
set children to null
save root->value = value
return root // if you need to return something, return the node you inserted.
//if not, this node has a value
if root->value < value //use strcmp since value is a string
add_tnode(root->left, value)
else
add_tnode(root->right, value)
return NULL
}
This is as clean as it gets when it comes to inserting a new tree node. pass the root and the value of the node you want to insert, and it does the rest.
Once you found out, that current_node->data is not null and compared it with value, you first have to check whether the corresponding pointer current_node->left (or ->right) is already in use (!= NULL).
If it is null, you proceed as you do. That is the case that works fine now.
If not, you have to retest the whole thing against the correspondig node, calling your function again on the cooresponding node. Here some pseudo code:
Wrap the code with:
void Add_node(Tnode* current_node) {
...
else {
if(strcmp(current_node->data,value) < 0) { //left for less than
if(current_node->left != NULL) {
Add_node(current_node->left);
} else {
ret_value = add_tnode((current_node->left), value);
current_node -> left = (Tnode*) malloc(sizeof(Tnode));
(current_node -> left) -> data = value;
} else if(strcmp(current_node->data,value) > 0) {
Add_node(current_node->right);
} else {
...
}
This is called recoursion (a function callin itself) and walk through the tree. To read some node, you have to do a recursive function again. Be carefull that they terminate (here at some point the left or right pointer will be null, thus terminating the recursive calling).