How to add node to binary tree in C? - c

How do I add more nodes to my binary tree if A (left) and B (right) are already full? I just need to create a tree that is balanced. But I can't figure out how to add more data to the tree. Any help would be greatly appreciated.
Thanks in advance for any tipps.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct node
{
char *titel;
struct node *A;
struct node *B;
};
void display(struct node *leaf)
{
if (leaf != NULL)
{
display(leaf->A);
printf("%s\n",leaf->titel);
display(leaf->B);
}
}
struct node *insert(char* titel, struct node **leaf)
{
if (*leaf == 0)
{
*leaf = (struct node*)malloc(sizeof(struct node));
(*leaf)->titel = malloc(strlen(titel)+1);
strcpy((*leaf)->titel,titel);
(*leaf)->A = NULL;
(*leaf)->B = NULL;
}
else if ((*leaf)->A == NULL)
{
(*leaf)->A = insert(titel,&(*leaf)->A);
}
else if ((*leaf)->B == NULL )
{
(*leaf)->B = insert(titel,&(*leaf)->B);
}
//WHAT TO ADD HERE TO CREATE ANOTHER NODE?
return(*leaf);
}
int main(int argc, char const *argv[])
{
struct node *root = NULL;
insert("root",&root);
insert("chapter_1A",&root);
insert("chapter_1B",&root);
insert("chapter_2A",&root);
insert("chapter_2B",&root);
insert("chapter_3A",&root);
display(root);
return 0;
}
Output should be like a balanced binary tree. Mustn't be printed but stored like that in memory.
Actual output:
chapter_1A
root
chapter_1B
root
/ \
chapter_1A chapter_1B
/ \ / \
ch_2A ch_2B ch_3A ch_3B
and so on.

How do I add more nodes to my binary tree if A (left) and B (right) are already full?
By "full" I take it that you mean both child nodes themselves have two children. In this case, any new node must be added to one of the children of the children. Typically you would do this via a recursive function, so that it correctly handles the case when the children's children are also "full", and so on.
I just need to create a tree that is balanced
(Note that "balanced" can itself mean several things. For instance, there are "height balanced" and "weight balanced" trees. You don't specify which you want).
The question then is which (full) child to add a new node to - right or left? One option is to keep a count of the total descendants of each node, and always add to the child which has the fewest.
Another option is to keep count of the total number of nodes in the tree, and use the bits in that number (ignoring the first 1 bit) to decide on where to insert the new node. For example, if you have a tree with 5 nodes:
A
B C
D E
To add a new node, increment the node count to 6, which is 110 in binary. Ignore the first 1; interpret the next 1 as "go right" (which takes you to C) and the following 0 as "go left" (which tells you to insert as the left child of C). Your code becomes something like this:
void insert(char* titel, struct node **leaf, int nodeCount, int bitPos)
{
if (*leaf == 0)
{
*leaf = (struct node*)malloc(sizeof(struct node));
(*leaf)->titel = malloc(strlen(titel)+1);
strcpy((*leaf)->titel,titel);
(*leaf)->A = NULL;
(*leaf)->B = NULL;
}
else
{
int currentBit = (nodeCount >> bitPos) & 1;
if (currentBit == 0) {
// insert to left
insert(titel, &((*leaf)->A), nodeCount, bitPos - 1);
}
else
{
// insert to right
insert(titel, &((*leaf)->B), nodeCount, bitPos - 1);
}
}
}
Notice I changed the return type to void since you don't need to return a value. I'll leave the calculation of the initial bitPos value as an exercise (remember: it's the position of the highest order 1 bit, minus 1).
If you also need to remove elements from the tree, you will need to find a way to re-balance it, however.
Note that there are several data structures and algorithms for maintaining balanced trees which support both insertion and deletion. See red-black trees and AVL trees for example. These are usually used for ordered trees, but it should be trivial to adapt them for an unordered-but-balanced tree.

Related

largest leaf node in a tree.how to prevent getting a 0 when leaf nodes are negative

I have to find the largest leaf node in a BST but it only has the shape of a BST not the properties. The right most node is not the largest and the left most is not the smallest.
So far I have created code that I think would work for most cases except negative cases.
typedef Struct BST
{
int data;
struct BST *left;
struct BST *right;
}Tree;
The above is just the structure of the node
int largest_leaf(Tree *head)
{
if(head == NULL)
{
printf("Heyall\n");
return 0;
}
if(head -> right == NULL && head -> left == NULL)
{
printf("head -> data: %d\n", head -> data);
return head -> data;
}
int i = largest_leaf(head -> left);
int r = i;
i = largest_leaf(head -> right);
if(i > r)
{
r = i;
}
return r;
}
I know my code may be confusing. But to simplfy it, since this is in a shape of a tree I am going to be traversing to one edge (In this case the left) and then return the leaf value and do the same for every value there after.
My question is how do I fix the problem of getting a zero for the case of all negative values in the leaf node.
edit: the tree is not empty
I have to find the largest leaf node in a BST but it only has the shape of a BST not the properties. The right most node is not the largest and the left most is not the smallest.
You have to traverse the whole tree and use the same basic algorithm you'd use for an array. Instead of 0 as the smallest number, use the smallest possible integer: INT_MIN.
As mentioned by kaylum, you need to consider what happens when the tree is empty. Does it return INT_MIN? Do you need a separate error flag?

Convert heap implemented in array to tree

I have this homework where I have to convert a min-heap represented in array:
DEFINE #SIZE
typedef int Heap[SIZE]
and implement it in a tree like so:
typedef struct node{
int val;
struct no *left, *right;
} Node, *Tree;
and as a reminder the index of min-heaps arrays is as follows:
#DEFINE PARENT(i) (i-1)/2
#DEFINE LEFT(i) 2*i + 1
#DEFINE RIGHT(i) 2*i + 2
so, how do I do this?
I started on something like this:
Tree heapToTree(int * heap){
Tree *t = malloc(sizeof(struct node));
t->val = heap[0];
Tree *aux = t; //save initial tree position
for(i=0;i<SIZE;i++){
aux->left=malloc(sizeof(struct Node));
aux->left->val=heap[i*2 +1];
aux->right=malloc(sizeof(struct Node));
aux->right->val=heap[i*2 +2];
}
Am I on the right path? I think this should be done recursively, but how?
thanks in advance
There is one thing that you are lacking is - not making the newly created node's links (left and right) to the NULL initially. No matter what, any kind of tree implementation this is very useful - helps in traversal, finding an element (which is again a traversal) etc.
Also in the loop you didn't change the value of aux (or atleast you didn't show) - as a result you are writing over the old values and having memory leak.
Apart from that not checking the return value of malloc is another point. You should check the return value of malloc - if NULL then you should handle that distinctly (error handling) from that of usual code flow.
Considering that heap is implemented in an array (0-index) you can do this to convert it to tree.
struct node *convIntoTree(int pos,int sz, int *heap){
if(pos >= sz ) return NULL;
struct node* root = malloc(sizeof *root);
if( root == NULL ){
perror("Malloc failed");
exit(EXIT_FAILURE);
}
root->data = heap[pos];
root->left = convIntoTree(pos*2+1,sz);
root->right = convIntoTree(pos*2+2,sz);
return root;
}
Call it like this
struct node *root = convToTree(0,heapsize,heap);
The solution is simply applying a brute force method of traversing every node of the heap and then allocate memory for it and populate it's left and right child recursively.

Inserting millions of Elements into a Binary Search Tree BST

I have been trying to solve this issue for almost 3 days with no luck yet. I am trying to insert many elements is size of (5 million)of unsigned integer into a binary tree.
This code works fine when I limit the total elements to be inserted into 10K, however, it does not work when I set the total elements to be 5 million.
I am running this code on my PC which has:
Windows 7 - 32
RAM 4 GB
Any help would be really appreciated. Thanks in advance :)
Here is my code:
#include<stdlib.h>
#include<stdio.h>
typedef int ElementType;
typedef struct TreeNode {
ElementType element;
struct TreeNode *left, *right;
} TreeNode;
TreeNode *createTree(){
//Create the root of tree
TreeNode *tempNode;
tempNode = malloc(sizeof(TreeNode));
tempNode->element = 0;
tempNode->left = NULL;
tempNode->right = NULL;
return tempNode;
}
TreeNode *createNode(ElementType X){
//Create a new leaf node and return the pointer
TreeNode *tempNode;
tempNode = malloc(sizeof(TreeNode));
tempNode->element = X;
tempNode->left = NULL;
tempNode->right = NULL;
return tempNode;
}
TreeNode *insertElement(TreeNode *node, ElementType X){
//insert element to Tree
if(node==NULL){
return createNode(X);
}
else{
if(X < node->element){
node->left = insertElement(node->left, X);
return node; // add this.
}
else if(X > node->element){
node->right = insertElement(node->right, X);
return node; // add t
else if(X == node->element){
printf("Oops! the element is already present in the tree.");
}
}
}
TreeNode *displayTree(TreeNode *node){
//display the full tree
if(node==NULL){
return;
}
displayTree(node->left);
printf("| %d ", node->element);
displayTree(node->right);
}
main(){
//pointer to root of tree #2
TreeNode *TreePtr;
TreeNode *TreeRoot;
TreeNode *TreeChild;
//Create the root of tree
TreePtr = createTree();
TreeRoot = TreePtr;
TreeRoot->element = 32;
for ( int i=0; i < 5000000; i ++)
insertElement(TreeRoot, i);
displayTree(TreeRoot);
}
Any help would be really appreciated. Thanks in advance :)
Assuming that you have no other errors in your code, always inserting 8 will degenerate the tree to a list, and I think, your stack will overflow at some recursion level far below the 5 million.
To generally avoid a degenerated tree, I would advise you to use the insert/deletion semantics of an AVL-Tree.
This has the advantage, that your datastructures can remain as they are, but you only have to adapt the insert and delete procedures.
Edit: In your comment, you state now that you do not insert always 8 but i. This means, you insert pre-sorted elements into the binary tree, which also degenerates it to a list, so the same problem arises as with always inserting "8".
It looks like:
1
\
2
\
3
\
4
\
...
after inserting the elements in order.
An AVL-Tree will not suffer from that problem:
https://en.wikipedia.org/wiki/AVL_tree
OK Faisal.
If you insert the value of i, then you will always insert a key greater than all the keys currently contained in the tree. Consequently you will get a tree of maximum height, which in performance (and shape too) is equivalent to a list. Since you algorithm is recursive, you will get a stack overflow very quickly.
A possible way for dealing with you problem, but is not a guarantee for avoiding an overflow, is to insert random keys. Theoretically, the average on the number of nodes revised in an unsuccessful search is O(log N).
So you could use the rand() for getting random numbers or a more sophisticated and sure random number generator.

Simple inorder tree traversal giving a non terminating loop. (using arrays)

Following is my code for building a simple tree. The approach I'm using here is that if a particular node is at index n in the arr[] array, then it has it's left child at index 2*n+1 and right child at 2*n+2 in the same arr[] array. And then I'm doing an inorder traversal. However, I'm getting an infinite loop at node D as my output. Would love if anybody could help me out here.
#include <stdio.h>
#include <malloc.h>
struct node
{
struct node * lc;
char data;
struct node * rc;
};
char arr[] = {'A','B','C','D','E','F','G','\0','\0','H','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
struct node * root = NULL;
struct node * buildTree(int rootIndex)
{
struct node * temp = NULL;
if(arr[rootIndex]!='\0')
{
temp = (struct node *)malloc(sizeof(struct node));
temp->lc = buildTree(rootIndex * 2 + 1);
temp->data = arr[rootIndex];
temp->rc = buildTree(rootIndex * 2 + 2);
}
return temp;
}
void inorder(struct node * parent)
{
while(parent != NULL)
{
inorder(parent->lc);
printf("%c\t",parent->data);
inorder(parent->rc);
}
}
int main()
{
root = buildTree(0);
inorder(root);
return 0;
}
Like BLUEPIXY mentioned in comments, you need to replace the while in inorder() method with an if. When building tree, D forms the left-most child. Therefore during in-order traversal, D is encountered as the first node to be printed. But the while loop keeps printing it as the condition never becomes false.
I'm sure a tool like gdb would have done much better job in explaining this.

Problem with pointers in binary search tree deletion

I am trying to implement binary search tree operations and got stuck at deletion.
11
/ \
10 14
Using inorder traversal as representation of tree initially output is 10 11 14.
Deleting node 10, output expected is 11 14 but I am getting 0 11 14.
Deleting node 14, output expected is just 11 but I am getting 0 11 67837.
Please explain why I am getting wrong output. I am not looking for any code :).
typedef struct _node{
int data;
struct _node *left;
struct _node *right;
} Node;
Node* bstree_search(Node *root, int key)
{
if(root == NULL){
return root;
}
// Based on binary search relation, key can be found in either left,
// right, or root.
if(key > root->data)
return bstree_search(root->right, key);
else if(key < root->data)
return bstree_search(root->left, key);
else
return root;
}
void bstree_insert(Node **adroot, int value)
{
// since address of address(root is itself address) is passed we can change root.
if(*adroot == NULL){
*adroot = malloc(sizeof(**adroot));
(*adroot)->data = value;
(*adroot)->right = (*adroot)->left = NULL;
return;
}
if(value > (*adroot)->data)
bstree_insert(&(*adroot)->right, value);
else
bstree_insert(&(*adroot)->left, value);
}
void bstree_inorder_walk(Node *root)
{
if(root != NULL){
bstree_inorder_walk(root->left);
printf("%d ",root->data);
bstree_inorder_walk(root->right);
}
}
void bstree_delete(Node **adnode)
{
//Node with no children or only one child
Node *node, *temp;
node = temp = *adnode;
if((*adnode)->right == NULL || (*adnode)->left == NULL){
if((*adnode)->right == NULL){
*adnode = (*adnode)->left;
}else{
*adnode = (*adnode)->right;
}
}else{ // Node with two children
}
free(temp);
}
int main()
{
Node *root = NULL;
Node *needle = NULL;
int i,elems[] = {11,10,14};
for(i = 0; i < 3; ++i)
bstree_insert(&root,elems[i]);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 10);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 14);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
}
Please explain why I am getting wrong
output.
Your delete function must also change the parent of the deleted Node. For example, when you delete the node holding 10, you must set the root Node's left child to NULL. Since you don't do this, when you later traverse the tree, you print out data that has already been freed.
I did not look at any code other than delete, so I can't make any guarantees about it working once this change is made.
You're getting wrong output because your deletion code is buggy (okay, maybe that's stating the obvious).
To delete from a binary search tree, you first find the node to be deleted. If it's a leaf node, you set the pointer to it in its parent node to NULL, and free the node. If it's not a leaf node, you take one of two leaf nodes (either the left-most child in the right sub-tree, or the right-most child in the left sub-tree) and insert that in place of the node you need to delete, set the pointer to that node in its previous parent to NULL, and delete the node you've now "spliced out" of the tree.
A couple of things really quick,
first when you allocate the node, you really should be doing the malloc on the sizeof the type (ie Node).
Second, if you have 2 children it looks like you are not really deleting the node and rebuilding the search tree by promoting one of the children.
Other people have already got you other obvious errors.

Resources