I'm trying to write a little program that goes through a list of numbers in an array and just inserts them into a binary search tree. Here's what I have:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t node_t;
struct node_t {
int data;
node_t *left;
node_t *right;
};
int insert(node_t *node, int n);
int main(void) {
int array[8] = {5, 8, 3, 6, 9, 2, 4, 7};
int i;
node_t *root;
for (i = 0; i < 8; i++) {
insert(root, array[i]);
}
return 0;
}
int insert(node_t *node, int n) {
if (node == NULL) {
node = malloc(sizeof node);
node->data = n;
return 1;
}
if (n > node->data) {
insert(node->left, n);
} else if (n < node->data) {
insert(node->right, n);
} else {
return -1;
}
return 0; // Suppress 'control reaches end of non-void function'
}
when I compile with gcc I get a warning saying "'root' may be used uninitialized in this function". Running it causes on errors (on Windows at least), however, printing out root->data in main() yields a 0.
The idea I was trying to implement was the insert() function checking if the pointer to the input node was NULL so it could then malloc it. Also, due to how the recursion is handled, the number being inserted should be inserted at that node. If the node did NOT equal NULL, then I would recursively call insert() again on the side of the node where the number should be inserted.
I understand the reason why this doesn't work has something to do with the pointer root not being directed anywhere, nor root->left/root->right, however, I don't know what I can do to fix this. Any help would be appreciated, thank you!
There might be more problem with the code you posted but I listed a few problems below.
Since it is the node that you need to allocate memory for if it contains NULL, you need to change this:
if (node->data == NULL) {
To this:
if (node == NULL) {
Also, you need to initiate the root node, since it will just contain whatever happens to be on stack at that moment and it may or may not be NULL (e.i. the thing you want to compare with in insert function). So initiate it like so:
node_t *root = NULL;
Last thing is to change to malloc to calloc function (or do a memset to zero on the memory separately). Otherwise the variables node->left and node->right can contain non NULL values that could result in making use of uninitialized memory.
Your program does indeed pass an unintialized root variable to the insert() function. But even if initialize root you are still going to have problems
because in order to populate the tree, you need to pass pointer to pointer (as you want to be able modify the pointer root in main()). Similarly, you need modify the argument to
the recursive calls to insert() as well.
I notice you don't really use the return value of insert(). So, it can just be a void function. I added some in-code comments to explain some problems.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t node_t;
struct node_t {
int data;
node_t *left;
node_t *right;
};
void print(node_t *r) { /* In order tree traversal. Gives the sorted output. */
if (!r) return;
print(r->left);
printf("%d ", r->data);
print(r->right);
}
void insert(node_t **node, int n);
int main(void) {
int array[] = {5, 8, 3, 6, 9, 2, 4, 7}; /* Removed the size. It can be calculated using sizeof and helps when array size changes */
int i;
node_t *root = NULL;
/* Without hard-coding, array size can be calculated like this. */
for (i = 0; i < sizeof array/sizeof array[0]; i++) {
insert(&root, array[i]);
}
print(root);
return 0;
}
void insert(node_t **node, int n) {
if (*node == NULL) {
*node = malloc(sizeof *node);
if (*node == NULL) { /* Need to check the return value for failure. */
perror("malloc");
exit(1);
}
(*node)->left = (*node)->right = NULL;
(*node)->data = n;
return;
}
if (n < (*node)->data) /* Insert smaller elements on the left for it to be a binary tree - but not neccessary */
insert(&(*node)->left, n);
else /* Another else below this isn't needed. There can't be any error with the number 'n' itself */
insert(&(*node)->right, n);
}
Related
Hello im trying to make a program that takes a linked list of integers and sums the squares of the int, using recursion. I have tried this so far, however i cant get the function of summin the squares to work. I dont know if using the pow() is the best way?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include<math.h>
typedef struct node
{
int value;
struct node* next;
} node;
/* terminal node at the end of the list */
node SENTINEL = {0, 0};
/* utility functions to create and free lists */
node * make_node(int v, node * q)
{
node* p = (node*) malloc(sizeof(node));
p->value = v;
p->next = q;
return p;
}
int sum_squares(node* list)
{
if(list == 0)
return 0;
else
{
return(pow(&list, 2) + sum_squares(list));
}
}
void free_node(node* p)
{
if(p == &SENTINEL)
return;
else
{
free_node(p->next);
free(p);
}
}
int main(void)
{
int sum;
node* list =
make_node(1,
make_node(2,
make_node(3,
make_node(4,
make_node(5, &SENTINEL)
)
)
)
);
sum = sum_squares(list);
printf("The sum of squares is: %d\n",sum);
free_node(list);
return 0;
}
it should equal 55 with the current numbers
There are a few things that you should edit!
In your sum_squares function, your base case checks whether current node list is equal to 0, but you should check whether it's the sentinel node.
In the recursive case, you should use pow(&list, 2). &list, however, returns the address of the argument list. What you're looking for is the integer value held in the node struct, which you get by using the -> operator. &list becomes list->value.
Finally, when you recursively call your next function, you pass it the same node. This will cause it to infinitely call itself on the same node, and never actually step through the list. Instead of just passing list again, you should pass list->next!
The changes are applied below:
int sum_squares(node* list)
{
if (list == &SENTINEL)
return 0;
return (pow(list->value, 2) + sum_squares(list->next));
}
I am trying to do a function that receives the root of a supposed BST and I want to know if the tree in question is a BST.
Problem is that, I am traveling the tree with recursion and what I'm trying to do is, put inside an array all the values of the tree. I searched for how to put a BST into an array (AddtoArray), but the answers I've found on stackoverflow and other websites didn't solve my problem. (I got seg fault).
Here's what I got so far:
#include<stdio.h>
#include<stdlib.h>
struct node{
int key;
struct node *left, *right;
};
struct node *newNode(int item){
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
struct node* insert(struct node* node, int key){
if(node == NULL) return newNode(key);
if(key < node->key)
node->left = insert(node->left, key);
else if(key >= node->key)
node->right = insert(node->right, key);
return node;
}
void check(struct node *root, int *array, int i){
if(root != NULL){
check(root->left, array, i);
array[i++] = root->key;
//I tried to put i++, ++i in every place of this function (trying table test) and I realized it was too difficult to realize what to do here, I've found some functions returning an integer, the "i" in question, but they didn't work out for me.
check(root->right, array, i);
}
}
int main(){
int *array;
int array_length = sizeof(array)/sizeof(array[0]);
int i = 0;
array = (int*)malloc(array_length*sizeof(int));
struct node *root = NULL;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 20);
check(root, array, i);
printf("PRINTING ARRAY TO SEE IF THE BST IS IN ARRAY:\n");
for(i = 0; i < array_length; i++){
printf("VALUE: %d ", array[i]);
}
free(array);
return 0;
}
I'd like to solve this problem WITHOUT using global variables. How can I do it?
I see two issues in your check-code and its usage (did not analyse the other functions):
First, your malloc does not work as intended, because sizeof(array)/sizeof(array[0]) will always give the same (small) value, probably 1 or 2, regardless of the size of your BST.
So you'd rather introduce a function getting the number of nodes and use this as the length for your array:
int array_length = getNrOfNodes(root); // function to be coded
int *array = malloc(array_length*sizeof(int));
Second, you pass an integral value i by value to a recursive function. As it is passed by value, any i++ will take effect only for the respective function call instance, but will not influence the other ones on the call stack. So it is very likely that the keys of the complete left part of your tree (the one before i is altered), will be written to array[0].
I'd suggest to share the array index among the function instances on the call stack. This can be achieved by passing a pointer to some i rather than passing i-s value around. And I'd introduce an internal version that does the work, because the user of the function needs not to be aware of the helper variable i:
void writeToArray_internal(struct node *root, int *array, int *i){
if(root != NULL){
writeToArray_internal(root->left, array, i);
array[*i] = root->key;
(*i)++;
writeToArray_internal(root->right, array, i);
}
}
void writeToArray(struct node *root, int *array) {
int i=0;
writeToArray_internal(root, array, &i);
}
This line here
int array_length = sizeof(array)/sizeof(array[0]);
is wrong. This only works with pure arrays, because sizeof returns the amount
of bytes of the expression/variable. Your variable array is a pointer, so
sizeof array returns you the size of a pointer and it doesn't matter where the
pointer is pointer, you always will get the same size.
Besides trying to get the number of elements of the "array" before knowing how
many nodes you have, makes no sense, because the number of elements that you need in array depend on the number of nodes, so
you've got write a function that returns you the number of nodes and then
you can allocate space for array.
Also note that your check function is not correct either. The variable i is
local to every call of check so you are going to overwrite values of the
array, because the i++ of the n-th iteration only affects the i of the
n-the iteration, the n-1-th iteration does not see that change and thus
overwrites the value of the n-th iteration.
You'll need to pass i as a pointer as well:
void check(struct node *root, int *array, size_t *i, size_t maxlen) {
if(root != NULL){
check(root->left, array, i, maxlen);
if(*i < maxlen) // checking that you don't step out of bounds
array[(*i)++] = root->key;
check(root->right, array, i, maxlen);
}
}
and the you call it like this:
size_t i = 0;
size_t nodes_number = get_number_of_nodes(root); // you have to write this function
int *array = malloc(nodes_number * sizeof *array);
if(array == NULL)
{
// error handling
// do not continue
}
check(root, array, &i, nodes_number);
I've implemented a Singly Linked List, and I'm noticing really strange behavior but can't pinpoint the exact reason why it's happening. I've tried using gdb to figure out what the problem is, and it looks like whenever I compute the size of a list, that's when things start to go wrong. This is the program I'm using to test out my implementation, and following is the actual implementation.
#include <stdio.h>
#include "singlylinked.h"
slist initialize(void); /* initializes test singly linked list */
slist initialize(){
int i, a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
slist l = sl_alloc();
int a_size = sizeof(a)/sizeof(a[0]);
for(i=0;i<a_size;i++){
sl_add(l, (void *)&a[i]);
}
return l;
}
int main(){
slist l = initialize();
int i, size = sl_size(l);
for(i = 0; i < size; i++){
printf("%d ", *(int *)sl_get(l,i));
}
fputc('\n',stdout);
return 0;
}
And now the actual implementation, I'm only going to post the methods used in the testing:
/* allocates an empty slist */
slist sl_alloc(){
return (slist) calloc(1, sizeof(struct node));
}
/* adds val to linked list */
void sl_add(slist l, void *val){
node *current, *new;
new = calloc(1, sizeof(struct node));
new->content = val;
new->next = NULL;
if((current = *l)){
while(current->next){
current = current->next;
}
current->next = new;
} else {
*l = new;
}
}
/* returns ith value in singly linked list l */
void *sl_get(slist l, int i){
node *current;
int j; /* counter */
void *result = NULL;
if((current = *l)){
int size = sl_size(l);
if(i < size){
for(j = i; j > 0; j--){
current = current->next;
}
result = current->content;
}
}
return result;
}
/* returns the size of the singly linked list */
int sl_size(slist l){
int size = 0;
node *current;
if((current = *l)){
do {
size++;
current = current->next;
} while (current);
}
return size;
}
And now this is how I define slist and struct node:
typedef struct node **slist;
typedef struct node {
void *content;
struct node *next;
} node;
EDIT: The strange behavior is this: When I try to print things out, it prints out the wrong values in the list. When I ran the program using gdb, this starts to happen after the first call to sl_size.
The problem is your initialisation of the list.
You add the 10 elements of the array a[] to the list that you are creating in initialize(). The only problem is that you store in your list nodes pointers to the data in the array a[]. Unfortunately this array is local to the function ! As soon as you return from initialize(), this array is no longer valid, and the pointer point to no valid place anymore. In consequence, the numbers that you expect to point to will be replaced by "garbage" value.
I am creating a binary tree from a bitstring in c. ie 1100100 creates a tree:
1
/ \
1 1
I decided to use a recursive function to build this tree however i keep getting the error
Debug assertion failed...
Expression : CrtIsValidHeapPointer(pUserData)
here is a fragment of my code
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
char string[1000];
int i = 0;
void insertRecursivePreorder(Node **node)
{
Node* parent = *node;
if(string[i] == '0')
{
parent = NULL;
i++;
}
else
{
Node *newn = (Node*)malloc(sizeof(Node));
newn->key = string[i];
parent = newn;
i++;
insertRecursivePreorder(&newn->left); //errors occur here
insertRecursivePreorder(&newn->right); //errors occur here
free(newn);
free(parent);
}
}
int main(void)
{
void printTree(Node* node);
Node* root = NULL;
scanf("%s", string);
insertRecursivePreorder(&root);
//... do other junk
}
i was wondering why this error comes about and what i can do to fix it.
The immediate problem is likely to be calling free on a pointer twice. In insertRecursivePreorder, you set parent to newn, and then call free on both. As an example of this, the following program fails (but works if you comment out one of the free(..)s):
#include <stdlib.h>
int main() {
int *a = malloc(sizeof(int)),
*b = a;
free(a);
free(b);
return 0;
}
However, there are several problems with your logic here. You should only call free when you have completely finished with the pointer, so if you are using your tree later you can't free it as you construct it. You should create a second function, recursiveDestroyTree, that goes through and calls free on the tree (from the bottom up!).
And, you probably want *node = newn rather than parent = newn, since the latter is the only one that actually modifies node.
(You could also change your function to return a Node * pointer, and then just go:
root = insertRecursivePreorder();
and
newn->left = insertRecursivePreorder();
newn->right = insertRecursivePreorder();
instead of trying to keep track of pointers to pointers etc.)
(Furthermore, on a stylistic point, using global variables is often bad practice, so you could have your insertRecursivePreorder take int i and char * string parameters and use them instead of global variables.)
The problem was: you were never assigning to the double pointer in 'insertRecursivePreorder', so root always stayed NULL.
#include <stdio.h>
#include <stdlib.h>
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
/* slightly changed the syntax for the str
** ; now '.' indicates a NULL pointer, values represent themselves.
*/
char *string = "12..3.." ;
/* Removed the global index 'i' */
void printTree(Node* node, int level);
unsigned insertRecursivePreorder(Node **pp, char *str);
unsigned insertRecursivePreorder(Node **pp, char *str)
{
unsigned pos =1;
if (!*str) { *pp = NULL; return 0; } /* safeguard for end of string */
if (*str == '.') { *pp = NULL; return pos; }
*pp = malloc(sizeof **pp);
(*pp)->key = *str;
pos += insertRecursivePreorder(&(*pp)->left, str+pos);
pos += insertRecursivePreorder(&(*pp)->right, str+pos);
return pos;
}
void printTree(Node* node, int level)
{
unsigned pos,len;
len = level> 0 ? level : -level;
for (pos =0; pos < len; pos++) putchar (' ');
if (!level) printf ("Root=");
else if (level<0) printf ("Left=");
else printf ("Right=");
if (!node) { printf( "Null\n" ); return; }
printf("Key=%c\n", node->key );
printTree(node->left, -(len+1) ) ;
printTree(node->right, len+1) ;
}
int main(void)
{
Node *root = NULL;
unsigned result = 0;
result = insertRecursivePreorder(&root, string);
printf( "Result=%u\n", result);
printTree(root, 0);
return 0; printTree(root, 0);
}
Output:
Result=7
Root=Key=1
Left=Key=2
Left=Null
Right=Null
Right=Key=3
Left=Null
Right=Null
I have a C program for an exercise and it has a strange issue
The program runs just fine on VS 2005 but it crashes on DEV-C++ and the problem that the problem is that the exercise is always evaluated against DEV-C++
The program is about inserting nodes to a BST and this is where the problem lies...
Well i would really appreciate some help.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct tree_node
{
int value;
int weight;
struct tree_node *left;
struct tree_node *right;
} TREE_NODE;
TREE_NODE *create_tree(int list[], int size);
TREE_NODE *search_pos_to_insert(TREE_NODE *root, int value, int *left_or_right);
// this is the problematic function */
void inorder(TREE_NODE *root); /* Inorder Traversing */
TREE_NODE *temp;
int main()
{
TREE_NODE *root; /* Pointer to the root of the BST */
int values[] = {10, 5, 3, 4, 1, 9, 6, 7, 8, 2}; /* Values for BST */
int size = 10, tree_weight;
root = create_tree(values, 10);
printf("\n");
inorder(root); /* Inorder BST*/
system("PAUSE");
}
TREE_NODE *search_pos_to_insert(TREE_NODE *root, int value, int *left_or_right)
{
if(root !=NULL)
{
temp = root;
if(value >root->value)
{
*left_or_right=1;
*search_pos_to_insert(root->right, value, left_or_right);
}
else
{
*left_or_right=0;
*search_pos_to_insert(root->left, value, left_or_right);
}
}
else
return temp;/* THIS IS THE PROBLEM (1) */
}
TREE_NODE *create_tree(int list[], int size)
{
TREE_NODE *new_node_pntr, *insert_point, *root = NULL;
int i, left_or_right;
/* First Value of the Array is the root of the BST */
new_node_pntr = (TREE_NODE *) malloc(sizeof(TREE_NODE));
new_node_pntr->value = list[0];
new_node_pntr->weight = 0;
new_node_pntr->left = NULL;
new_node_pntr->right = NULL;
root = new_node_pntr;
/* Now the rest of the arrat. */
for (i = 1; i < size; i++)
{
/* THIS IS THE PROBLEM (2) */
insert_point = search_pos_to_insert(root, list[i], &left_or_right);
/* insert_point just won't get the return from temp */
new_node_pntr = (TREE_NODE *) malloc(sizeof(TREE_NODE));
new_node_pntr->value = list[i];
new_node_pntr->weight = 0;
new_node_pntr->left = NULL;
new_node_pntr->right = NULL;
if (left_or_right == 0)
insert_point->left = new_node_pntr;
else
insert_point->right = new_node_pntr;
}
return(root);
}
void inorder(TREE_NODE *root)
{
if (root == NULL)
return;
inorder(root->left);
printf("Value: %d, Weight: %d.\n", root->value, root->weight);
inorder(root->right);
}
Your search_pos_to_insert isn't returning anything in the first section, where root is not NULL. It is recursively calling the function, but not gathering the result. You need to return whatever your recursive calls return to ensure correctness.
You should change the calls
*search_pos_to_insert(root->right, value, left_or_right);
...
*search_pos_to_insert(root->left, value, left_or_right);
to
return search_pos_to_insert(root->right, value, left_or_right);
...
return search_pos_to_insert(root->left, value, left_or_right);
While I haven't delved deep into many issues, are you sure your use of "temp" as a global is correct here? Should it not be local to the search function, so the function is reentrant?
In your function TREE_NODE *search_pos_to_insert() you have code pathes, that don't return a value. Your compiler should issue a warning about it.
The line:
return temp;/* THIS IS THE PROBLEM (1) */
is reached only if the if(root != NULL) evaluates to true.
Replace the recursive calls with:
return search_pos_to_insert(root->right, value, left_or_right);
return search_pos_to_insert(root->left, value, left_or_right);
to make it work.
Frank your the man ..
In some moment i thought that maybe i could return the function itself but i was almost sure it wouldn't work and also i took a different road (to left_or_right) and i was completely lost
Well u saved from a lot of anger and u really saved my day(probably a lot more)