realloc in recursion in trees - c

I am trying to find the maximum sum leaf to root path in a Binary Tree as in below
http://www.geeksforgeeks.org/find-the-maximum-sum-path-in-a-binary-tree/
1) I am unable to find why the path doesn't get printed in the main()
Is this because of wrong reallocs in the function.?
2) Also is my free correct?
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
/* A tree node structure */
struct node
{
int data;
struct node *left;
struct node *right;
};
// Returns the maximum sum and prints the nodes on max sum path
int maxsumtoleaf(struct node *node,int** path,int &height)
{
// base case
if (node == NULL)
return 0;
printf("\n At node %d,",node->data);
if (node->left==NULL && node->left==NULL) {
*path=(int*)realloc(*path,sizeof(int));
*path[0]=node->data;
height=1;
printf("\n value is %d,",*path[0]);
return node->data;
}
// find the target leaf and maximum sum
int rightheight=0,leftheight=0;
int *path1=NULL,*path2=NULL;
int left=maxsumtoleaf (node->left,&path1,leftheight);
int right=maxsumtoleaf (node->right,&path2,rightheight);
if ( left > right ) {
printf("\nbefore left is");
for(int i=0;i<leftheight;i++)
printf("%d,",path1[i]);
path1=(int*)realloc(path1,sizeof(int)*(leftheight+1));
if ( path1 == NULL ) {
printf("Out of Memory!\n");
return 0;
}
path1[leftheight]=node->data;
height=leftheight+1;
printf("\nafter left %d is ",leftheight);
for(int i=0;i<height;i++)
printf("%d,",path1[i]);
path=&path1;
return left+node->data;
} else {
printf("\nbefore right is");
for(int i=0;i<rightheight;i++)
printf("%d,",path2[i]);
path2=(int*)realloc(path2,sizeof(int)*(rightheight+1));
if ( path2 == NULL ) {
printf("Out of Memory!\n");
return 0;
}
path2[rightheight]=node->data;
height=rightheight+1;
printf("\nafter right is");
for(int i=0;i<height;i++)
printf("%d,",path2[i]);
path=&path2;
return right+node->data;
}
// return maximum sum
}
/* Utility function to create a new Binary Tree node */
struct node* newNode (int data)
{
struct node *temp = new struct node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
/* Driver function to test above functions */
int main()
{
struct node *root = NULL;
/* Constructing tree given in the above figure */
/* (8<--2->-4)<-10->7 */
root = newNode(10);
root->left = newNode(-2);
root->right = newNode(7);
root->left->left = newNode(8);
root->left->right = newNode(-4);
int sum=0;
int** path=NULL;
int height=0;
sum = maxsumtoleaf(root,path,height);
printf ("\nSum of the nodes is %d ,len=%d", sum,height);
printf ("\nPath is ");
for(int i=0;i<height;i++)
printf("%d,",*path[i]);
free(path);
getchar();
return 0;
}
Output:
At node 10,
At node -2,
At node 8,
value is 8,
At node -4,
value is -4,
before left is8,
after left 1 is 8,-2,
At node 7,
value is 7,
before right is7,
after right is7,10,
Sum of the nodes is 17 ,len=2
Path is ---> Breaks at this point in main()

Code is C++ with passing args by reference and using new.
To make C, lots of little fixes including how C "reference" variable are passed (explicitly by address).
You are not doing rellloc() correctly should the allocation fail as you have lost the original pointer.
Always good form to NULL a pointer after freeing it.
#include <stdio.h>
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
/* A tree node structure */
struct node {
int data;
struct node *left;
struct node *right;
};
// Returns the maximum sum and prints the nodes on max sum path
int maxsumtoleaf(struct node *node, int** path, int *height) {
// base case
if (node == NULL)
return 0;
printf("\n At node %d,", node->data);
if (node->left == NULL && node->left == NULL) {
*path = (int*) realloc(*path, sizeof(int));
(*path)[0] = node->data;
*height = 1;
printf("\n value is %d,", *path[0]);
return node->data;
}
// find the target leaf and maximum sum
int rightheight = 0, leftheight = 0;
int *path1 = NULL, *path2 = NULL;
int left = maxsumtoleaf(node->left, &path1, &leftheight);
int right = maxsumtoleaf(node->right, &path2, &rightheight);
if (left > right) {
printf("\nbefore left is");
for (int i = 0; i < leftheight; i++)
printf("%d,", path1[i]);
path1 = (int*) realloc(path1, sizeof(int) * (leftheight + 1));
if (path1 == NULL) {
printf("Out of Memory!\n");
return 0;
}
path1[leftheight] = node->data;
*height = leftheight + 1;
printf("\nafter left %d is ", leftheight);
for (int i = 0; i < *height; i++)
printf("%d,", path1[i]);
*path = path1;
return left + node->data;
} else {
printf("\nbefore right is");
for (int i = 0; i < rightheight; i++)
printf("%d,", path2[i]);
path2 = (int*) realloc(path2, sizeof(int) * (rightheight + 1));
if (path2 == NULL) {
printf("Out of Memory!\n");
return 0;
}
path2[rightheight] = node->data;
*height = rightheight + 1;
printf("\nafter right is");
for (int i = 0; i < *height; i++)
printf("%d,", path2[i]);
*path = path2;
return right + node->data;
}
// return maximum sum
}
/* Utility function to create a new Binary Tree node */
struct node* newNode(int data) {
struct node *temp = malloc(sizeof *temp); // new struct node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
/* Driver function to test above functions */
int main() {
struct node *root = NULL;
/* Constructing tree given in the above figure */
/* (8<--2->-4)<-10->7 */
root = newNode(10);
root->left = newNode(-2);
root->right = newNode(7);
root->left->left = newNode(8);
root->left->right = newNode(-4);
int sum = 0;
int* path = NULL;
int height = 0;
sum = maxsumtoleaf(root, &path, &height);
printf("\nSum of the nodes is %d ,len=%d", sum, height);
printf("\nPath is %p ", path);
// return 0;
for (int i = 0; i < height; i++)
printf("%d,", path[i]);
free(path);
path = NULL;
// getchar();
return 0;
}
Preferred realoc() use
// Somehow these are to be updated (initial to NULL and 0)
some_type *current_ptr;
size_t current_element_count; // best too use type size_t
size_t new_element_count = some_function(current_size);
void *new_ptr = realloc(current_ptr, new_element_count * sizeof *current_ptr);
if (new_ptr == NULL && new_element_count > 0) {
Handle_OOM(); // current_ptr is still same & current_element_count elements
return;
}
current_ptr = new_ptr;
current_element_count = new_element_count;
// continue on the happy path

Related

Skip list getting lost when either inserting with a new level or adding a new node to lower level

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#define Malloc(n, type) (type *)malloc((unsigned)((n) * sizeof(type)))
#define Realloc(ptr, n, type) (type *)realloc(ptr, (n) * sizeof(type))
typedef struct Node
{
int key;
struct Node *next;
struct Node *down;
} Node;
typedef struct
{
int level;
struct Node *header;
} skiplist;
int level()
{
/*
This function takes the coin flip and decides the level of the node with each
level having a probability of 0.25.
arg: void
return: a number from the set {1,2,3, 4}
*/
int level = 1;
for (int i = 0; i < 3; i++)
{
unsigned int coin = (unsigned int)rand();
coin = coin % 2;
if (coin)
{
level++;
}
else
break;
}
return level;
}
skiplist skip_list_init();
Node *Traverse_Express(Node *, int);
Node *skip_list_search(skiplist, int);
Node *insert_level(Node *, int, int, int);
void skip_list_insert(skiplist *, int);
void skip_print(skiplist);
int main()
{
srand(time(0));
int arr[10000];
for (int i = 0; i < 10; i++)
{
arr[i] = (int)rand();
}
printf("The array is initialised\n");
skiplist list;
list = skip_list_init();
printf("The Skip list is initialised\n");
if (list.header == NULL)
{
printf("List is null\n");
}
for (int i = 0; i < 10; i++)
{
skip_list_insert(&list, arr[i]);
printf("The %d element is initialised with key: %d\n", i, arr[i]);
}
printf("The skip list is:\n");
skip_print(list);
return 0;
}
void skip_print(skiplist list)
{
/*
The function prints the skip list level-wise.
arg: list
return: none
*/
Node *temp = list.header;
int count = 0;
for (int i = list.level; i > 0; i--)
{
printf("The Keys at level %d:\n", i);
while (NULL != temp->next)
{
printf("%d ->", temp->key);
temp = temp->next;
}
printf("%d\n", temp->key);
int dummy = count;
temp = list.header;
while (dummy)
{
temp = temp->down;
dummy--;
}
count++;
}
}
skiplist skip_list_init()
{
/*
This function creates the first node in the skip list with key value
to be negative infinity and level of the list =1.
arg: None
return: Skiplist initialised with a Node having key as INT_MIN.
*/
skiplist list;
Node *head;
if (NULL == (head = Malloc(1, Node)))
{
exit(1);
}
list.header = head;
list.level = 1;
head->key = INT_MIN;
head->next = NULL;
head->down = NULL;
return list;
}
Node *skip_list_search(skiplist list, int key)
{
/*
The function returns a pointer to the either the key itself if present
or the key immediatedly smaller than the searched key.
arg:
list:The skiplist to be searched. Type: skiplist
key: A key to be searched. Type: int.
return: Type: Node pointer
A pointer to the searched key or immediately smaller it.
*/
if (list.header == NULL)
exit(1);
else
skip_print(list);
int level = list.level; // Number of levels already present in the list
Node *curr = list.header;
printf("Inside Skip search\n");
printf("The value of level %d\n", level);
for (; level > 0; level--)
{
curr = Traverse_Express(curr, key);
if ((curr->key == key) && (INT_MIN != curr->key))
{
return curr;
}
if (NULL != curr->down)
curr = curr->down;
}
printf("The value at current node %d\n", curr->key);
printf("Leaving Skip_search\n");
return curr;
}
Node *Traverse_Express(Node *temp, int key)
{
printf("On the express way\n");
printf("We are searching the key: %d\n", key);
while (key > temp->key && NULL != temp->next)
{
printf("Loop of expressway\n");
printf("The current key : %d\n", temp->key);
if (key >= temp->next->key)
temp = temp->next;
else
break;
}
printf("Left the express way\n");
return temp;
}
Node *insert_level(Node *nod, int key, int lev, int list_lev)
{
/*
Inserting the key till the required level
arg:
nod: a pointer to the exsiting skip list
key: key to be inserted
lev: the level of the key
list_lev: the number of levels in the given skiplist
return: A Node pointer to the head of the skiplist with the key
inserted to the existing list.
*/
Node *temp1 = nod, *temp3 = NULL;
printf("\nStarting of insert at level procedure\n");
// Procedure to cut-off the extra levels in the list if any
if (lev < list_lev)
{
for (int i = list_lev - lev; i > 0; i--)
{
printf("Searching on the level: %d\n", i + lev);
temp1 = Traverse_Express(temp1, key);
temp1 = temp1->down;
}
}
printf("The value of first node: %d\n", temp1->key);
// Procedure to insert from the required level till level 1
for (int i = 0; i < lev; i++)
{
Node *temp2 = Malloc(1, Node);
temp2->key = key;
temp2->next = NULL;
temp2->down = NULL;
temp1 = Traverse_Express(temp1, key);
printf("Temp1 current key:%d\n", temp1->key);
if (NULL == temp1->next)
{
temp1->next = temp2;
printf("Node inserted at level: %d\n", lev - i);
}
else
{
printf("Entered the else procedure\n");
temp2->next = temp1->next;
temp1->next = temp2;
printf("%d\n", temp1->next->key);
}
if (i > 0)
{
temp3->down = temp2;
}
temp1 = temp1->down;
temp3 = temp2;
/*
free(temp2);
if(temp3==NULL)
{
printf("did a fuck up\n");
exit(1);
}*/
}
skiplist list;
// list = skip_list_init(list);
list.header = nod;
list.level = list_lev;
printf("Printing skip list from insert level\n");
skip_print(list);
printf("End insert level procedure\n\n\n");
temp1 = temp3 = NULL;
return nod;
free(temp1);
free(temp3);
}
void skip_list_insert(skiplist *list, int key)
{
/*
This function finds the key value and if already present, then returns back
else it inserts the key at its right place.
arg: a skilplist by reference and a key
return: None
*/
printf("Inside skip_list_insert\n");
Node *req = skip_list_search(*list, key);
printf("The value returned by skip search %d\n", req->key);
if (key == req->key)
{
printf("Key %d is already present in skip list\n", key);
}
Node *temp1 = list->header;
int list_lev = list->level;
printf("The list level = %d\n", list_lev);
int lev = level();
printf("The prob level %d\n", lev);
Node *hold_prev = NULL;
// creating a skip list if level returned is greater than existing one.
if (lev > list_lev)
{
for (int i = lev - list_lev; i > 0; i--)
{
skiplist l = skip_list_init();
Node *inser = Malloc(1, Node);
printf("The value of i in loop %d\n", i);
inser->key = key;
inser->down = NULL;
inser->next = NULL;
l.header->next = inser;
Node *trans = l.header;
// Zipping the previous levels with new level
while (NULL != hold_prev)
{
trans->down = hold_prev;
trans = trans->next;
hold_prev = hold_prev->next;
}
hold_prev = l.header;
l.header = NULL;
if (hold_prev == NULL)
{
printf("Big Mistake");
exit(1);
}
else
{
printf("You are doing it correct way\n");
}
}
list->header = hold_prev;
list->level = lev - list_lev;
skip_print(*list);
// Returning a pointer to the zeroth element of last level in this list.
while (NULL != hold_prev->down)
{
hold_prev = hold_prev->down;
}
}
// Inserting the node till the min(list_lev, level())
if (list_lev > lev)
{
temp1 = insert_level(temp1, key, lev, list_lev);
}
else
{
temp1 = insert_level(temp1, key, list_lev, list_lev);
}
skiplist l1 = skip_list_init();
l1.header = temp1;
l1.level = list_lev;
skip_print(l1);
printf("\n Now the Zipping procedure with level()>list_lev starts\n");
// Zipping Procedure only if level()>list_lev
if (lev > list_lev)
{
hold_prev->down = temp1;
skiplist l1 = skip_list_init();
l1.header = list->header;
l1.level = lev;
skip_print(l1);
printf("the key at the first node:%d\n", temp1->key);
hold_prev = hold_prev->next;
while (temp1->key != key)
{
temp1 = temp1->next;
printf("Zipping over keys:\n");
printf("Current key: %d\n", temp1->key);
}
hold_prev->down = temp1;
list->level = lev;
}
if (list_lev > lev)
{
list->level = list_lev;
}
printf("\n\n\n");
}
The above is my implementation. I have tried with all my might to debug the code but I am falling to implement a skip list for past 1 month. I genuinely request with pleading hands πŸ™πŸ™πŸ™ to look into the implementation and please do let me know the fixes, I can do.
It would be a great help. Thank you.
I have tried with all my might to debug the code but I am falling to implement a skip list for past 1 month.
You will have much easier time debugging if you fill the list with some non-random values (you can switch back to random values once the program is working for all hand-coded combinations).
Also fix your comments so they match the code. E.g. here the comments are clearly wrong:
skiplist skip_list_init()
{
/*
This function creates the first node in the skip list with key value
to be negative infinity and level of the list =1.
arg: It takes a list by reference
return: None
*/
There is no arg and the return is not None.
You should avoid making a copy of the list when calling skip_list_search (pass a pointer to the list).
You should avoid this construct:
if (hold_prev == NULL)
{
printf("Big Mistake");
exit(1);
}
else
{
printf("You are doing it correct way\n");
}
It make your code way too long. Instead, do this:
assert(hold_prev != NULL);
Giving your variables meaningful names will also go a long way helping you and others understand the code.
With the value inputs by Gene and Employed Russian, the skip list implementation has a mistake in the function skip_print which unfortunately didn't transverse all the levels of the skip-list.
See here:
int count=0;
and
int dummy = count;
temp = list.header;
while (dummy)
{
temp = temp->down;
dummy--;
}
count++;
When count=0 implies dummy=0. This doesn't let your pointer temp transverse to the bottom level till the next iteration when count=1. Thus, effectively only transversing and printing till list.level-1.
Hence, the implementation doesn't work correctly.
Please incorporate the following code for skip_print:
void skip_print(skiplist list)
{
/*
The function prints the skip list level-wise.
arg: list
return: none
*/
Node *temp = list.header;
int count = 1;
while (temp)
{
Node *n1 = temp;
printf("Printing the keys at level: %d\n", count);
while (NULL != n1->next)
{
printf("%d ->", n1->key);
n1 = n1->next;
}
printf("%d\n", n1->key);
temp = temp->down;
count++;
}
}
The rest of the code seems to be working fine for me.

binary search tree delete function deleting the same thing twice

I am trying to create a binary search tree that deletes the 2 leftmost nodes in a bst. For some reason, my code deletes the first value twice instead of moving onto the next.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct treeNode {
char *word; // the string word that is stored
int origin; // position of the word in the original text input’s line 1
struct treeNode *left; // pointer for the left children of the node
struct treeNode *right; // pointer for the right children of the node
struct treeNode *parent; // pointer for the parent of the node
};
typedef struct treeNode NODE;
NODE *
addNode(NODE * r, char *x)
{
// r = root pointer of the tree
// x = value to add into this tree
// return the root of the updated tree
NODE *p = malloc(sizeof(NODE));
p->word = malloc(strlen(x) + 1);
strcpy(p->word, x); // strcpy input: (destination, data to be copied)
// printf("%s", x);
p->parent = NULL;
p->left = NULL;
p->right = NULL;
// if tree is empty, tree consists of p only
if (r == NULL)
return p;
if (strcmp(x, r->word) > 0) {
r->right = addNode((r->right), x);
return r;
}
else {
// add new node the left subtree
r->left = addNode((r->left), x);
return r;
}
return r;
}
NODE *
getLeftMostNode(NODE * root)
{
// return the pointer to the right most node
if (root == NULL)
return NULL;
NODE *p = root;
while (p->left != NULL)
p = p->left;
return p;
}
NODE *
addTree2Tree(NODE * X, NODE * Y)
{
if (X == NULL)
return Y;
if (Y == NULL)
return X;
X = addNode(X, Y->word);
X = addTree2Tree(X, Y->left);
X = addTree2Tree(X, Y->right);
return X;
}
NODE *
removeNode(NODE * r)
{
// remove any node that store value x from tree
// r: root pointer of this tree
// return root pointer of the updated tree after removal
NODE *p = getLeftMostNode(r);
NODE *C = p->parent;
NODE *A = p->left;
NODE *B = p->right;
if (C == NULL) {
// p is root of the tree
free(p);
return addTree2Tree(A, B); // add tree A and tree B and return the new combination tree
}
if (A != NULL) {
// make A a child of C assuming position of P
if (p == C->left)
C->left = A;
else
C->right = A;
A->parent = C;
free(p);
return addTree2Tree(r, B);
}
if (B != NULL) {
if (p == C->left)
C->left = B;
else
C->right = B;
B->parent = C;
free(p);
return r;
}
if (p == C->left)
C->left = NULL;
else
C->right = NULL;
free(p); // free allocation for p
return r;
}
void
printArray(NODE * r)
{
// print all the values on the tree rooted at node "r" // print in alphabetical order
// if the tree is empty, return // print all the values on the tree rooted at node "r" // print in the in-order order: print left first, followed by root, followed by right values
if (r == NULL) {
return;
}
else {
printArray(r->left); // print all values in left subtree
printf("%s ", r->word);
printArray(r->right); // print all values in right subtree
}
}
int
main()
{
// input must be implemented by linked list, not array
NODE *root = NULL;
int ch;
char in[1000]; // input array
int len = 0;
char del[100]; // word to be deleted
char word[1000];
while ((ch = getchar()) != '\n')
in[len++] = ch;
in[len] = '\0';
// printf("%s\n", in);
int i = 0,
j = 0;
while (i <= len) {
// space to store a word
if ((in[i] == ' ') || (in[i] == '\0') || (in[i] == '\t')) {
word[j] = '\0'; // end of word
j = 0;
root = addNode(root, word);
// printf("%s\n", word);
}
else
word[j++] = in[I];
i++;
}
int k = 0;
removeNode(root);
removeNode(root);
printArray(root);
printf("\n");
return 0;
}
this is the error that I got
The function removeNode is looking for parent, but parent is never assigned in addNode. You want to assign r->right->parent = r; and r->left->parent = r;.
BST doesn't keep duplicate keys. If strcmp(x, r->word) == 0, then don't add a new node.
addNode should also be corrected so that if r is NULL, the function returns the new node immediately.
NODE* addNode(NODE* r, char* x)
{
if(!x)
return NULL;
if (!r)
{
NODE* p = malloc(sizeof(NODE)); if (!p) return NULL;
p->word = strdup(x);
p->parent = NULL;
p->left = NULL;
p->right = NULL;
return p;
}
if (strcmp(x, r->word) > 0)
{
r->right = addNode((r->right), x);
r->right->parent = r;
return r;
}
else if (strcmp(x, r->word) < 0)
{
r->left = addNode((r->left), x);
r->left->parent = r;
return r;
}
return r;
}
Modify the insert functions such that root is assigned only once:
while (i <= len)
{
if ((in[i] == ' ') || (in[i] == '\0') || (in[i] == '\t'))
{
word[j] = '\0';
j = 0;
if(!root)
root = addNode(root, word);
else
addNode(root, word);
}
else
word[j++] = in[i];
i++;
}
Double check the pointers to make sure NULL pointers are avoided. For example:
NODE* removeNode(NODE* r)
{
if(!r)
return NULL;
NODE* p = getLeftMostNode(r);
if(!p)
return NULL;
...
}
I have not checked the rest of the code but the example will work with these changes made.

Infinite loops with a linked list

I'm working on a program that takes an input of numbers from stdin and computes the median of the sequence and prints it out as a float. I'm currently getting an infinite loop in the function
len(struct node *)
at the for loop and I'm not sure why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
float *val;
struct node *next;
};
int len(struct node *list) {
int i = 0;
struct node *temp = list;
for (i = 0; temp != NULL; i++) {
temp = temp->next;
}
return i;
}
float median(int size, struct node list) {
struct node temp = list;
int i = 0;
if (size == 1) {
return *temp.val;
} else
if (size == 2) {
return (*(temp.val) + *(temp.next->val)) / 2;
} else {
if (size / 2 == 1) {
for (i = 3; i != (size / 2) - 1; i++) {
temp = *(temp.next);
}
return *temp.val;
} else {
for (i = 3; i != (size / 2); i++) {
temp = *(temp.next);
}
return (*(temp.val) + *(temp.next->val)) / 2;
}
}
}
int main() {
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while ((err = scanf("%f", &temp)) != EOF) {
if (err < 1) {
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = &temp;
tmpnode->next = list;
list = tmpnode;
}
size = len(list);
if (size == 0) {
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
return 0;
}
Edit: I've fixed the infinite loop, but now I'm getting a segfault at temp = *(temp.next) in median(). Do I need to allocate for temp?
You created only one node and assigned next of the node to itself, so this is cause of the infinite loop.
Create new nodes and link them in the input loop.
Assigning address of temp to all nodes is also not good.
Your main() function should be like this:
int main(void){
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
if(tmpnode == NULL){
perror("malloc 1");
return 1;
}
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while((err = scanf("%f", &temp)) != EOF){
if(err < 1){
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = malloc(sizeof(float));
if(tmpnode->val == NULL){
perror("malloc 2");
return 1;
}
*tmpnode->val = temp;
tmpnode->next = malloc(sizeof(struct node));
if(tmpnode->next == NULL){
perror("malloc 3");
return 1;
}
tmpnode = tmpnode->next;
tmpnode->val = NULL;
tmpnode->next = NULL;
}
size = len(list);
if(size == 0){
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
/* code to free the list should be here */
return 0;
}
(I gave input 1 2 3 4 5 and this program's output was 1.500000, which might be wrong)
If you're looking for the median you would have to arrange the nodes in order and get the number that is in the middle.If the number of nods is even and there is no middle you should add the two middlemost numbers and divide them by two.
Is the sequence in order? If not you're miscalculating the median.
Supposing the sequence is in order.
I didn't really understand the usefulness of this statement
if(size/2 == 1)
Maybe you're trying to see if the size is odd. In that case you should do:
> if(size%2 == 1)
Why the list is probably looping might be due to this
for(i = 3; i != (size/2); i++){
temp = *(temp.next);
}
Suppose you pass a 5 to the function size/2=2 (decimal part is lost), so it'll keep on going until an overflow occurs and it actually reaches 2, making your program most probably seg_fault in the process.
Start from i=0, because even though you started from 3 your current node is not the third one but the FIRST ONE.
Good luck hope this helps!!!!

Error allocating memory for temp in queue push in c invalid write size of 8 from valgrind

This is my push function
void push(struct Map *map, struct Location location){
struct Node *temp = map->front;
temp->loc = location; //this line causes the error
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
free(temp);
}
and I am getting this error
==2301== Invalid write of size 8
==2301== at 0x401148: push (3146.c:239)
==2301== by 0x400DE7: findEntrance (3146.c:164)
==2301== by 0x400820: main (3146.c:55)
==2301== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2301==
I am doing a breadth first search on a grid of characters arranged to be a maze. I have been having trouble getting no memory leaks so I have finally found that using malloc helps, but I don't understand why I cannot do this data assignment without a segfault
The alternative is to not free it and have memory leaks, which I don't think is an acceptable solution. Where is my logic wrong?
Below this is the whole program
#include <stdio.h>
#include <stdlib.h>
struct Location;
struct Map;
struct Node;
//function names seem to self describe
void pathFinder(struct Map*);
void findEntrance(struct Map*);
void readInMap(struct Map*);
void printMap(struct Map*);//to screen
/* Q funcs */
void pop(struct Map*);
void push(struct Map*, struct Location);
struct Location {// simple location type
int x;
int y;
};
struct Node {//standard linked list node
struct Location loc;
struct Node *next;
};
struct Map { //variable size encompassing array, and dimension variables
char arr[100][100];
int xLength;//dimensions
int yLength;
int complete;
struct Node *rear;//Q pointers
struct Node *front;
struct Node *currLoc; //temp for BFS
struct Location entrance;
};
int main(){
struct Map map;//the one map to rule them all
map.xLength = 0;//map dimensions
map.yLength = 0;
map.front = NULL; // queue pointers init
map.rear = NULL;
map.currLoc = NULL;
map.entrance.x = 0;
map.entrance.y = 0;
map.complete = 0;
readInMap(&map);
findEntrance(&map);//start off by finding where to start
pathFinder(&map); // problem solver method
printMap(&map);
free(map.front);
free(map.rear);
free(map.currLoc);
return 0;
}
void pathFinder(struct Map *map){
int x;//should be the entrance already pushed from findEntrance
int y;
int done = 0;
struct Location temp;
temp.x = 0;// temp for pushing locations that are adjacent 0's
temp.y = 0;
while(map->front != NULL){
map->currLoc = map->front;//currLoc is just a copy so that we can pop the map location of currLoc from Q
pop(map);// pop so it cant be used twice in this loop
x = map->currLoc->loc.x;
y = map->currLoc->loc.y;
temp.x = 0;
temp.y = 0;
if(map->arr[y][x] == '0'){//protection of 1 values from replacement
map->arr[y][x] = 'X';//replace the array position loc w x
}
if(map->arr[y][x] == '0'){//protection of 1 values from replacement
map->arr[y][x] = 'X';//replace the array position loc w x
printf("test\n");
}
/* find adjacent 0's */
if((y < map->xLength)&&(map->arr[y+1][x] == '0')){
temp.x = x;
temp.y = y+1;
push(map, temp);
}
if((x < map->xLength)&&(map->arr[y][x+1] == '0')){
temp.x = x+1;
temp.y = y;
push(map, temp);
}
if((y > 0)&&(map->arr[y-1][x] == '0')){
temp.x = x;
temp.y = y-1;
push(map, temp);
}
if((x > 0)&&(map->arr[y][x-1] == '0')){
temp.x = x-1;
temp.y = y;
push(map, temp);
}
if((x == 0)||(x == map->xLength)||(y == 0)||(y == map->yLength)){ //then its not on the edge
if((x != map->entrance.x)&&(y != map->entrance.y)){
map->front = NULL;
map->complete++;
}
}
}
}
void findEntrance(struct Map *map){
struct Location entrance;
int done = 0;
int y=0;//index of current row depth
int x=0;//index of current column depth
if (done == 0){
for (x=0;x<=map->xLength;x++){ // top row
if (map->arr[y][x] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(y=0;y<=map->yLength;y++){//down the right side
if (map->arr[y][map->xLength] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(x;x>=0;x--){//bottom row RtoL
if (map->arr[map->yLength][x] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(y;y>=0;y--){//up the left side
if (map->arr[y][0] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
map->entrance = entrance;
push(map, map->entrance);
}
void readInMap(struct Map *map){
FILE *fptr;
char c;
char file_name[20];
int i,j;
int rows;
int cols;
int x,y;
printf("Size\n");
printf("Rows:");
scanf("%i", &rows);
printf("Columns:");
scanf("%i", &cols);
map->xLength = cols-1; //[y][xLength]
map->yLength = rows-1; //[yLength][x]
for (x=0;x<100;x++){
for (y=0;y<100;y++){
map->arr[x][y] = '1';//whole array is 1
}
}
printf("Type in the name of the file containing the Field\n");
scanf("%s",file_name);
fptr=fopen(file_name, "r");
for (i = 0; i <= map->xLength; i++){
for (j = 0; j <= map->yLength; j++){
c=fgetc(fptr); //handles new line character and spaces
while ( !((c == '1') || (c =='0')) ) {
c=fgetc(fptr);
}
map->arr[i][j] = c;
}
}
printf("\n");
fclose(fptr);
}
void printMap(struct Map *map){
int y;//index of current row depth
int x;//index of current column depth
for (x=0;x<=map->xLength;x++){
for (y=0;y<=map->yLength;y++){//current pos (x,y)
printf("%c", map->arr[x][y]);
}
printf("\n");
}
if(map->complete != 0){
printf("\n An exit to the maze was found that is not the entrance\n");
}else{
printf("\n No exit was found \n");
}
}
void pop(struct Map *map){
if (map->front != NULL){//if not empty
if (map->front == map->rear){
map->rear = NULL;//if the line length is 1, empty it
map->front = NULL;
}else{
map->front = map->front->next;//next in line
}
}else{
map->rear = NULL;//empty out the queue
map->front = NULL;
}
}
void push(struct Map *map, struct Location location){
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->loc = location;
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
free(temp);
}
When the Map is empty, both front and rear are NULL. So temp->loc is dereferencing a NULL pointer.
You need to malloc the new node and add that to the list. Additionally, you don't want to free here, as that deallocates the memory that you just added to the list.
void push(struct Map *map, struct Location location){
struct Node *temp = malloc(sizeof(struct Node));
temp->loc = location;
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
}
In pop is where you want to deallocate the memory:
void pop(struct Map *map){
struct Node *temp = map->front;
if (map->front != NULL){//if not empty
if (map->front == map->rear){
map->rear = NULL;//if the line length is 1, empty it
map->front = NULL;
}else{
map->front = map->front->next;//next in line
}
free(temp);
}else{
map->rear = NULL;//empty out the queue
map->front = NULL;
}
}

Creating a binary search tree in C99

I've got a programming class assignment due tonight at 8 PM CDT that I'm having trouble with. We are to take a list of the following numbers via reading a file:
9
30
20
40
35
22
48
36
37
38
place them in an array (easy enough), and then read these into a binary search tree using C. The first number in the list is the number of elements in the tree. The rest are placed into the following struct:
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
I think I've got the first part down pat. Take the stuff in using fscanf (I didn't choose to use this method, I like fgets better), call an insertion function on each member of the array, then call a "createNode" function inside the insertion function.
Problem is, I'm only getting one member into the BST. Furthermore, the BST must satisfy the condition node->left->data <= node->data < node->right->data... in other words, the nodes must be in order in the tree.
Here's what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node* createNode(int data);
Node* bstInsert(Node* root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node* root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if(argc != 2){
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if(in == NULL){
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while(!feof(in)){
fscanf(in, "%d", &num_read);
array[count] = num_read;
count++;
}
fclose(in);
if (array_size != count) {
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
Node *root1 = NULL, *root2 = NULL, *root3 = NULL;
int i;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (i = 0; i < array_size; i++) {
root1 = bstInsert(root1, array[i]);
}
displayTree(root1, 0);
return 0;
}
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
Node* current, previous, right;
current = root;
previous = root->left;
next = root->right;
else{
if(previous->data <= current->data){
}
}
return root;
}
Node* createNode(int data) {
// TODO
Node* aRoot;
if(!data)
return NULL;
aRoot = malloc(sizeof(Node));
if(!aRoot){
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch ,ch, ch);
}
void displayTree(Node* root, int depth){
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
main, createNode, displayTree, and padding are okay, I believe. It's bstInsert where I'm having trouble. I'm just not sure how to order things to create a valid tree.
EDIT:
I've edited bstInsert and injected some more logic. It should be printing out more leaves on the tree, but alas, it's only printing out the number "30". Here's the new function.
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
else{
if(data < root->data){
bstInsert(root->left, data);
}
else if(data > root->data || data == root->data){
bstInsert(root->right, data);
}
}
return root;
}
You have to assign the newly created node pointer to the correct part of the tree. This code does that. The key change is using the return value from bstInsert() correctly. The other changes are cosmetic. Note that I checked the input array by printing it out; also, it is sensible to print out the BST as you build it.
Don't use feof() as a loop control condition. It is almost invariably wrong when used as a loop control, but at least you have to also check the input operation that follows. I've written a lot of programs in my time; I've hardly ever used feof() (I found two places in my own code with it; in both, it was correctly used to distinguish between EOF and an error after an input had failed.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct
{
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node *createNode(int data);
Node *bstInsert(Node *root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node *root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if (argc != 2)
{
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if (in == NULL)
{
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while (count < array_size && fscanf(in, "%d", &num_read) == 1)
array[count++] = num_read;
fclose(in);
if (array_size != count)
{
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
for (int i = 0; i < array_size; i++)
printf("%d: %d\n", i, array[i]);
Node *root1 = NULL;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (int i = 0; i < array_size; i++)
{
root1 = bstInsert(root1, array[i]);
displayTree(root1, 0);
}
displayTree(root1, 0);
return 0;
}
Node *bstInsert(Node *root, int data)
{
if (root == NULL)
{
root = createNode(data);
if (root == NULL)
printf("%d not inserted, no memory available.\n", data);
}
else if (data < root->data)
root->left = bstInsert(root->left, data);
else
root->right = bstInsert(root->right, data);
return root;
}
Node *createNode(int data)
{
Node *aRoot;
aRoot = malloc(sizeof(Node));
if (!aRoot)
{
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
for (int i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch, ch, ch);
}
void displayTree(Node *root, int depth)
{
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
Ok, think about what you want to do in the different tree configurations:
when the tree is empty -> create a root node
when the tree isn't empty -> how do the value to be inserted and the value of the root compare?
above -> insert in the right subtree
below -> insert in the left subtree
equal -> do nothing (this actually depends on how your assignment tells you to treat duplicates)
From this basic algorithm, you should be able to figure out all the corner cases.
A simplified solution (naive insertion with recursion, data input noise removed):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int nums[] = { 6, 8, 4, 1, 3, 7, 14, 10, 13 }; // instead of the user input
typedef struct _node {
int value;
struct _node *left;
struct _node *right;
} node;
node *node_new(int v)
{
node *n = malloc(sizeof(*n));
assert(n);
n->value = v;
n->left = NULL;
n->right = NULL;
return n;
}
void insert(node **tree, node *leaf)
{
if (*tree == NULL) {
*tree = leaf;
} else if (leaf->value > (*tree)->value) {
insert(&((*tree)->right), leaf);
} else {
insert(&((*tree)->left), leaf);
}
}
void dump(node *tree, int level)
{
static const char *pad = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
if (tree != NULL) {
printf("%sSelf: %d\n", pad + 16 - level, tree->value);
if (tree->left) {
printf("%sLeft node:\n", pad + 16 - level);
dump(tree->left, level + 1);
}
if (tree->right) {
printf("%sRight node:\n", pad + 16 - level);
dump(tree->right, level + 1);
}
} else {
printf("%sEmpty\n", pad + 16 - level);
}
}
int main()
{
size_t n = sizeof(nums) / sizeof(*nums);
int i;
node *tree = NULL;
for (i = 0; i < n; i++) {
insert(&tree, node_new(nums[i]));
}
dump(tree, 0);
// give some work to the kernel
return 0;
}
You should consider doing this recursively. Remember that each node is a tree in itself:
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_struct {
int value;
struct tree_struct* left;
struct tree_struct* right;
} Tree;
Tree* addToTree(int value, Tree* tree)
{
if (tree == NULL) {
tree = malloc(sizeof(Tree));
tree->value = value;
tree->left = NULL;
tree->right = NULL;
} else {
if (value < tree->value) {
tree->left = addToTree(value, tree->left);
} else {
tree->right = addToTree(value, tree->right);
}
}
return tree;
}
int main(int argc, char** argv)
{
Tree* tree = NULL;
int in;
while (scanf("%d", &in) != EOF) {
tree = addToTree(in, tree);
}
return 0;
}

Resources