Using recursive DFS to find node in binary tree - c

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.

Related

How can I check if two binary trees contain the same nodes?

I am trying the implement a function which checks whether two binary search trees are equal, order of the nodes not matter. But my implementation does not work.
I am not allowed to flatten the trees into arrays.
this is what I have so far:
int isIdentical(struct Node* root1, struct Node* root2)
{
if (root1 == NULL && root2 == NULL)
return 1;
else if (root1 == NULL || root2 == NULL)
return 0;
else {
if (root1->data == root2->data && isIdentical(root1->left, root2->left)
&& isIdentical(root1->right, root2->right))
return 1;
else
return 0;
}
}
when supplied with trees containing the nodes tree A = 2 4 5 6 and Tree B = 2 5 4 6, the output should be:
1, meaning they are equal, but instead I am getting 0. I am not sure where I am going wrong.
This is how Node is implemeted:
struct Node {
int data;
struct Node* left;
struct Node* right;
};
Make a recursive function that traverses treeA and checks that every item is present in treeB. On failure it abandons the search and returns 0 for failure. It can be your function
int isIdentical(struct Node* root1, struct Node* root2)
If success, call the function again with the arguments for treeA and treeB reversed. The 'check if present' operation can be iterative and inline, because it does not need to backtrack.
Example untried code, to give the idea.
int isAllFound(struct Node* root1, struct Node* root2)
{
// recursive parse of tree 1
if (root1 == NULL)
return 1;
// iterative search of tree 2
int found = 0;
struct Node *root = root2;
while(root != NULL) {
if(root1->data == root->data) {
found = 1;
break;
}
if(root1->data < root->data)
root = root->left;
else
root = root->right;
}
if(!found)
return 0;
// continue recursive parse of tree 1
if(!isAllFound(root1->left, root2))
return 0;
if(!isAllFound(root1->right, root2))
return 0;
return 1;
}
Then call like
if(isAllFound(treeA, treeB) && isAllFound(treeB, treeA))
puts("Success!");
If every item of treeA can be found in treeB, and every item of treeB can be found in treeA then they contain the same data. Provided the keys are unique.
Why do you think they are equal? They are not.
tree A is represented as 2 4 5 6 which I guess you obtained by some sort of pre-order or level-order traversal. If your tree B (2, 5, 4, 6) is equal then with the same sort of traversal you'd obtain same order. They are not equal if the traversal is the same.
Order of nodes doesn't matter:
If the order of the nodes doesn't matter. One thing you could do is do an inorder traversal for both trees and you get a sorted array from both. Then compare both arrays element by element and declare equal or not.
Your function will only compare as equal 2 trees that have exactly the same structure. If the trees are balanced differently, the comparison will return 0 even if the values are identical.
Performing this comparison is non trivial as the trees can have an arbitrary depth if they are not balanced.
You can walk the first tree in depth first order to populate an array and then walk the second tree in depth first order, checking that the values are identical to those in the array.
Here is a simple implementation:
#include <stdlib.h>
struct Node {
int data;
struct Node* left;
struct Node* right;
};
size_t tree_length(const struct Node *root) {
return root ? 1 + tree_length(root->left) + tree_length(root->right) : 0;
}
void tree_store(int *array, size_t *pos, struct Node *node) {
if (node) {
tree_store(array, pos, node->left);
array[++*pos - 1] = node->data;
tree_store(array, pos, node->right);
}
}
int tree_check(int *array, size_t *pos, struct Node *node) {
if (node) {
return tree_check(array, pos, node->left)
&& array[++*pos - 1] == node->data
&& tree_check(array, pos, node->right);
} else {
return 1;
}
}
/* compare trees: return 0 if different, 1 if same values, -1 if allocation error */
int isIdentical(const struct Node *root1, const struct Node *root2) {
size_t len1 = tree_length(root1);
size_t len2 = tree_length(root2);
size_t pos;
if (len1 != len2)
return 0;
if (len1 == 0)
return 1;
int *array = malloc(sizeof(*array) * len1);
if (!array)
return -1;
pos = 0;
tree_store(array, &pos, root1);
pos = 0;
int res = tree_check(array, &pos, root2);
free(array);
return res;
}
If you are not allowed to convert the trees to arrays, you could:
normalize both trees, then use your simple comparator, but this will modify the trees and is difficult.
implement a stack based iterator and iterate both trees in parallel.
Here is a simple implementation of the latter:
#include <stddef.h>
struct Node {
int data;
struct Node *left;
struct Node *right;
};
size_t max_size(size_t a, size_t b) {
return a < b ? b : a;
}
size_t tree_depth(const struct Node *root) {
return root ? 1 + max_size(tree_depth(root->left), tree_depth(root->right)) : 0;
}
int tree_next(const struct Node **stack, size_t *ppos, int *value) {
size_t pos = *ppos;
if (stack[pos] == NULL) {
if (pos == 0)
return 0; // no more values
pos--;
} else {
while (stack[pos]->left) {
stack[pos + 1] = stack[pos]->left;
pos++;
}
}
*value = stack[pos]->data;
stack[pos] = stack[pos]->right;
*ppos = pos;
return 1;
}
/* compare trees: return 0 if different, 1 if same values, -1 if allocation error */
int isIdentical(const struct Node *root1, const struct Node *root2) {
if (root1 == NULL || root2 == NULL)
return root1 == root2;
size_t depth1 = tree_depth(root1);
size_t depth2 = tree_depth(root2);
const struct Node *stack1[depth1];
const struct Node *stack2[depth2];
size_t pos1 = 0;
size_t pos2 = 0;
stack1[pos1++] = root1;
stack2[pos2++] = root2;
for (;;) {
int value1, value2;
int has1 = tree_next(stack1, &pos1, &value1);
int has2 = tree_next(stack2, &pos2, &value2);
if (!has1 && !has2)
return 1;
if (!has1 || !has2 || value1 != value2)
return 0;
}
}

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.

Insertion into AVL tree only replaces root node

I'm currently working on an assignment where the N most frequent words in a book (.txt) must be printed. The issue that I'm currently facing is that when I add a node to one of my trees, it simply replaces the root node and thus, the tree remains as a single node.
Code snippet which adds words from the file "stopwords.txt" to a tree named stopwords:
Dict stopwords = newDict();
if (!readFile("stopwords.txt"))
{
fprintf(stderr, "Can't open stopwords\n");
exit(EXIT_FAILURE);
}
FILE *fp = fopen("stopwords.txt", "r");
while (fgets(buf, MAXLINE, fp) != NULL)
{
token = strtok(buf, "\n");
DictInsert(stopwords, buf); //the root is replaced here
}
fclose(fp);
The data structures are defined as follows:
typedef struct _DictNode *Link;
typedef struct _DictNode
{
WFreq data;
Link left;
Link right;
int height;
} DictNode;
typedef struct _DictRep *Dict;
struct _DictRep
{
Link root;
};
typedef struct _WFreq {
char *word; // word buffer (dynamically allocated)
int freq; // count of number of occurences
} WFreq;
Code to insert and rebalance tree:
// create new empty Dictionary
Dict newDict(void)
{
Dict d = malloc(sizeof(*d));
if (d == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
d->root = NULL;
return d;
}
// insert new word into Dictionary
// return pointer to the (word,freq) pair for that word
WFreq *DictInsert(Dict d, char *w)
{
d->root = doInsert(d->root, w); //the root is replaced here before doInsert runs
return DictFind(d, w);
}
static int depth(Link n)
{
if (n == NULL)
return 0;
int ldepth = depth(n->left);
int rdepth = depth(n->right);
return 1 + ((ldepth > rdepth) ? ldepth : rdepth);
}
static Link doInsert(Link n, char *w)
{
if (n == NULL)
{
return newNode(w);
}
// insert recursively
int cmp = strcmp(w, n->data.word);
if (cmp < 0)
{
n->left = doInsert(n->left, w);
}
else if (cmp > 0)
{
n->right = doInsert(n->right, w);
}
else
{ // (cmp == 0)
// if time is already in the tree,
// we can return straight away
return n;
}
// insertion done
// correct the height of the current subtree
n->height = 1 + max(height(n->left), height(n->right));
// rebalance the tree
int dL = depth(n->left);
int dR = depth(n->right);
if ((dL - dR) > 1)
{
dL = depth(n->left->left);
dR = depth(n->left->right);
if ((dL - dR) > 0)
{
n = rotateRight(n);
}
else
{
n->left = rotateLeft(n->left);
n = rotateRight(n);
}
}
else if ((dR - dL) > 1)
{
dL = depth(n->right->left);
dR = depth(n->right->right);
if ((dR - dL) > 0)
{
n = rotateLeft(n);
}
else
{
n->right = rotateRight(n->right);
n = rotateLeft(n);
}
}
return n;
}
static Link newNode(char *w)
{
Link n = malloc(sizeof(*n));
if (n == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
n->data.word = w;
n->data.freq = 1;
n->height = 1;
n->left = NULL;
n->right = NULL;
return n;
}
// Rotates the given subtree left and returns the root of the updated
// subtree.
static Link rotateLeft(Link n)
{
if (n == NULL)
return n;
if (n->right == NULL)
return n;
Link rightNode = n->right;
n->right = rightNode->left;
rightNode->left = n;
n->height = max(height(n->left), height(n->right)) + 1;
rightNode->height = max(height(rightNode->right), n->height) + 1;
return rightNode;
}
// Rotates the given subtree right and returns the root of the updated
// subtree.
static Link rotateRight(Link n)
{
if (n == NULL)
return n;
if (n->left == NULL)
return n;
Link leftNode = n->left;
n->left = leftNode->right;
leftNode->right = n;
n->height = max(height(n->left), height(n->right)) + 1;
leftNode->height = max(height(leftNode->right), n->height) + 1;
return leftNode;
}
I believe that most of the code is functional and it is simply the insertion which fails. When I attempted to debug this with gdb, I had discovered that the root node (d->root) was replaced before the recursive insert function (doInsert) was run, causing the program to always return the node n which, as a result, already exists in the tree. For example, if the text file contained the following:
a
b
c
then the program would first insert "a" as stopwords->root, then "b" would replace "a" and become the new stopwords->root, finally "c" would replace "b" as the stopwords->root, resulting in a tree with one node, "c".
There are many inconsistencies in your code.
One mistake is here:
d->root = doInsert(d->root, w);
You reassign unconditionally the root each time when you insert a new node.
You are supposed to return the new node from the function doInsert and to reassign the root only if the new node had become a new root.
But other mistake that you make is that you return from doInsert a local variable n that was not newly allocated but that was initialized to point to the previous root.
Inside doInsert you need to allocate a new node NEW and use a variable x to walk down from the root until you find a place to insert a new allocated node NEW. If x stops at root then you reinitialize the d->root = NEW.
Your function newNode just stores the passed string pointer, so what is pointed at will change when you modify the original string.
To prevent that, you should copy the input string on node insertions.
To archive that,
n->data.word = w;
should be
n->data.word = malloc(strlen(w) + 1);
if (n->data.word == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
strcpy(n->data.word, w);
Add #include <string.h> to use strlen() and strcpy() if it isn't.

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.

BST insertion function causes weird output (C)

I am trying to write a program that takes a newline separated list of strings from a file and one by one inserts them into a BST.
The way I have it now results in the tree having all of the node's values be the value of the last string added to the tree.
For example, if the list being inserted is: b a c e d z, an inorder traversal will print the tree as: z z z z z z.
I've traced through this code a large number of times over and can not see what's causing this, i've hit a complete mental block.
Here is the code:
insert.c:
#include "node.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void insert_node(Node* root, char *nextString) {
Node* freshNode;
freshNode = newNode();
freshNode->Word = nextString;
printf("Root->Word = %s\n",root->Word);
printf("nextString = %s\n",freshNode->Word);
int newLessThanRoot = 0;
if (strcmp(root->Word,freshNode->Word) > 0) {
newLessThanRoot = 1;
}
if (newLessThanRoot) {
if (root->Left == NULL) {
root->Left = freshNode;
}
else {
insert_node(root->Left, freshNode->Word);
}
}
if (!newLessThanRoot) {
if (root->Right == NULL) {
root->Right = freshNode;
}
else {
insert_node(root->Right, freshNode->Word);
}
}
}
void inorder(Node *temp) {
if (temp != NULL) {
inorder(temp->Left);
printf("%s ",temp->Word);
inorder(temp->Right);
}
}
relevant parts of main.c:
char inputString[15];
char *inputStringPtr = &inputString[0];
Node* root;
root = newNode();
fscanf(infile,"%s",inputStringPtr);
root->Word = inputString;
printf("Root's word: %s\n",root->Word);
while (fscanf(infile,"%s",inputStringPtr) == 1) {
insert_node(root,inputStringPtr);
printf("%s\n",inputString);
}
int numberOfStrings = num_of_strings(root);
int heightOfBST = height_of_tree(root);
int numberOfLeaves = num_of_leaves(root);
inorder(root);

Resources