I'm implementing an binary search tree but for some reasons I 'm not able to add a node
my: input was :
a.value = 5;
add_bst_node(&t,a);
mystructures:
typedef struct BST_node{
entity value;
struct BST_node* left;
struct BST_node* right;
}BST_node;
typedef struct BST_tree{
BST_node* root;
}BST_tree;
my code for add a node:
void add_bst_node2(BST_node* root,entity* e){
if(!root){
root = (BST_node*)malloc(sizeof(BST_node));
root->value = *e;
root->left = NULL;
root->right = NULL;
return;
}
else if(great_than(&root->value,e))
add_bst_node2(root->left,e);
else
add_bst_node2(root->right,e);
}
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t->root,&e);
printf("%d\n",t->root==NULL);
}
Someone can explayn why I'can't add a node?
Apart from not passing double pointer to BST_node (i.e. BST_node**) in add_bst_node2() as noted in the comments, you also didn't implement the function properly.
Your implementation never really adds a node, but instead in enters into infinite recursion.
Here you can find some clean theory about BST - http://www.zentut.com/c-tutorial/c-binary-search-tree/
Here is an untested correction of your code. Note that here we pass pointer to BST_tree instead of BST_node
void add_bst_node2(BST_tree* tree,entity* e){
if(!tree->root){
/* If the binary search tree is empty, we just create a root node */
tree->root = bst_create_node(e);
return;
}
int is_left = 0;
BST_node* current_node = tree->root;
BST_node* prev = NULL;
/* Traverse the tree until we find the proper position for the new node.
* The position is denoted by 'current_node'
*/
while(current_node != NULL) {
prev = current_node;
if(greater_than(¤t_node->value, e)) {
is_left = 1;
current_node = current_node->left;
} else {
is_left = 0;
current_node = current_node->right;
}
}
/* We finally know the position where we should add the new node */
if(is_left)
prev->left = bst_create_node(e);
else
prev->right = bst_create_node(e);
}
We introduce another function for creating and initializing a node...
BST_node *bst_create_node(entity *e)
{
BST_node *n = malloc(sizeof(BST_node));
n->value = *e;
n->left = NULL;
n->right = NULL;
return n;
}
And finally we change add_bst_node()
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t, &e);
printf("%d\n", t->root==NULL);
}
From what it seems, a is a struct BST_node and value is a variable in it. You have to either pass the value to the function and handle the node creation there, or pass the whole constructed node and just point to it from the existing tree.
first thing is that you put an unnecessary structure BST_tree.You do it in simple way like
struct node
{
int value;
node* left;
node* right;
};
struct node* root;
I suggest you try with this code
struct node* insert(struct node* r, int data)
{
if(r==NULL) // BST is not created created
{
r = (struct node*) malloc(sizeof(struct node)); // create a new node
r->value = data; // insert data to new node
// make left and right childs empty
r->left = NULL;
r->right = NULL;
}
// if the data is less than node value then we must put this in left sub-tree
else if(data < r->value){
r->left = insert(r->left, data);
}
// else this will be in the right subtree
else {
r->right = insert(r->right, data);
}
return r;
}`
`
Related
I have a problem that I cannot introduce a temp NODE* and iterate to find the next NODE that is NULL (I marked it in the code with comment).
But, if I do:
parent->child->next->next = result
It works completely fine.
Any help?
typedef struct tNODE {
char* inner_text;
char* tag;
struct tNODE* parent;
struct tNODE* child;
struct tNODE* next;
}NODE;
NODE* new_node(NODE* parent){
NODE* result = (NODE*)malloc(sizeof(NODE));
result->inner_text = NULL;
result->tag = NULL;
result->parent = parent;
result->child = NULL;
result->next = NULL;
if (parent != NULL){
if (parent->child == NULL){
parent->child = result;
} else {
if (parent->child->next == NULL){
parent->child->next = result;
return result;
} else {
//HERE IS THE PROBLEM. A TEMP NODE DOES NOT WORK
//BUT parent->child->next->next = result works. WHY ? what should i do
NODE* temp = parent->child->next;
while(temp != NULL){
temp = temp->next;
}
temp = result;
}
}
}
return result;
}
If the parent has no children, you set the new node as the 1st child. OK.
If the parent has 1 child, you set the new node as the 2nd child. OK.
But, if the parent has more than 2 children, you are looping to the end of the child list, which is where you are going wrong. You are setting temp to point at each child in the list, and break the loop only when temp becomes NULL, meaning it is not pointing at any node at all, as you went beyond the end of your list. You lost track of the last child in the list. And then you are setting temp to point at the new node, but temp does not refer to the last child's next pointer in the list, so assigning it a value does not update the list at all.
Your logic needs to look more like this instead:
NODE* new_node(NODE* parent){
NODE* result = (NODE*) malloc(sizeof(NODE));
if (!result)
return NULL;
// in C++, use this instead:
// NODE* result = new NODE;
result->inner_text = NULL;
result->tag = NULL;
result->parent = parent;
result->child = NULL;
result->next = NULL;
if (parent){
// if no children yet, assign the
// new node as the first child ...
if (!parent->child){
parent->child = result;
} else {
// find the last child ...
NODE *temp = parent->child;
while (temp->next){
temp = temp->next;
}
// ... and set it to point at the
// new node as the next child ...
temp->next = result;
}
}
return result;
}
That being said, the logic can be simplified a bit more. Try this instead:
NODE* new_node(NODE* parent){
NODE* result = (NODE*) malloc(sizeof(NODE));
if (!result)
return NULL;
result->inner_text = NULL;
result->tag = NULL;
result->parent = parent;
result->child = NULL;
result->next = NULL;
if (parent){
// find the last NODE* pointer that is NULL ...
NODE **temp = &(parent->child);
while (*temp) {
temp = &((*temp)->next);
}
// ... and set it to point at the new node ...
*temp = result;
}
return result;
}
And, if you are free to add another member to your NODE type, the logic becomes even simpler as the entire loop can then be eliminated completely, eg:
typedef struct tNODE {
char* inner_text;
char* tag;
struct tNODE* parent;
struct tNODE* first_child;
struct tNODE* last_child;
struct tNODE* next;
}NODE;
NODE* new_node(NODE* parent){
NODE* result = (NODE*) malloc(sizeof(NODE));
if (!result)
return NULL;
result->inner_text = NULL;
result->tag = NULL;
result->parent = parent;
result->first_child = NULL;
result->last_child = NULL;
result->next = NULL;
if (parent){
NODE **temp = (parent->last_child)
? &(parent->last_child->next)
: &(parent->first_child);
*temp = result;
parent->last_child = result;
}
return result;
}
The assignment to temp can never change the linked list. To modify the linked list you need to dereference temp when it still points to the tail node, and then assign to its next member.
So that means you need to stop the loop one iteration earlier:
NODE* temp = parent->child;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = result;
Note that you don't need the innermost if as a special case. The case where parent->child->next == NULL can be dealt with using the code above.
Look at the two alternatives, they are quite different
parent->child->next->next = result;
and
NODE* temp = parent->child->next;
while(temp != NULL){
temp = temp->next;
}
temp = result;
The first one assigns to the next field of parent->child->next. The second assigns to the temp variable. These are not the same thing, it doesn't matter where the temp variable is pointing to when you make the assignment, the temp variable is not any part of your linked list.
Here is what your code should look like
NODE* temp = parent->child;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = result;
In this code temp points to the node whose next field you want to change.
I am trying to implement the insert operation of a binary search tree using C. Why does the following code show a Segmentation fault when trying to print the value of the left and right nodes of the root?
Please explain what caused this error exactly.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* left;
struct node* right;
};
struct node *root, *temp = NULL;
void insert(int data) {
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
if (root == NULL){
// if tree is empty insert the node as root
root = newNode;
}else {
// if the tree is not empty
temp = root;
while(temp != NULL) {
if(data <= root->data) {
temp = temp->left;
}
if(data > root->data) {
temp = temp->right;
}
}
temp = newNode;
}
}
int main() {
insert(7);
insert(4);
insert(8);
printf("\n\n------%d------", root->left->data);
printf("\n\n------%d------", root->right->data);
return 0;
}
The assignment temp = newNode only stores a pointer in the temp variable, not somewhere in the tree. So your tree's root node will never get any child. By consequence the main program is dereferencing a root->left pointer that is NULL, and this explains the error you get.
In order to really attach the new node at the right place in the tree, you need to modify a left or right member of some node. You can do this in several ways. One is to make temp a pointer-pointer, so that it will have the address of a left or right member. Then the assignment to *temp, will be an assignment to a node's left or right member, effectively extending the tree with that new node.
Here is the updated part of the code:
struct node **temp = &root;
while(*temp != NULL) {
if(data <= root->data) {
temp = &(*temp)->left;
}
if(data > root->data) {
temp = &(*temp)->right;
}
}
*temp = newNode;
okay you have a few issues here,
first of all, temp will point back to newNode, as you have not copied newNode's values to where temp is pointing now.
second and no less important, newNode is created within the scope of insert() - therefore, root will always remain null, as root points after execution of insert() to data wich no longer exists.
I have improved your code, and this definitely works as expected
hope it has helped.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node* left;
struct node* right;
}node;
node *root=NULL;
void insert(int data) {
node *temp = NULL;
if (root == NULL){
/* if tree is empty insert the node as root*/
root = malloc(sizeof(struct node));
root->data=data;
}else {
/*if the tree is not empty*/
temp = root;
while(temp->left!= NULL||temp->right!=NULL) {
if(data <= temp->data){
if(temp->left==NULL)
break;
else
temp = temp->left;
}
else if(data > temp->data){
if(temp->right==NULL)
break;
else
temp = temp->right;
}
}
if(data<= temp->data){
temp->left=malloc(sizeof(struct node));
(temp->left)->data=data;
}
else {
temp->right=malloc(sizeof(struct node));
(temp->right)->data=data;
}
/*temp=newNode;*/
}
}
int main() {
insert(7);
insert(4);
insert(8);
printf("\n\n------%d------", root->left->data);
printf("\n\n------%d------", root->right->data);
return 0;
}
I have understood how deletion works in linked list, however the implementation is harder than I thought.
I have written this below but it is not working sadly
My node:
struct DLinkedList
{
double sensorData;
struct DLinkedList *prev;
struct DLinkedList *next;
};
And this is my delete function:
void delete(struct DLinkedList **first, struct DLinkedList *el)
{
struct DLinkedList* temp = *first;
if (temp != NULL && temp->sensorData == el->sensorData)
{
(*first) = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->sensorData == el->sensorData)
{
temp->prev = temp;
temp = temp->next;
}
if (temp == NULL)
{
return;
}
free(temp);
}
Is there something wrong with the code itself? The compiler is not giving me any errors but the function doesn't seem to work properly, the way I call it in main() is delete(&first, el);
Here is my main, I have added 3 elements excluding el so that I can see the list more clearly:
int main()
{
//Adding 3 nodes
struct DLinkedList* first = NULL;
struct DLinkedList* second = NULL;
struct DLinkedList* last = NULL;
struct DLinkedList* el = NULL;
//Allocating 3 nodes
first = malloc(sizeof(struct DLinkedList));
second = malloc(sizeof(struct DLinkedList));
last = malloc(sizeof(struct DLinkedList));
el = malloc(sizeof(struct DLinkedList));
first->sensorData = 1; //Assigning data for 'first' node
first->next = second; //Link first node with second node
first->prev = NULL;
second->sensorData = 2;
second->next = last;
second->prev = first;
last->sensorData = 3;
last->next = NULL;
last->prev = second;
el->sensorData = 10;
el->next = first;
el->prev = NULL;
insertFirst(&first, el);
printList(first);
isMember(&first, el);
delete(&first, el);
return 0;
}
//Printing contents of the linked list starting from the 'first' node
void printList(struct Node* first)
{
while (first != NULL)
{
printf(" %f ", first->data);
first = first->next;
}
}
Here below is my minimal example, I have made some changes in the names and main in order to be more readable
#include <stdio.h>
#include <stdlib.h>
//A linked list node
struct Node
{
double data;
struct Node* prev;
struct Node* next;
};
void delete(struct Node** first, struct Node* el)
{
if (*first == el)
{
*first = el->next;
}
if (el->prev)
{
el->prev->next = el->next;
}
if (el->next)
{
el->next->prev = el->prev;
}
free(el);
}
int main()
{
struct Node* first = NULL;
struct Node* el = NULL;
el = malloc(sizeof(struct Node));
el->data = 10;
el->next = NULL;
el->prev = NULL;
delete(&first, el);
print(first);
return 0;
}
You're complicating it much more than necessary. If you have a doubly linked list, use it's abilities.
void delete(struct DLinkedList **first, struct DLinkedList *el) {
// We only need to change the pointer to the first element
// if that's the element we're deleting
if(*first == el)
*first = el->next;
// The old switcheroo
if(el->prev)
el->prev->next = el->next;
if(el->next)
el->next->prev = el->prev;
// Free and we're done. Skip this line if you want to keep the node
// and only remove it from the list.
free(el);
}
This could be combined with a convenient find function:
struct DLinkedList *find(struct DLinkedList **first, double val) {
struct DLinkedList ret = *first;
while(ret && ret->sensorData != val)
ret = ret->next;
return ret;
}
However, you should be careful comparing float numbers. Read more here: What is the most effective way for float and double comparison?
It seems you're trying to reuse an "element" struct as the "list" struct for a doubly linked list.
Although you can reuse next/prev as head/tail, I recommend a separate header struct:
Here's what I mean. Note that I renamed the struct slightly to be more descriptive of purpose:
// element of list
typedef struct element Element;
struct element {
double sensorData;
Element *next;
Element *prev;
};
// list header
typedef struct list List;
struct list {
Element *head;
Element *tail;
};
void
delete(List *list,Element *el)
{
Element *next;
Element *prev;
next = el->next;
prev = el->prev;
if (next != NULL)
next->prev = prev;
if (prev != NULL)
prev->next = next;
if (list->head == el)
list->head = next;
if (list->tail == el)
list->tail = prev;
}
I try to implement the delete method but that doesn't work with me. I want to delete all nodes in the tree. The function has tree type of "struct tree" as a parameter so I can't use recursion; I want to do it with a loop.
That's my structure
typedef struct Node Node;
struct Node{
const void* data;
const void* value;
Node* left;
Node* right;
};
typedef struct Tree Tree;
struct Tree{
Node* root;
size_t size;
int (*comp)(const void *, const void *);
};
function delete
void freeTree(Tree* tree, bool TreeContent){
if(tree->root != NULL){
// free(tree->root->left);
// free(tree->root->right);
// free(tree->root);
}
}
function insert
bool insertInTree(Tree* bst, const void* key, const void* value){
if(bst->root == NULL){
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
return true;
}
else{
int isLeft = 0 ;
Node* Current = bst->root ;
Node* precedant = NULL;
while(Current != NULL){
int compare = bst->comp(&Current->data , &key);
precedant = Current;
if(compare == 1){
isLeft = 1;
Current = Current->left;
}
else if(compare == 0){
isLeft = 0;
Current = Current->right;
}
}
if(isLeft == 1){
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
precedant->left = newNode;
bst->size++;
return true;
}
else{
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
precedant->right = newNode;
bst->size++;
return true;
}
}
return false;
}
edit You don't want to use recursion because the freeTree function doesn't take a Node argument. In this case, you can remove that restriction by creating another function that is recursive, called initially by freeTree.
void freeTree(Tree* tree, bool TreeContent){
if(tree->root != NULL){
freeNode(tree->root);
tree->root = NULL;
}
}
The new freeNode could look like
void freeNode(Node *node) {
if (node->left) freeNode(node->left);
if (node->right) freeNode(node->right);
free(node);
}
Note that freeNode intent is to free the whole tree (otherwise the parent element's left or right [or root] would have to be set to NULL).
Your requirement is that you don't want to use recursion.
Any kind of traversal is not possible in O(n) time without use of a stack/queue (implicitly or explicitly). So we will use a stack (made using an array) and use it to delete all the nodes.
I understand that you have the size of the BST known, so you can create an array of appropriate size as -
struct Node* stack[bst->size];
int top = -1;
This stack will hold all the elements to be processed.
We will first add the root to the stack -
if(bst->root)
stack[++top] = bst->root;
Now we need to process all the nodes in the tree using a loop -
while(top>=0){
//Pop one node -
struct Node* node = stack[top--];
//Add its children to the stack;
if(node->left)
stack[++top] = node->left;
if(node->right)
stack[++top] = node->right;
// Now free the node as
free(node);
}
That is all, one by one each node will be added to the stack and the stack will become empty when all the nodes are done.
Also as a side note, in your insert function you need to do bst->size++ in the if(bst->root == NULL) branch. Else your size will be one less than actual number of nodes.
I am getting a segmentation fault when trying to print the nodes in my binary tree. It looks to be an issue with the third node. I have searched google and stack overflow for hours but I can not understand what the problem is. I am trying to teach myself data structures in C and am very much a novice so I may be doing something in a frowned upon way.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *left;
struct node *right;
} Node;
typedef struct
{
Node *root;
} BinarySearchTree;
void printInOrder(Node *);
void addNode(Node *, Node *);
int main (void)
{
BinarySearchTree tree;
BinarySearchTree *tree_ptr = &tree;
Node n1, n2, n3;
n1.data = 1;
n2.data = 2;
n3.data = 3;
Node *n1_ptr = &n1;
Node *n2_ptr = &n2;
Node *n3_ptr = &n3;
tree_ptr->root = n1_ptr;
addNode(tree_ptr->root, n2_ptr);
addNode(tree_ptr->root, n3_ptr);
printInOrder(tree_ptr->root);
}
void printInOrder(Node *root)
{
if (root == NULL)
{
return;
} else
{
printInOrder(root->left);
printf("%i\n", root->data);
printInOrder(root->right);
}
}
void addNode(Node *root, Node *node)
{
if (node->data < root->data)
{
if (root->left == NULL)
{
root->left = node;
} else
{
addNode(root->left, node);
}
}
else if (node->data > root->data)
{
if (root->right == NULL)
{
root->right = node;
} else
{
addNode(root->right, node);
}
}
}
output:
1
2
Segmentation fault: 11
There doesn't seem to be an issue with any but the third node. If I comment out the line that adds the second node I get the same error (with only 1 being printed, obviously).
Your initialization is incomplete
n1.data = 1;
n2.data = 2;
n3.data = 3;
should also set the pointers
n1.data = 1;
n1.left = NULL;
n1.right = NULL;
n2.data = 2;
n2.left = NULL;
n2.right = NULL;
n3.data = 3;
n3.left = NULL;
n3.right = NULL;
Problem is occurring because you are not initializing all the member of structure Node type variable.
I would suggest, you should write a function to initialize the Node type variable, like this:
void init_node(Node * nodeptr, int data)
{
nodeptr->data = data;
nodeptr->left = NULL;
nodeptr->right = NULL;
}
and in your main() (or from where ever you want to initialize) you can simply do:
init_node(&n1, 1);
init_node(&n2, 2);
init_node(&n3, 3);
With this, you will never miss assigning NULL to left and right pointer during initialization of Node type variable and chances of the error occurring because of it will be reduced to a greater extent.