C - recursion not working in a Binary Search Tree - c

I'm implementing a BST in C. If the tree only has 2 leaves and nothing in between, recursion works. But as soon as it goes deeper (eg below 3 levels deep) - the recursion breaks.
My code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node* left;
struct node* right;
} node_t;
void print_tree(node_t* n, int indent) {
//base case, tree leaves
if (n->left == NULL && n->right == NULL) {
printf("%*c", indent, ' ');
printf("%d\n", n->val);
} else {
//print current level
printf("%*c", indent, ' ');
printf("%d\n", n->val);
//then kids
print_tree(n->left, indent+2);
print_tree(n->right, indent+1);
}
}
int bst() {
node_t* n1;
n1 = (node_t*) malloc(sizeof(node_t));
//level 1 children
n1->val = 5;
n1->left = (node_t*) malloc(sizeof(node_t));
n1->right = (node_t*) malloc(sizeof(node_t));
//level 2 children
n1->left->val = 3;
n1->left->left = (node_t*) malloc(sizeof(node_t));
n1->left->right = NULL;
n1->right->val = 10;
n1->right->left = (node_t*) malloc(sizeof(node_t));
n1->right->right = NULL;
//level 3 children
n1->left->left->val = 1;
n1->left->left->left = NULL;
n1->left->left->right = NULL;
n1->right->left->val = 6;
n1->right->left->left = NULL;
n1->right->left->right = NULL;
print_tree(n1, 0);
return 1;
}
What happens:
5
3
1
What I want to happen:
5
3
1
10
6
When I run in debug mode I see that for some reason the base case never triggers and so at some point n itself becomes NULL and the if statement breaks.
Why is the base case not triggering?

First point:
In your function print_tree, you are dereferencing n without checking if it is NULL.
This will cause trouble when there are nodes whose one child is NULL and the other child is not NULL.
You should add
if (n == NULL) return;
just after
void print_tree(node_t* n, int indent) {
Second point:
The line
print_tree(n->right, indent+1);
is wrong and it will make the number of spaces of 10 and 6 fewer than expected.
It should be
print_tree(n->right, indent+2);

Your recursion eventually reaches the point where it calls print_tree on the NULL pointer n1->left->right and you trigger a segmentation fault by trying to access n1->left->right->left in the first if statement of the function.
This might be more of what you want
void print_tree(node_t* n, int indent) {
if(n == NULL) {
return;
}
printf("%*c", indent, ' ');
printf("%d\n", n->val);
print_tree(n->left, indent+2);
print_tree(n->right, indent+2);
}

Related

Using recursive DFS to find node in binary tree

I have to use DFS to search a binary tree to find a node. (tok is the string I'm searching for). If it finds it, it has to return the number of nodes it traversed to find it. If it doesn't then it has to return -1.
I have tried many recursive solutions but honestly, I'm stumped. I may not be returning values correctly.
Test case:
Lets say i have a tree with the root called "John"."John" as a left child "Shayne" and a right child "Eric". Additionally, "Shayne" has a left child "Max". The output would be correct for John,Shayne and Max. But the output of Eric should be 4, since i traverse john and then shayne and then max and then Eric (considering im going left first and then right), but for Eric, im getting the output of 3
Edited with exact test case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char* name;
char* tea;
struct node* left;
struct node* right;
};
typedef struct node Node;
int depth(struct node* root);
int dfs(struct node* root, char* tok);
int main() {
Node* John = (Node*)malloc(sizeof(Node));
John->left = NULL;
John->right = NULL;
John->name = "John";
Node* Shayne = (Node*)malloc(sizeof(Node));
Shayne->left = NULL;
Shayne->right = NULL;
Shayne->name = "Shayne";
Node* Eric = (Node*)malloc(sizeof(Node));
Eric->left = NULL;
Eric->right = NULL;
Eric->name = "Eric";
Node* Max = (Node*)malloc(sizeof(Node));
Max->left = NULL;
Max->right = NULL;
Max->name = "Max";
John->left = Shayne;
Shayne->left = Max;
John->right = Eric;
printf("%d",dfs(John,"Eric"));
}
int depth(struct node* root) {
if (root == NULL) {
return 0;
}
int l = depth(root->left);
int r = depth(root->right);
int d = max(l, r) + 1;
return d;
}
int dfs(struct node* root, char* tok) {
if (root == NULL) {
return 0;
}
if (strcmp(root->name, tok) == 0) {
return 1;
}
else {
int l = dfs(root->left, tok);
if (l != -1) {
return 1 + l;
}
int r = dfs(root->right, tok);
if (r != -1) {
return 1+l+ r;
}
return -1;
}
}
You correctly add 1 to the return value when the value has been found in an immediate child to produce the number of nodes. But it also means that you will return 2 to your parent.
You have to change your test to
if (l != -1) { //found on left child
return 1 + l;
}
The only problem with your function is that when you are returning from the child node you are always checking the value of l with 1 for instance:
int l = dfs(root->left, tok);
if (l == 1) { //found on left child
return 1 + l;
}
which will work fine for the first 2 nodes but then the value of the return becomes 2,3,4,.... in that case it will skip the if and return -1 again, so to solving this problem a good approach will be to check if the return value is not -1, for example:
int l = dfs(root->left, string);
if (l != -1) {
return 1 + l;
}
int r = dfs(root->right, string);
if (r != -1) {
return 1 + r;
}
Hope this gives you the answer.

convert array to binary tree with recursive strategy

I need to create a binary tree starting from vector containing some zeros where a zero represents a node that doesn't exists. for example if I got:
int a[] = {10,4,7,2,3,-1,8,9,-1,2,4,5};
I would like my output like this:
10
/ \
4 7
/ \ \
2 3 8
/ / \ /
9 2 4 5
my struct:
typedef struct node {
int n;
struct node * dx;
struct node * sx;
} *Bit_node;
method to build one node:
Bit_node bit_new(int n) {
Bit_node new_node = malloc(sizeof(struct node));
new_node -> n = n;
return new_node;
}
method to build the whole tree:
Bit_node bit_arr2tree(int a[], int size, int i) {
if (i>= size) {
return NULL;
}
if(a[i] != -1) {
Bit_node new_node = bit_new(a[i]);
new_node -> sx = bit_arr2tree(a, size, i*2 +1);
new_node -> dx = bit_arr2tree(a, size, i*2 +2);
}
return new_node;
}
But with my implementation my tree is built not considering the "holes". Is there a way to considering them , keeping the recursive strategy?
First of all, int a[] = {10,4,7,2,3,-1,8,9,-1,2,4,5}; shouldn't produce the tree you expect, with 5 as the left child of 8. Since 8 is at index 6, its left child would be at index 6 * 2 + 1 == 13. So your input should probably be int a[] = {10,4,7,2,3,-1,8,9,-1,2,4,-1,-1,5};, with two extra -1s towards the end of the array to push 5 to the correct index.
Your implementation can't work because in the pattern:
{
Bit_node new_node = malloc(...)
}
return new_node;
new_node is being accessed when not in scope. If you encounter a -1, you want to return NULL just like you're doing if you go out of bounds on the array. Returning NULL says "there is no child here", which is exactly what you want to communicate to a parent frame so that it sets the missing child to NULL.
The fix should be pretty straightforward:
Bit_node bit_arr2tree(int a[], int size, int i) {
if (i>= size || a[i] < 0) {
// ^^^^^^^^^^^
return NULL;
}
Bit_node new_node = bit_new(a[i]);
new_node->sx = bit_arr2tree(a, size, i * 2 + 1);
new_node->dx = bit_arr2tree(a, size, i * 2 + 2);
return new_node;
}
As an aside, I'd caution against typedeffing away pointers. This makes the code less readable and hides information.
Here's a runnable proof of concept:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *left;
struct Node *right;
};
struct Node *arr2tree(int arr_len, int *arr, int i) {
if (i >= arr_len || arr[i] < 0) {
return NULL;
}
struct Node *node = malloc(sizeof(*node));
node->data = arr[i];
node->left = arr2tree(arr_len, arr, i * 2 + 1);
node->right = arr2tree(arr_len, arr, i * 2 + 2);
return node;
}
void print_tree(struct Node *root, int depth) {
if (root) {
print_tree(root->right, depth + 4);
for (int i = 0; i < depth; i++) {
printf(" ");
}
printf("%d\n", root->data);
print_tree(root->left, depth + 4);
}
}
void free_tree(struct Node *root) {
if (root) {
free_tree(root->left);
free_tree(root->right);
free(root);
}
}
int main() {
int a[] = {10,4,7,2,3,-1,8,9,-1,2,4,-1,-1,5};
struct Node *root = arr2tree(sizeof(a) / sizeof(a[0]), a, 0);
print_tree(root, 0);
free_tree(root);
return 0;
}
Output:
8
5
7
10
4
3
2
4
2
9
Given that the input data structure does not guarantee the relationship between parent and children is i*2+1 and i*2+2, a recursive solution is not really called for. The input sequence represents a breadth-first order, so it would be more natural to build the tree in breadth-first order.
As a side note: the function bit_new should also initialise the sx and dx members: you don't want to leave those with undefined values.
Here is how you could write your algorithm:
Bit_node bit_new(int n) {
Bit_node new_node = malloc(sizeof(struct node));
new_node -> n = n;
new_node -> sx = NULL;
new_node -> dx = NULL;
return new_node;
}
Bit_node bit_arr2tree(int a[], int size) {
if (size == 0) {
return NULL;
}
// Create a temporary array to store the node pointers
Bit_node nodes[size];
// Create the nodes
for (int i = 0; i < size; i++) {
nodes[i] = a[i] == -1 ? NULL : bit_new(a[i]);
}
// To link the nodes, use two indexes: parent and child
for (int child = 1, parent = 0; child < size; child += 2, parent++) {
// Here we "skip the gaps": a parent cannot be NULL:
while (nodes[parent] == NULL) {
parent++;
}
nodes[parent] -> sx = nodes[child];
if (child + 1 < size) {
nodes[parent] -> dx = nodes[child + 1];
}
}
return nodes[0];
}

Taking values from stdin and storing those in linked list nodes

Yesterday after I did a stupid approach, I think I am on a good way right now. The thing I wanna program is that I am getting n values from the user and I am trying to store every value into a linked list node which has to be sorted after every input.
So it means:
Input:
5 1 9
Output:
1 5 9
Input:
2 3
Output:
1 2 3 5 9
My code so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
int val;
struct node* next;
} node;
void printList(node* n) {
while (n != NULL) {
printf("%d ", n->val);
n = n->next;
}
}
void push(node * head, int val) {
node * current = head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
current->next = malloc(sizeof(node));
current->next->val = val;
current->next->next = NULL;
}
int main() {
char input[20];
char* ptr;
node* head = NULL;
head = (node*) malloc(sizeof(node));
do {
printf("Eingabe:");
fgets(input,20,stdin);
ptr = strtok(input," ");
while(ptr!=NULL){
int val = atoi(ptr);
push(head,val);
ptr = strtok(NULL, " ");
}
printList(head);
}
while(*input != '0');
return 0;
}
Edited my code, node creation is working , but when I input 5 1 9 , it outputs 0 5 1 9 where is that 0 coming from?
The 0 is the value of your head.
When you create the first node you add it as the next of the head, this means that by having as input 5 1 9 your linked list will be:
head -> 5 -> 1 -> 9
When you print you don't just print the values of the nodes you have created but also the value of the head, since the value was never initialized and in the struct it's an int your compiler intializes it to 0 automatically (this depends on the compiler implementation so it's always better to initialize it).
If you don't want that 0 in the front you have a couple of options:
assign to head->value the first number that you input
call the printList as printList(head->node)
change your linked list implementation to not have the head hold a value
change printList to:
void printList(node* n) {
n = n->next;
while (n != NULL) {
printf("%d ", n->val);
n = n->next;
}
}
The correct approach could be (pseudo-code):
[START]
Read new line from the STDIN;
While there are new values:
Read new value;
Add it on new node (easier adding on top of the list);
Sort the list;
Print the list;
Loop to [START]
In your code you are missing the "sort the list" phase.
Easier if you add a swap function and try one of sorting algorithm on your choice

Fibonacci Sequence using Linked List crashes after linked list is destroyed. How can I trace the error?

I'm working on a program that calculates any number in the Fibonacci Sequence without using the int data type since it would overflow. Instead I am using linked lists to hold the digits that represent each number. My current issue is with freeing memory allocated to linked lists that I no longer need. If I'm calculating F(10000), I'd like the thousands of previous lists to be freed. The program as is produces each value up to "F(7) = 13" before crashing and showing "exit status -1". I'd really just like to know what's causing this error and go from there. Any help is appreciated. Thank you and I apologize for the large amount of code.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int digit;
struct Node *next;
} Node;
typedef struct ListyInt
{
Node *head;
int length;
} ListyInt;
Node *create_node(unsigned int digit, ListyInt *listy);
Node *removeNode(Node *node, ListyInt *listy);
void listyPrintHelper(Node *current);
ListyInt *destroyListyInt(ListyInt *listy);
ListyInt *fib(unsigned int n);
void listyPrint(ListyInt *p)
{
if (p == NULL || p->head == NULL)
{
printf("(null pointer)\n");
return;
}
listyPrintHelper(p->head);
printf("\n");
}
void listyPrintHelper(Node *current)
{
if (current == NULL)
return;
listyPrintHelper(current->next);
printf("%d", current->digit);
}
int main()
{
int i;
ListyInt *p;
for (i = 0; i <= 1000; i++)
{
printf("F(%d) = ", i);
listyPrint(p = fib(i));
destroyListyInt(p);
}
return 0;
}
ListyInt *listyAdd(ListyInt *p, ListyInt *q)
{
ListyInt *listy = NULL;
Node *ptemp = NULL;
Node *qtemp = NULL;
Node *temp = NULL;
ListyInt *temp_list = NULL;
unsigned int x = 0;
unsigned int count = 0;
if (p == NULL || q == NULL)
{
return NULL;
}
listy = malloc(sizeof(ListyInt));
if (listy == NULL)
{
return NULL;
}
listy->length = 0;
if (q->length > p->length)
{
temp_list = q;
q = p;
p = temp_list;
}
while (count < p->length)
{
if (count == 0)
{
x = p->head->digit + q->head->digit;
ptemp = p->head->next;
qtemp = q->head->next;
listy->head = create_node(x, listy);
temp = listy->head;
temp->next = create_node(0, listy);
if (temp->digit > 9)
{
temp->digit = temp->digit - 10;
temp->next->digit = temp->next->digit + 1;
}
}
else
{
temp->next->next = create_node(0, listy);
if (qtemp == NULL)
{
temp->next->digit += ptemp->digit;
ptemp = ptemp->next;
temp = temp->next;
}
else
{
x = ptemp->digit + qtemp->digit;
temp->next->digit += x;
if (temp->next->digit > 9)
{
temp->next->digit = temp->next->digit - 10;
temp->next->next->digit = temp->next->next->digit + 1;
}
qtemp = qtemp->next;
ptemp = ptemp->next;
temp = temp->next;
}
}
if (count == p->length - 1 && temp->next->digit == 0)
{
temp->next = removeNode(temp->next, listy);
}
count++;
}
return listy;
}
ListyInt *destroyListyInt(ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *current = listy->head;
Node *temp;
while (current != NULL)
{
temp = current->next;
free(current);
current = temp;
}
free(listy);
return NULL;
}
ListyInt *fib(unsigned int n)
{
ListyInt *spiral = malloc(sizeof(ListyInt));
ListyInt *p = NULL;
ListyInt *q = NULL;
unsigned int count = 2;
if (spiral == NULL)
{
return NULL;
}
if (n == 0)
{
spiral->head = create_node(0, spiral);
return spiral;
}
if (n == 1)
{
spiral->head = create_node(1, spiral);
return spiral;
}
p = malloc(sizeof(ListyInt));
p->head = create_node(0, p);
q = malloc(sizeof(ListyInt));
q->head = create_node(1, q);
while (count <= n)
{
spiral = listyAdd(p, q);
destroyListyInt(p);
p = q;
q = spiral;
count++;
}
return spiral;
}
Node *create_node(unsigned int digit, ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *new_node = malloc(sizeof(Node));
new_node->digit = digit;
new_node->next = NULL;
listy->length++;
return new_node;
}
Node *removeNode(Node *node, ListyInt *listy)
{
if (node == NULL)
{
return NULL;
}
if (listy == NULL)
{
return NULL;
}
free(node);
node = NULL;
listy->length--;
return NULL;
}
I'd really just like to know what's causing this error and go from there.
Long story short, C's equivalent of a NullPointerException, as far as I can tell.
Long story longer, I haven't had time to fully examine your code or debug it, but I have had time to run it through gdb, which is included with most Linux installations. If you're using Visual Studio, I vaguely remember there being a debug mode, which should show you roughly the same information, just in a different place. This is GDB's output:
Starting program: /home/ubuntu/C/a.out
F(0) = 0
F(1) = 1
F(2) = 1
F(3) = 2
F(4) = 3
F(5) = 5
F(6) = 8
F(7) = 13
Program received signal SIGSEGV, Segmentation fault.
0x00000000004008db in listyAdd (p=0x6036a0, q=0x6036e0) at main.c:117
117 temp->next->digit += ptemp->digit;
(Okay, that's not all of it, but that's the relevant bit.)
What those last three lines mean is that you got a segfault. There are a bunch of things that can cause it, but based on that line, it looks like it's been caused by trying to dereference an invalid pointer. That's either a NULL pointer (a value of 0x0) or a pointer you've already freed.
If you're on Linux, you can then run Valgrind on it to figure out what, exactly, happened. It'll tell you if it's using a freed pointer or a NULL one, and that'll give you a good starting point to find the actual bug. You can also use your IDE's debugger (or GDB, if you want to try playing with the command-line version, but I wouldn't recommend it) to step through your program and see what the values of the variables involved are, which you can walk backwards from to see where they're being changed and invalidated.
If I had to guess, though, I'd say 0andriy's comments hit it on the nose -- you seem to be freeing things twice, and you probably meant to free them once, at the end.
I'm somewhat intentionally leaving this vague. Segfaults are common and (as you've noticed) difficult to debug, and you can only really learn how through experience. I think being shown the answer would honestly be less helpful than working through it yourself, and with tools like Valgrind and your debugger, that's not actually that hard, just tedious.
I found the issue. It was because the length of my linked lists weren't being reset when fib() was called. Thanks for your help everyone.

Linked list — deletion of nodes which contain prime numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have written a code in the C language which will create a linked list. The linked list structre has two fields, namely data and next; data contains integer data, next is a structure pointer.
The program asks the user to input data into the list. Once the data has been entered, the program will go through the list and check which data in the node contains a prime number. If it finds one such node, it will delete it and link the next node to the previous node, but I am getting a segmentation fault error and I am unable to solve.
I am putting below the code. Can you please be kind enough to help me solve it as I do not know how to find the problem?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
The problem is here:
while (temp != NULL) {
N = temp->next->data;
When you reach the last element of the list, temp is not NULL, but temp->next is so temp->next->data has undefined behavior.
There are other problems:
your prime() function is inefficient and will return 1 for 0 and 1.
you deletetheprime() function deletes the node and updates the pointer in the callers scope, but the caller does not update the link in the previous node nor the H pointer if the deleted node is the first.
you use global variables for no good reason, you should pass H to display() and make all variables local in main().
you never free the allocated objects, it is good style to free everything you allocate.
you should not hide pointers behind typedefs, make node a typedef for struct node but keep pointers visible, it is a good habit to avoid confusing both the reader and the programmer.
To delete the node, you should use the pointer to link trick:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p initially points to the head pointer H and subsequently points to the next member of the previous node. It can be used to update the head pointer or the link in the previous node when a node to be deleted is found.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
I shall attribute your please solve it! stance to your poor command of the English language. Please learn to improve both your communications and your programming skills by carefully studying answers on this site.
The problem occurs here, in main
while(temp!=NULL)
{
N=temp->next->data;
...
You are checking if temp is not NULL, which is correct, but accessing data of next node, which can be NULL, and has to be NULL near the end of the list, which leads to undefined behavior.
Simply modify it to
while(temp!=NULL)
{
N=temp->data;
...
Where you are sure that temp isn't NULL and you won't get segmentation error here. And it'll work.
Or if you need to access data of temp->next->next node, you've got to check if next->next isn't NULL as well.
while(temp!=NULL)
{
if (temp->next->next != NULL)
{
N=temp->next->data;
}
else // temp->next->next is NULL so you can't access the data
...

Resources