C- Binary Search Tree - c

I am trying to build a a binary search tree. But I am not getting the correct output when performing the different traversals.
typedef struct binary_search_tree{
struct binary_search_tree *lchild;
int data;
struct binary_search_tree *rchild;
}bst_t;
#define ALLOCATE (bst_t*)malloc(sizeof(bst_t))
Here is the insert function:
void insert(bst_t *ptr,int data){
if( ptr->data < data){
if ( ptr->lchild == NULL ){
ptr->lchild = ALLOCATE;
ptr->lchild->data = data;
return;
}else
insert(ptr->lchild,data);
}else{
if ( ptr->rchild == NULL ){
ptr->rchild = ALLOCATE;
ptr->rchild->data = data;
return;
}else
insert(ptr->rchild,data);
}
}
Is this function correct?
I am sending the address of root while calling that function.

The problem is the ALLOCATE macro. It doesn't do nearly enough to properly allocate and initialize a new node. I suggest creating a newNode function that allocates memory for the node, and then initializes all of the members of the structure, like this
bst_t *newNode(int data)
{
// allocation and error checking
bst_t *node = malloc(sizeof(bst_t));
if ( node == NULL )
{
fprintf(stderr, "out of memory\n");
exit( 1 );
}
// initialize the members of the structure
node->lchild = NULL;
node->data = data;
node->rchild = NULL;
return node;
}
Then the insert function can be simplified to this
void insert(bst_t *ptr,int data)
{
if( ptr->data < data){
if ( ptr->lchild == NULL )
ptr->lchild = newNode(data);
else
insert(ptr->lchild,data);
}else{
if ( ptr->rchild == NULL )
ptr->rchild = newNode(data);
else
insert(ptr->rchild,data);
}
}

Related

Queue implementing by linked list in c

I am implementing queue with a linked list but I am facing problem in the insertion() function. I am able to insert only one data, whenever I insert another data then again previous data insert whatever did I insert at first time.
#include <stdio.h>
#include <stdlib.h>
struct Queue
{
int data;
struct Queue *next;
};
struct Queue *rear = NULL;
struct Queue *front = NULL;
void insertion(int data)
{
struct Queue *n;
n = (struct Queue *)malloc(sizeof(struct Queue));
n->data = data;
n->next = NULL;
if (rear == NULL)
{
front = n;
rear = n;
}
else
{
rear->next = n;
rear = n;
}
}
void deletion()
{
if (front == NULL)
printf("\n Underflow");
else if (front == rear)
{
front = NULL;
rear = NULL;
}
else
front = front->next;
}
void viewList()
{
struct Queue *t = front;
if (t == NULL)
printf("\n there is no item for view...............");
else
{
while (t != NULL)
{
printf(" %d", front->data);
t = t->next;
}
}
}
int main()
{
struct Queue *q = NULL;
insertion(5);
insertion(10);
// deletion();
viewList();
printf("\n");
viewList();
return 0;
}
The function deletion produces a memory leak because it does not free the memory of the deleted node. The function can look at least like
void deletion() {
if(front == NULL)
printf("\n Underflow");
else
{
stuct Queue *n = front;
front = front->next;
if ( front == NULL ) rear = NULL;
free( n );
}
}
Within the function viewList you are always outputting the value stored in the node pointed to by the pointer front
printf(" %d", front->data);
You have to write
printf(" %d", t->data);
This declaration in main
struct Queue *q = NULL;
is redundant and does not make a sense.
Pay attention to that it is a bad idea when functions depend on global variables. You could define the queue the following way
struct Node
{
int data;
struct Node *next;
};
struct Queue
{
struct Node *front;
struct Node *rear;
};
And in main you could define an object of the queue the following way
struct Queue queue = { .front = NULL, .rear = NULL };
And the functions should be rewritten such a way that they would accept a pointer to the queue. For example
int insertion( struct Queue *queue, int data );
The function can be defined like
int insertion( struct Queue *queue, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( queue->front == NULL )
{
queue->front = new_node;
}
else
{
queue->rear->next = new_node;
}
queue->rear = new_node;
}
return success;
}
And the function will be called like
int main( void )
{
struct Queue queue = { .front = NULL, .rear = NULL };
insertion( &queue, 5 );
insertion( &queue, 10 );
//...
you can check the returned value of the function to determine whether the insertion was successful as for example.
if ( !insertion( &queue, 5 ) ) puts( "Error. Not enough memory." );
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Queue
{
struct Node *front;
struct Node *rear;
};
int insertion( struct Queue *queue, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( queue->front == NULL )
{
queue->front = new_node;
}
else
{
queue->rear->next = new_node;
}
queue->rear = new_node;
}
return success;
}
int empty( const struct Queue *queue )
{
return queue->front == NULL;
}
void viewList( const struct Queue *queue )
{
if ( empty( queue ) )
{
printf("\n there is no item for view...............");
}
else
{
for ( struct Node *current = queue->front; current != NULL; current = current->next )
{
printf( " %d", current->data );
}
}
}
int main(void)
{
struct Queue queue = { .front = NULL, .rear = NULL };
insertion( &queue, 5 );
insertion( &queue, 10 );
viewList( &queue );
return 0;
}
The program output is
5 10

exc bad access C

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.

Binary tree doesn't work the print

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 );
}
}

How to access the data inside a node whose memory location has been freed?

I am trying to return the data in the node after freeing the node. But I receive segfault when I am trying to do that (my guess is that when I assign the elem value to the variable data, it only copies the reference. After the memory location of the node freed, we lose the member elem inside the node struct. Therefore it is illegal to retrieve the elem via its reference.). Is there any other way of doing it?
void* remove_node(struct s_node** node){
if(node != NULL && *node!= NULL && (*node)->elem != NULL){
void* data = (*node)->elem;
if((*node)->prev == NULL && (*node)->next == NULL){
free(*node);
}else if((*node)->prev == NULL){
(*node)->next->prev = NULL;
(*node)->next = NULL;
free(*node);
}else if((*node)->next == NULL){
(*node)->prev->next = NULL;
(*node)->prev = NULL;
free(*node);
}else{
(*node)->prev->next = (*node)->next;
(*node)->next->prev = (*node)->prev;
(*node)->prev = NULL;
(*node)->next = NULL;
free(*node);
}
return data;
}else{
return NULL;
}
}
And here is the struct
struct s_node {
void* elem;
struct s_node* next;
struct s_node* prev;
};
The code posted does not seem to be causing the bug you observe. The tree structure might get corrupted somewhere else.
Note however that it can be simplified drastically:
void *remove_node(struct s_node **node) {
if (node != NULL && *node != NULL && (*node)->elem != NULL) {
void *data = (*node)->elem;
if ((*node)->prev != NULL) (*node)->prev->next = (*node)->next;
if ((*node)->next != NULL) (*node)->next->prev = (*node)->prev;
free(*node);
*node = NULL; /* safely, cannot hurt */
return data;
} else {
return NULL;
}
}

void Pointer to a structure causes error 'dereferencing 'void *' pointer'

I try to initialize a queueADT pointer called initAmigo. Apparently I never create one if the structure is not making the pointers for the (void *data)
Reasons why I can't put any data in void *data in node structure:
Asuumption 1: Take away void *data and say User_struct (from .h file)
Assumption 2: RegisteredData is not supposed to be a pointer because the parameter in que_Insert asks for a pointer)
Assumption 3: In AddUser function, que_insert( initAmigo , registeredData); The registeredData to be inserted in the void *data node was actually a pointer to a pointer to a structure
Having a queue reference a void * creates the following error:
amigonet.c: In function 'findUser':
amigonet.c:247:21: warning: dereferencing 'void *' pointer [enabled by default]
if (currNode->data->name == name) { //If front is the name being searched
^
amigonet.c:247:21: error: request for member 'name' in something not a structure or union
amigonet.c:253:22: warning: dereferencing 'void *' pointer [enabled by default]
if (currNode->data->name == name ) {
.c file just has to create a structure of a queue of Users (QueueADT initAmigo)
typedef struct node {
//name of data userStruct (just for referencing)
void* data;
struct node *next;
}node;
struct queueStruct {
struct node *front; /* pointer to front of queue */
struct node *rear; /* pointer to rear of queue */
int (*cmprFunc)(const void*a,const void*b); /* The compare function used for insert */
};
typedef struct queueStruct *QueueADT; //typedef inserted for pointers,
//name is QueueADT
#define _QUEUE_IMPL_
#include "queueADT.h"
/// create a queue that is either sorted by cmp or FIFO
//function with two void
QueueADT que_create( int (*cmp)(const void*a,const void*b) ) {
QueueADT new;
new = (QueueADT)malloc(sizeof(struct queueStruct)); //NOTE: NO POINTERS HERE
//use pointers in Single lines
if (cmp == NULL) {
new->front = NULL;
new->rear = NULL;
new->cmprFunc = NULL;
} else {
new->cmprFunc = cmp;
new->front = NULL;
new->rear = NULL;
}
return ( new );
}
//free the queue once the nodes have been cleared from the queue
void que_destroy( QueueADT queue ) {
if ( queue->front == NULL ) {
free(queue);
} else {
que_clear(queue);
free(queue);
}
}
//passes a real pointer for dynamic allocation
//set a temp to the front to be deleted, then front becomes the next and delete the temp
void que_clear( QueueADT queue ) {
while (queue->front->next != NULL) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp = queue->front;
queue->front= queue->front->next;
free(temp);
}
}
//if the cmpr function returns a positive then put in in before the b node in cmp(curr, temp)
void que_insert( QueueADT queue, void *data ) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data= data;
temp->next = NULL;
node *currNode; //simply a pointer
currNode = queue->front;
if ( queue->front != NULL ) { //+1 or more in Q
if ( queue->cmprFunc == NULL ) { //if the cmp_func is FIFO
queue->rear->next = temp;
queue->rear= temp;
queue->rear->next=NULL;
if ( queue->front == queue->rear ) {
currNode->next = temp;
queue->rear = temp;
temp->next= NULL;
}
} else {
while ( currNode->next != NULL ){ //2 or more
if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0
&& ( currNode == queue->front)) ) {
temp->next = currNode;
queue->front=temp;
break;
}
if (( (*(queue->cmprFunc))(currNode->next->data, temp->data) >= 0 ) ) {
temp->next = currNode->next;
currNode->next = temp;
break;
} else {
currNode = currNode->next; //move past front and possibly rear
if (currNode->next == NULL ) { //currNode is rear of queue
currNode->next = temp;
queue->rear = temp;
temp->next = NULL;
break;
}
//exit_failure
}
}
if ( queue->front == queue->rear ) { //exactly 1 node in queue
if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0 ) ) {
temp->next = queue->front;
queue->front = temp;
} else {
queue->front->next = temp;
queue->rear = temp;
}
}
}
} else {
queue->front = temp;
queue->rear= queue->front;
queue->front->next= queue->rear->next = NULL;
}
}
//removes the front
void *que_remove( QueueADT queue ) {
if ( queue->front != NULL ) { //if the size of queue is greater than 1
node *currNode; // dont make new node, pointer
currNode = queue->front;
void *data = currNode->data;
if ( queue->front == queue->rear ) { //if size of queue is 1
free(currNode);
queue->front = queue->rear = NULL; //set both to NULL
} else {
queue->front= currNode->next;
free(currNode);
}
return data;
}
return NULL;
}
bool que_empty( QueueADT queue ) {
if ( queue->front == NULL ) {
return true;
} else {
return false;
}
}
QueueADT initAmigo;
//struct queueStruct *initAmigo
//QueueADT initAmigo;
//make a Queue with front and rear
//compare function with A-Z
struct Friends_struct {
struct queueStruct *amigos_Queue;
};
void create_amigonet() {
//makes the same thing as que_Create
//(Friends)malloc(sizeof(struct Friend_struct));
initAmigo = que_create(NULL);
printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
}
//The add user will find a new user and make the name of the user to a amigonet
//add Usernode to queue initAmigo
//make sure set to first and display queue
void addUser( const char *name ) {
//create Usernode and void *data (user w/ friends)
//check to see if User already exists
if ( findUser(name) != NULL) {
return;
}
//create data for node, by initializing memorry for a userStruct
struct User_struct *registeredData;
registeredData = ( struct User_struct* )malloc(sizeof(struct User_struct)); //first user Data
registeredData->name = name;
//create a Friends
//put this in file create F
struct Friends_struct *initAmigos;
initAmigos = (struct Friends_struct*)malloc(sizeof(struct Friends_struct)); //NOTE: NO POINTERS HERE
//set Friends list to Null
initAmigos->amigos_Queue = que_create( NULL );
//put User with empty Friends struct
registeredData->amigos = initAmigos;
//void que_insert( QueueADT queue, void *data )
que_insert( initAmigo , registeredData);
printf("%s User was inerted \n", name);
}
//Find a user in the init Amgio
//start at front as temp, go to next until name found
User *findUser( const char *name ) {
struct node *currNode;
currNode = initAmigo->front;
printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
if ( initAmigo->front == NULL ) {
return NULL;
} else {
if (currNode->data->name == name) { //If front is the name being searched
return currNode->data;
}
//Loop after front
while ( currNode->next != NULL ) {
currNode = currNode->next;
if (currNode->data->name == name ) {
return currNode->data;
}
}
node *rear = currNode;
if (rear->data->name == name ) {
return rear->data;
}
}
//User Not Founded
return;
}
#if 0
void addAmigo( User *user, User *amigo ) {
//check to see if node exits within friends
//go to use friends list
//traverse the node, check data for amigo->name == data->name
if ( user->amigos->amigos_Queue->front != NULL ) {
node *currNode = user->amigos->amigos_Queue->front;
if ( currNode->data->name == amigo->name ) {
return ;
} else {
//loop to determine if User friend queue front to rear has amigo already
while ( currNode->next != NULL ) {
currNode = currNode->next;
if (currNode ->data->name == amigo->name) {
return;
}
}
}
}
que_insert( user->amigos->amigos_Queue, amigo);
}
void removeAmigo( User *user, User *ex_amigo) {
//Pre Condition: Amgio exists in user
//go to user
//set user as currNode
//either create a function in queueADT remove
// use a prev and curr and next and traverse, remove, connect
//preconditions: front is not examigo
// rear is not examigo
// amigo is friend of user
}
size_t separation( const User *user1, const User *user2 ) {
return;
//queue a DFS
// queue a BFS
//
}
//search using a queue BFS
//search using a DFS
//number of users and their names
void dump_data() {
if (initAmigo->front != NULL) {
node *currNode = initAmigo->front;
printf("%s: Amigos!\n", currNode->data->name); //prints the name of the first node
while ( currNode->next != NULL ) {
currNode = currNode->next;
printf("%s: Amigos!\n", currNode->data->name);
}
//while loop of each user set to currNodw
//set a variable for currNodeAmigo and print the names of them inside ^^^
}
}
void destroy_amigonet(){
//clear Friend Queue and destroy for each User Friend
//destroy initAmigo queue
}
The problem looks like this:
typedef struct node {
void* data;
struct node *next;
}node;
...
struct node *currNode;
if (currNode->data->name == name) { //If front is the name being searched
return currNode->data;
}
The type of currNode->data is void *. This is an incomplete type, which means that it cannot be dereferenced. The compiler has no idea what to make of whatever it points at. You need to convert the void pointer, into a pointer to a meaningful type.
You have not defined the User type in the code you posted, but I'm guessing that you want something like this:
User *user = currNode->data;
if (user->name == name) {
return user;
}
You will also have to make similar changes elsewhere in the same function.

Resources