I need some help with creating a binary tree program. Basically, I have different methods for creating and using a binary tree table (insert, find etc). The methods are called from other classes. Right now I don't think my insert function is working properly since when I print the table out it only shows the last node of the tree.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define __USE_BSD
#include <string.h>
#include "speller.h"
#include "dict.h"
typedef struct node *tree_ptr;
struct node {
Key_Type element; // only data is the key itself
tree_ptr left, right;
// add anything else that you need
};
struct table {
tree_ptr head; // points to the head of the tree
// add anything else that you need
};
Table initialize_table(/*ignore parameter*/) {
Table newTable = malloc(sizeof(Table));
newTable->head = NULL;
return newTable;
}
void insert_again(Key_Type key, tree_ptr node) {
Key_Type currentKey = node->element;
//printf("%s\n%s", currentKey, key);
int keyCompare = strcmp(key, currentKey);
// Move to the left node.
if (keyCompare < 0) {
//printf("%s\n%s", currentKey, key);
// If left node is empty, create a new node.
if (node->left == NULL) {
tree_ptr newPtr = malloc(sizeof(tree_ptr));
newPtr->element = key;
newPtr->left = NULL;
newPtr->right = NULL;
node->left = newPtr;
} else {
insert_again(key, node->left);
}
}
// Move to the right node.
else if (keyCompare > 0) {
//printf("%s\n%s", currentKey, key);
// If right node is empty, create a new node.
if (node->right == NULL) {
tree_ptr newPtr = malloc(sizeof(tree_ptr));
newPtr->element = key;
newPtr->left = NULL;
newPtr->right = NULL;
node->right = newPtr;
} else {
insert_again(key, node->right);
}
}
}
Table insert(Key_Type key, Table table) {
// if it's a new tree.
if (table->head == NULL) {
tree_ptr headPtr = malloc(sizeof(tree_ptr));
headPtr->element = key;
headPtr->left = NULL;
headPtr->right = NULL;
table->head = headPtr;
//printf("%s", table->head->element);
}
// if the tree already exists
else {
//printf("%s", table->head->element);
insert_again(key, table->head);
}
//printf("%s", table->head->element);
return table;
}
Boolean find_key(Key_Type key, tree_ptr node) {
Key_Type currentKey = node->element;
int keyCompare = strcmp(key, currentKey);
if (node != NULL) {
if (keyCompare == 0) {
return TRUE;
} else
if (keyCompare == -1) {
return find_key(key, node->left);
} else {
return find_key(key, node->right);
}
} else {
return FALSE;
}
}
Boolean find(Key_Type key, Table table) {
return find_key(key, table->head);
}
void print_tree(tree_ptr node) {
if (node == NULL) {
return;
}
print_tree(node->left);
printf("%s\n", node->element);
print_tree(node->right);
}
void print_table(Table table) {
print_tree(table->head);
}
void print_stats(Table table) {
}
You have to search for an empty child node to insert a new node into a tree. Use a pointer to a pointer to notice the empty child node. Apart from this you have to allocate memory for sizeof(struct node)and not for sizeof(struct node*) as you did. In relation to the code I can see, that type of Key_Type is char*. So you have to use strcmp to compare keys and you have to allocate memory and to copy the key into the node.
Boolean insert( Key_Type key, Table table )
{
tree_ptr *ppNode = &(table->head); // pointer to pointer to node (struct node **)
while ( ppNode != NULL )
{
int keyCompare = strcmp( key, (*ppNode)->element );
if ( keyCompare == 0 )
return FALSE; // element with key is already member of tree
if ( keyCompare < 0 )
ppNode = &((*ppNode)->left); // go to left child
else
ppNode = &((*ppNode)->right); // go to right child
}
// now ppNode is either a pointer to an empty child pointer,
// or to table->head if the tree is empty
*ppNode = malloc( sizeof(struct node) ); // allocate new node right to target
(*ppNode)->left = NULL;
(*ppNode)->right = NULL;
(*ppNode)->element = malloc( strlen(key) + 1 );
strcpy( (*ppNode)->element, key );
return TRUE; // new node added successfully
}
Finding a node with key is similar to find an empty child pointer:
Boolean find_key( Key_Type key, Table table )
{
tree_ptr pNode = table->head;
while ( ppNode != NULL )
{
int keyCompare = strcmp( key, pNode->element );
if ( keyCompare == 0 )
return TRUE; // element with key was found
if ( keyCompare < 0 )
pNode = pNode->left; // go to left child
else
pNode = pNode->right; // go to right child
}
return FALSE; // key is not member of tree
}
Related
I'm trying to practice Linked Lists in C and I created a simple LL with an add function that takes a position index and inserts the data at that position.
I keep getting an infinite loop when trying to add to the beginning of my list using the add_beg, which just calls the add_at function with position 0 (add(0, data)) function. I can't seem to find the reason why this is happening. I need another set of eyes. Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int _data;
struct node_t *_next;
} node_t;
node_t *_head = NULL;
void add_at(int pos, int data) {
node_t *node = malloc(1 * sizeof(node_t));
node->_data = data;
node->_next = NULL;
// insert if empty
if (_head == NULL) {
_head = node;
}
else {
int index = 0;
node_t *prev = NULL;
node_t *curr = _head;
while (curr != NULL && index != pos) {
prev = curr;
curr = curr->_next;
index++;
}
// insert beginning
if (index == 0) {
_head = node;
node->_next = _head;
}
// insert end
else if (index != 0 && curr == NULL) {
prev->_next = node;
}
// insert middle
else {
prev->_next = node;
node->_next = curr;
}
}
}
void add_beg(int data) {
add_at(0, data);
}
void add_end(int data) {
add_at(-1, data);
}
void dump() {
if (_head != NULL) {
node_t *curr = _head;
while (curr != NULL) {
if (curr->_next != NULL) {
printf("%d -> ", curr->_data);
}
else {
printf("%d", curr->_data);
}
curr = curr->_next;
}
printf("\n");
}
else {
printf("The list is empty\n");
}
}
int main() {
add_beg(6);
add_at(1, 1);
add_at(2, 3);
add_at(3, 9);
add_at(4, 8);
add_at(5, 5);
add_at(7, 2);
add_at(8, 4);
add_beg(9); // commenting this out prevents the infinite loop
dump();
return 0;
}
The error is in this section:
if (index == 0) {
_head = node;
node->_next = _head;
}
That second command sets node->_next to head. However, the line before set _head to node. Therefore, you just set node->_next to node, creating the infinite loop.
You need to reverse the order of those two statements.
if (index == 0) {
_head = node;
node->_next = _head;
}
here you set _head as node but after next node at _head then when your doing while loop you had already broke your linked list.
Fix :
first set the _head as node->_next then set _head as node
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.
Can anyone tell me what is wrong with my code?
I want to create non- return function void to insert a node at the end of linked list.
void insert_tail_Recursively(struct node **phead, int key) {
if (*phead == NULL) {
Node*temp = malloc(sizeof(Node));
temp->data = key;
temp->pLeft = temp->pRight = NULL;
*phead = temp;
} else {
Node*temp = malloc(sizeof(Node));
temp->data = key;
temp->pLeft = temp->pRight = NULL;
/* data more than root node data insert at right */
if ((temp->data > (*phead)->data) && ((*phead)->pRight != NULL))
insert_tail_Recursively((*phead)->pRight, key);
else if ((temp->data > (*phead)->data) && ((*phead)->pRight == NULL)) {
(*phead)->pRight = temp;
}
/* data less than root node data insert at left */
else if ((temp->data < (*phead)->data) && ((*phead)->pLeft != NULL))
insert_tail_Recursively((*phead)->pLeft, key);
else if ((temp->data < (*phead)->data) && ((*phead)->pLeft == NULL)) {
(*phead)->pLeft = temp;
}
}
}
Your code is too complicated and as result has bugs. For example there are memory leaks.
It seems you mean the following.
void insert_tail_Recursively( struct node **phead, int key )
{
if ( *phead == NULL )
{
*phead = malloc( sizeof( struct node ) );
( *phead )->data = key;
( *phead )->pLeft = ( *phead )->pRight = NULL;
}
else
{
phead = key < ( *phead )->data ? &( *phead )->pLeft : &( *phead )->pRight;
insert_tail_Recursively( phead, key );
}
}
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 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.