does anyone know how save a value into a binary tree on the left or right side?
for example we have 2 structs:
struct A
{
int a;
struct A *left;
struct A *right;
}
struct B
{
A *root;
}
and we have a function:
void insert(B *tree, int value)
{
if(tree== NULL)
{
tree= (B*) malloc (sizeof(B));
}
else if(tree!=NULL)
{
tree->root->a = value;
tree->root->left = NULL;
tree->root->right = NULL;
}
now we have the root...
but how to initiliase the value on the right and left side?
else if(tree->apointer->a< value)
{
tree->root->left = value // with & wont work cause is a pointer to integer
}
does anyone know ??
Thanks in advance
With tree= (B*) malloc (sizeof(B));, you create an object of type B, but you do not create an object of type A to which tree->root could point to. Accessing tree->root->a or the other members of root then is undefined behaviour;
You could write:
tree = malloc (sizeof(B));
tree->root = malloc(sizeof(A));
I think there is no sense to discuss your code.:) Even structure definitions are written without semicolons.
Taking into account these structure definitions
struct A
{
int value;
struct A *left;
struct A *right;
};
struct B
{
struct A *root;
};
and assuming that in main there is the following declaration of the tree
int main( void )
{
struct B tree = { NULL };
//...
then the function insert can be defined the following way
int insert( struct B *tree, int value )
{
struct A **node = &tree->root;
while (*node)
{
if (value < (*node)->value)
{
node = &(*node)->left;
}
else
{
node = &(*node)->right;
}
}
*node = malloc(sizeof(struct A));
int success = *node != NULL;
if ( success )
{
(*node)->value = value;
(*node)->left = NULL;
(*node)->right = NULL;
}
return success;
}
The function can be called like
insert( &tree, value );
or its call can be enclosed in an if statement
if ( insert( &tree, value ) ) { /*...*/ }
Related
I am making a simple BST and, in the add_to_bst() function, it is throwing an error in the first line when referencing the object's value.
CODE
typedef struct node {
int value;
struct node* leftChild;
struct node* rightChild;
} BSTNode;
BSTNode *new_BSTNode(int val) {
BSTNode *this = (BSTNode *) malloc(sizeof(BSTNode));
this->value = val;
this->leftChild = (BSTNode * ) malloc(sizeof(BSTNode));
this->rightChild = (BSTNode * ) malloc(sizeof(BSTNode));
this->leftChild = NULL;
this->rightChild = NULL;
return this;
}
typedef struct bst {
BSTNode * root;
} BST;
BST *new_BST(int root_val) {
BST *this = (BST *) malloc(sizeof(BST));
this->root = (BST * ) malloc(sizeof(BSTNode));
this->root->value = root_val;
// this->root->value = (int *) malloc(sizeof(int));
return this;
}
int node_get(BSTNode *n, int i) {
if (n == NULL) return -1;
if (i == n-> value) return 1;
if (i > n-> value) return node_get(n->rightChild, i);
else return node_get(n->leftChild, i);
}
int bst_get(BST *bst, int i) {
return node_get(bst->root, i);
}
void add_to_bst_node(int i, BSTNode *to) {
int n = to->value; // <--- ERR
printf("\nBST VAL: %d", n);
if (i > n) {
if (to->rightChild == NULL)
to->rightChild = new_BSTNode(i);
else
add_to_bst_node(i, to->rightChild);
} else {
if (to->leftChild == NULL)
to->leftChild = new_BSTNode(i);
else
add_to_bst_node(i, to->leftChild);
}
}
void add_to_bst(BST *tree, int i) {
if (tree->root != NULL) {
add_to_bst_node(i, tree->root);
} else {
tree->root = new_BSTNode(i);
}
}
int main() {
BST *bst = new_BST(10);
add_to_bst(bst, 10);
}
RUN MSG:
0x7fa64fc00690
0x7fa64fc00640
First Val: 10
Process finished with exit code 11
BUILD ERR:
BSTNode *new_BSTNode(int val) {
BSTNode *this = (BSTNode *) malloc(sizeof(BSTNode));
this -> value = val;
this -> leftChild = (BSTNode * ) malloc(sizeof(BSTNode));
this -> leftChild = (BSTNode * ) malloc(sizeof(BSTNode));
return this;
}
This leaves this->rightChild uninitialized and leaves this->leftChild pointing to uninitialized garbage. Neither of these issues is fixed in the code that calls new_BSTnode.
void add_to_bst_node(int i, BSTNode *to) {
int n = to -> value; // <------ ERROR
Not surprising, since to comes from leftChild and rightChild, both of which are broken by the logic of new_BSTNode.
Also:
BST *new_BST(int root_val) {
BST *this = (BST *) malloc(sizeof(BST));
this -> root = (BST * ) malloc(sizeof(BSTNode));
this -> root -> value = root_val;
// this -> root -> value = (int *) malloc(sizeof(int));
return this;
}
This doesn't set this->root->leftChild or this->root->rightChild either, so again, they're garbage that gets passed to add_to_bst_node as to.
The creation of the new node, and insertion into the tree seems incorrect.
A new node should not allocate space for the left and right subtrees. Since new nodes are always added to the extremities, they never have subtrees when new anyway.
BSTNode *new_BSTNode( int val )
{
BSTNode *this = ( BSTNode * ) malloc( sizeof( BSTNode ) );
if ( this != NULL )
{
this->value = val;
this->leftChild = NULL;
this->rightChild = NULL;
}
return this;
}
Using a recursive algorithm when inserting new data allows the code to "walk" the tree, finding the correct place for insertion.
void add_to_bst_node( int value, BSTNode *to )
{
if (to != NULL)
{
if (value > to->value)
{
// Add to child-right subtree
if (to->rightChild == NULL)
{
// right-tree is empty, create it
to->rightChild = new_BSTNode( value );
}
else
{
// add it somewhere on the right-side (recursively)
add_to_bst_node( value, to->rightChild );
}
}
else // if (i <= to->value)
{
// Add to child-left subtree
if (to->leftChild == NULL)
{
// left-tree is empty, create it
to->leftChild = new_BSTNode( value );
}
else
{
// add it somewhere on the right-side (recursively)
add_to_bst_node( value, to->leftChild );
}
}
}
}
A tree is just a node. Making a separate structure for a "tree" is just extra work.
typedef BSTNode BST;
So the creation of a tree, is just the creation of a node:
BST *new_BST( int value )
{
return new_BSTNode( value );
}
The branch in add_to_BST() always chooses the tree->root != NULL if it was initialised error-free. Then the add_to_BST_node() dereferences garbage, (as the other answers have pointed out); here is a graphical representation of the memory allocating functions,
And,
I recommend thinking about what the states are in ones system and drawing them out first so one doesn't fall into an invalid state. Also, if one is doing a constructor, it's a good idea to initialise the entire structure.
i have this struct :
struct node
{
int data;
struct node *next;
};
so the following strcut has an int data , i want the function to accept CopyFunction which is baisicly a pointer to a function that accepts void* and returns void* , i want my function to get a copy of the data in the first node connected to a copy f the second data , now i want the data to be not only int i want to use this function on any data so i used CopyFunction to be pointer to a function that as i saied accepts void* ... how can i use this in the function bellow .. for example if i want to change the struct to be :
struct node
{
Element data;
struct node *next;
};
typedef void* Element;
typedef Element (*copy_function) (Element);
struct node * concatLists( struct node *head1, struct node *head2, int cmp( struct node *),copy_function CopyFunction)
{
struct node *head = NULL;
struct node **current = &head;
for ( ; head1 != NULL; head1 = head1->next )
{
if ( cmp( head1 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = CopyFunction(head1->data);
( *current )->next = NULL;
current = &( *current )->next;
}
}
for ( ; head2 != NULL; head2 = head2->next )
{
if ( cmp( head2 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = CopyFunction(head2->data);
( *current )->next = NULL;
current = &( *current )->next;
}
}
and then if i have a int struct i can just use this function with a copy function for int like this :
static void* copyInt(void* num){
int* newInt=malloc(sizeof(*newInt));
*newInt=*(int*)num;
return newInt;
}
also i think it is better if i change and without using always struct node * i want to have maybe: typedef struct node_t* Node;
concatLists(..., (copy_function)copyInt)
Providing all the "methods" (cmp and CopyFunction) as parameters gets silly fast. Why not create a List "object" that holds not just a pointer to the head and tail, but the "methods" to genericize the list too.
cmp is probably a compare function (which means it should take two arguments), which means you are probably trying to merge sorted lists. Well, here's code that uses a generic list implementation to do just that. (I figured I might as well make malloc and free plugable as well.)
#include <stdio.h>
#include <stdlib.h>
// -----
// ListNode type declarations.
typedef struct ListNode {
void* data;
struct ListNode* prev;
struct ListNode* next;
} ListNode;
// -----
// ListType type declarations.
typedef void* (* Allocator )(size_t);
typedef void (* Deallocator )(void*);
typedef void (* FreeFunction )(void*);
typedef int (* CmpFunction )(void*, void*);
typedef void* (* CopyFunction )(void*);
typedef struct {
Allocator malloc;
Deallocator free;
FreeFunction free_data;
CmpFunction cmp;
CopyFunction copy;
} ListType;
// -----
// List type declarations.
typedef struct {
const ListType* list_type;
ListNode* head;
ListNode* tail;
} List;
typedef void (*ListVisitor)(void*);
// -----
// ListDataInt definitions.
static void* ListDataInt_new(int i) {
int* ip = malloc(sizeof(int));
*ip = i;
return ip;
}
static void ListDataInt_free_data(int* ip) {
free(ip);
}
static int ListDataInt_cmp(const int* ap, const int* bp) {
if (*ap < *bp) return -1;
if (*ap > *bp) return +1;
return 0;
}
static int* ListDataInt_copy(const int* orig_ptr) {
int* new_ptr = malloc(sizeof(int));
*new_ptr = *orig_ptr;
return new_ptr;
}
static const ListType ListDataInt_list_type = {
malloc,
free,
(FreeFunction)ListDataInt_free_data,
(CmpFunction)ListDataInt_cmp,
(CopyFunction)ListDataInt_copy
};
// -----
// ListNode definitions.
static ListNode* ListNode_new(List* list, void* data) {
const ListType* list_type = list->list_type;
ListNode* node = list_type->malloc(sizeof(ListNode));
node->data = data;
node->prev = NULL;
node->next = NULL;
return node;
}
static void ListNode_free(List* list, ListNode* node) {
const ListType* list_type = list->list_type;
list_type->free_data(node->data);
list_type->free(node);
}
// -----
// List definitions.
static List* List_new(const ListType* list_type) {
List* list = list_type->malloc(sizeof(List));
list->list_type = list_type;
list->head = NULL;
list->tail = NULL;
return list;
}
static void List_free(List* list) {
ListNode* next = list->head;
while (next != NULL) {
ListNode* node = next;
next = node->next;
ListNode_free(list, node);
}
list->list_type->free(list);
}
static void List_push(List* list, ListNode* node) {
if (list->tail == NULL) {
list->head = list->tail = node;
} else {
list->tail->next = node;
node->prev = list->tail;
list->tail = node;
}
}
static void List_push_data(List* list, void* data) {
List_push(list, ListNode_new(list, data));
}
static void List_visit(List* list, ListVisitor visitor) {
for (ListNode* node = list->head; node != NULL; node = node->next) {
visitor(node->data);
}
}
// -----
// Main program.
static List* merge_sorted_lists(List* list1, List* list2) {
const ListType* list_type = list1->list_type;
List* new_list = List_new(list_type);
ListNode* src1 = list1->head;
ListNode* src2 = list2->head;
while (src1 != NULL && src2 != NULL) {
int cmp = list_type->cmp(src1->data, src2->data);
if (cmp <= 0) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
src1 = src1->next;
}
if (cmp >= 0) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
src2 = src2->next;
}
}
while (src1 != NULL) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
src1 = src1->next;
}
while (src2 != NULL) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
src2 = src2->next;
}
return new_list;
}
static void dumper(const int* ip) {
printf("%d\n", *ip);
}
int main(void) {
List* sorted_int_list1 = List_new(&ListDataInt_list_type);
List_push_data(sorted_int_list1, ListDataInt_new(4));
List_push_data(sorted_int_list1, ListDataInt_new(6));
List_push_data(sorted_int_list1, ListDataInt_new(8));
List* sorted_int_list2 = List_new(&ListDataInt_list_type);
List_push_data(sorted_int_list2, ListDataInt_new(5));
List_push_data(sorted_int_list2, ListDataInt_new(7));
List_push_data(sorted_int_list2, ListDataInt_new(9));
List* merged_sorted_int_list =
merge_sorted_lists(sorted_int_list1, sorted_int_list2);
List_visit(merged_sorted_int_list, (ListVisitor)dumper);
List_free(sorted_int_list1);
List_free(sorted_int_list2);
List_free(merged_sorted_int_list);
return 0;
}
Test:
$ gcc -Wall -Wextra -pedantic --std=c99 -o a a.c && a
4
5
6
7
8
9
I'm implementing my own binary tree and this is my node structure:
struct node {
int value;
struct node *left;
struct node *right;
};
and my start node:
struct node * start = NULL;
this is my insert function:
void insert(int value, struct node *leaf) {
if (leaf == NULL) {
leaf = (struct node*) malloc( sizeof( struct node ) );
leaf->value = value;
leaf->left = NULL;
leaf->right = NULL;
} else if (value < leaf->value) {
insert(value, leaf->left);
} else if (value > leaf->value) {
insert(value, leaf->right);
}
}
and this is the function I use for visiting the tree:
void print_tree(struct node * leaf) {
if (leaf == NULL)
return;
print_tree(leaf->left);
printf(" %d ", leaf->value);
print_tree(leaf->right);
}
The problem is that after I insert all the values it prints nothing.
I'm assuming that you're calling the insert in this way:
insert(5, start);
The problem is that in this way you are copying NULL into the leaf local variable of the insert function.
So also if you are allocating memory for the nodes, you aren't updating the start pointer.
In order to do this you need to use a double pointer in your insert function (struct node ** leaf).
This should work:
void insert(int value, struct node **leaf)
{
if( (*leaf) == NULL )
{
(*leaf) = malloc( sizeof( struct node ) ); // You don't need casting
(*leaf)->value = value;
(*leaf)->left = NULL;
(*leaf)->right = NULL;
}
else if(value < (*leaf)->value)
{
insert( value, &(*leaf)->left );
}
else if(value > (*leaf)->value)
{
insert( value, &(*leaf)->right );
}
}
I am learning the C language and trying to build a C binary tree library. My structure is defined as:
struct Node {
int value;
struct Node *left;
struct Node *right;
};
typedef struct Node TNode;
typedef struct Node *binary_tree;
It is created like this:
binary_tree NewBinaryTree(int value_root) {
binary_tree newRoot = malloc(sizeof(TNode));
if (newRoot) {
newRoot->value = value_root;
newRoot->left = NULL;
newRoot->right = NULL;
}
return newRoot;
}
I add elements to it like:
void Insert(binary_tree *tree, int val) {
if (*tree == NULL) {
*tree = (binary_tree)malloc(sizeof(TNode));
(*tree)->value = val;
(*tree)->left = NULL;
(*tree)->right = NULL;
} else {
if (val < (*tree)->value) {
Insert(&(*tree)->left, val);
} else {
Insert(&(*tree)->right, val);
}
}
}
This kinda "sort" the tree by checking the value.However I would like a function that simply add the val value to the left(left) without doing any sorting. I did:
void InsertLeft(binary_tree *tree, int val) {
Insert(&(*tree)->left, val);
}
I call the function like this:
InsertLeft(&tree, 8);
I have a main program that initialise the tree like this:
tree = NewBinaryTree(3);
Also a tree display method:
void display_binary_tree( binary_tree tree )
{
if( tree != NULL )
{
display_binary_tree( tree->left ) ;
printf( "%d " , tree->value ) ;
display_binary_tree( tree->right ) ;
}
}
and afterwards I can add elements by calling the Insert(binary_tree *tree, int val) function, however when calling this function, it just crashes the program. I dont understand why.
I've been struggling with this for a while, I can't seem to create a valid LinkedList data structure in C,
Here's all my structures:
typedef struct {
int size;
int *cellsI;
int *cellsJ;
} DataInList;
typedef struct listElement{
DataInList dataVar;
struct listElement *next;
} LinkedListElement;
typedef struct {
LinkedListElement*first;
LinkedListElement*last;
} LinkedListRoot;
I have a function that adds a data element to the linked list:
public void addDataToList(LinkedListRoot root, DataInList data) {
LinkedListElement newElem;
newElem.dataVar = data;
newElem.next = NULL;
if(root->first == NULL) {
root->first = &newElem;
root->last = &newElem;
} else {
root->last->next = &newElem;
root->last = &newElem;
}
}
Can anyone help me please?
As the commenter said, you've defined newElem in the function, and on the stack as well, so you have no way to globalize it or return a permanent entry to it. Something more along these lines. I haven't tested it yet, but it should give you the idea:
typedef listData struct {
int size;
int *cellsI;
int *cellsJ;
} listData_t
typedef struct listElement {
listData_t dataVar;
struct listElement *next;
} listElement_t;
typedef struct listRoot {
listElement_t *first;
listElement_t *last;
} listRoot_t;
listElement_t *
addDataToList(listRoot_t *root, listData_t *data) {
listElement_t *newElem = malloc(sizeof(struct listElement));
if (newElem == NULL) {
fprintf(stderr, "Error allocating memory\n");
exit(-1)
}
newElem->dataVar = data;
newElem->next = NULL;
if (root->first == NULL) {
root->first = newElem;
root->last = newElem;
} else {
root->last->next = newElem;
root->last = newElem;
}
return newElem;
}