I'm creating a binary tree in C in which I use indexes as in a binary search tree. I'm having trouble with a function that finds a node.
My code for the tree is in a separate file and it's the following:
struct node {
struct node *left;
struct node *right;
int index;
void *data;
};
struct node * init_mt()
{
struct node *root = malloc(sizeof(struct node));
root->index = -1;
root->data = NULL;
root->left = root->right = NULL;
return root;
}
void create_mt(struct node *mt, int h, int i)
{
if (h == 0) // end of tree reached
{
mt->index = 0;
mt->left = mt->right = NULL;
return;
}
else
{
mt->index = i;
int l = i-pow(2,h-1);
int r = i+pow(2,h-1);
mt->left = malloc(sizeof(struct node));
mt->right = malloc(sizeof(struct node));
create_mt(mt->left,h-1,l);
create_mt(mt->right,h-1,r);
}
}
struct node * get_node_mt(struct node *mt, int p, int h)
{
if (h == -1) // end of tree reached
{
return NULL;
}
else
{
if (mt->index == p)
{
printf("Found %p\n", mt);
return mt;
}
else if (mt->index > p)
{
get_node_mt(mt->left,p,h-1);
}
else
{
get_node_mt(mt->right,p,h-1);
}
}
}
When I run my main like this (root->left->left is the node index #2):
struct node *root = NULL;
root = init_mt();
create_mt(root,3,8); // root index == 8
printf("%d %p\n", root->left->left->index,root->left->left);
struct node *find;
find = get_node_mt(root,2,3);
printf("%p\n", find);
I get the following output:
2 0x7ffd1dd011a0
Found 0x7ffd1dd011a0
0x0
I don't understand why I get the right pointer both when priting directly using root->left->left and inside the function get_node_mt() but not when I print the pointer I've returned. What am I doing wrong?
The get_node_mt() function calls itself in two places. Neither of these two places return a value.
struct node * get_node_mt(struct node *mt, int p, int h)
{
if (h == -1) // end of tree reached
return NULL;
else if (mt->index == p)
return mt;
else if (mt->index > p)
get_node_mt(mt->left,p,h-1);
else
get_node_mt(mt->right,p,h-1);
}
I reformatted the code a bit and removed a lot of braces. The compiler should've warned about this problem, IMHO.
Related
I am making a program to test out binary search trees in the c language. I want to balance it using a less good array method. I dynamically allocate the array based on the number of nodes in the BST and send the array off to another function that does the search and should place the elements in the array. However, when I run the program just the first element (the root of the tree) shows up in the array with every other iteration nothing happens. I am not sure on what is wrong.
Below is a MCVE for the part of the program that does not work. The first code blocks are simply to make and fill a BST. And it's the sorterToArray function that does not work.
In the recursive function sorterToArray I have tried to send the next place in the array but that does not work since it "is a nullptr".
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct treeNode
{
int data;
struct treeNode* left;
struct treeNode* right;
};
typedef struct treeNode* BSTree;
void insertSorted(BSTree* tree, int data);
void sorterToArray(struct treeNode* temp, int* pArray, int i);
int counter(int i, const BSTree tree);
void goLeftAndRight(struct treeNode* newNode, struct treeNode* tempTree, const int data);
void balanceTree(BSTree* tree);
static int* writeSortedToArray(const BSTree tree);
int main(void) {
BSTree tree = NULL;
insertSorted(&tree, 10);
for (int i = 0; i < 9; i++)
insertSorted(&tree, i + 20);
balanceTree(&tree);
}
static struct treeNode* createNode(int data)
{
//Creates the new node for the tree
struct treeNode* newNode;
//Allocates memory for the new node
newNode = calloc(1, 1 + sizeof(struct treeNode*));
//Tests the new memory
assert(newNode != NULL);
//Assigns data to the new node
newNode->data = data;
//Sets the left and right pointers to NULL so that other functions know where the ends are
newNode->left = NULL;
newNode->right = NULL;
return newNode; //Returns the new node
}
void insertSorted(BSTree* tree, int data)
{
//Creates a new temp struct
struct treeNode* newNode = createNode(data);
struct treeNode* tempTree = (*tree);
//If the tree is empty then the data will be at the root
if (tempTree == NULL) {
(*tree) = newNode;
}
//If the tree is not empty the function will call the help function in order to find the right node.
else {
goLeftAndRight(newNode, tempTree, data);
}
}
void goLeftAndRight(struct treeNode* newNode, struct treeNode* tempTree, const int data) {
if (data < tempTree->data && tempTree->left == NULL) {
tempTree->left = newNode;
return;
}
else if (data > tempTree->data && tempTree->right == NULL) {
tempTree->right = newNode;
return;
}
if (data < tempTree->data && data != tempTree->data) {
goLeftAndRight(newNode, tempTree->left, data);
}
else if (data > tempTree->data && data != tempTree->data) {
goLeftAndRight(newNode, tempTree->right, data);
}
}
int counter(int i, const BSTree tree) {
if (tree->left != NULL)
i = 1 + counter(i, tree->left);
if (tree->right != NULL)
i = 1 + counter(i, tree->right);
return i;
}
void balanceTree(BSTree* tree) {
int* sortedArray = writeSortedToArray((*tree));
}
//Code blocks writeSortedToArray ans SorterToArray are the ones causing the problems.
static int* writeSortedToArray(const BSTree tree)
{
struct treeNode* temp = tree;
int i = 0, number = 1 + counter(i, tree);
int* pArray = calloc(number, sizeof(int*));
assert(pArray != NULL);
sorterToArray(temp, pArray, i);
return pArray;
}
//Function where the problem is most likely located.
void sorterToArray(struct treeNode* temp, int* pArray, int i) {
if (temp->left != NULL)
sorterToArray(temp->left, pArray, i);
pArray[i] = temp->data;
i = i + 1;
if (temp->right != NULL)
sorterToArray(temp->right, pArray, i);
}
The problem is indeed in the function you point to. The variable i is local to the function's execution context, and each recursive execution has thus its "own" i. The i = i + 1 only affects one local instance, while other versions of i don't change. That means that none of those i variables will ever get the value 2 or more.
Otherwise put: i is passed by value to the recursive function call.
The solution is to have the function return the updated value of i to the caller:
int sorterToArray(struct treeNode* temp, int* pArray, int i) {
if (temp->left != NULL)
i = sorterToArray(temp->left, pArray, i);
pArray[i] = temp->data;
i = i + 1;
if (temp->right != NULL)
i = sorterToArray(temp->right, pArray, i);
return i;
}
void
LInsert (LIST * l, int x, int pos)
{
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc (sizeof (struct Node));
new->val = x;
if (pos == 0)
{ // insert to start
new->next = l->head;
l->head = new;
}
else
{
// insert after p
p = l->head;
while (p != NULL && pos > 1)
{
p = p->next;
--pos;
}
if (p == NULL)
{
printf ("LInsert: Position not possible\n");
return;
}
new->next = p->next;
p->next = new;
}
l->size++;
}
This is a function of inserting a node to a linked list. I don't understand a few lines in this program.
In the first if condition there is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?. It makes the linked list a circular linked list but this is just a simple linked list.
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Hope the indentation is correct I always get people yelling at me for wrong indentation
Here is the complete code which includes struc declaration and stuff
#include <stdio.h>
#include <stdlib.h>
struct Node {
int val;
struct Node *next;
};
struct List {
struct Node *head;
int size;
};
// LIST is new name for "struct List"
typedef struct List LIST;
void LInit(LIST *l){ // Initialize list to empty
l->head = NULL; // pointer to first node
l->size = 0; // number of nodes
}
int LGetPos(LIST *l, int x) {
struct Node *p;
int i=0;
// go through all nodes
for (p=l->head; p!=NULL; p=p->next)
if (p->val == x) return i; // found
else i++; // next
return -1; // not found in the list
}
int LGetAt(LIST *l, int pos) {
struct Node *p=l->head;
int i;
// go to position
for(i=0; p!=NULL && i<pos; i++) p = p->next;
if(p) return p->val; // if exists, return it
else { printf("LDelete: Position not exist\n"); return -99; }
}
void LInsert(LIST *l, int x, int pos) {
struct Node *new, *p; // p: previous node
// create a new node
new = (struct Node *) malloc(sizeof(struct Node));
new->val = x;
if(pos==0) { // insert to start
new->next = l->head;
l->head = new;
}
else { // insert after p
p = l->head;
while(p!=NULL && pos>1) { p = p->next; --pos; }
if(p==NULL) { printf("LInsert: Position not possible\n"); return; }
new->next = p->next;
p->next = new;
}
l->size++;
}
void LDelete(LIST *l, int pos) {
struct Node *p, *d; // p: previous
if(l->head == NULL) return;
if(pos==0) { // delete first node
d = l->head;
l->head = d->next;
}
else { // delete after p
p = l->head;
while(pos>1 && p) { p = p->next; --pos; }
if(p==NULL) { printf("LDelete: Position not exist\n"); return; }
d = p->next;
p->next = p->next->next;
}
l->size--;
free(d);
}
int LIsEmpty(LIST * l){
return (l->size == 0);
}
int LSize(LIST * l){
return (l->size);
}
void LDisplay(LIST *l) {
struct Node *p;
printf("List: ");
for(p=l->head; p!=NULL; p=p->next)
printf("--> %d ", p->val);
printf("\n");
}
int LHeadOf(LIST *l) {
if (!LIsEmpty(l)) return l->head->val;
else {
printf("LHeadOf: Linked list empty\n");
return -99;
}
}
int main() {
LIST list;
LInit(&list);
LDisplay(&list);
LInsert(&list, 3, 0);
LInsert(&list, 4, 0);
LInsert(&list, 5, 2);
LDisplay(&list);
printf("Value at 1: %d\n", LGetAt(&list, 1));
printf("Location of 4: %d\n", LGetPos(&list, 4));
LDelete(&list, 1);
LDisplay(&list);
return 0;
}
I don't understand a few lines in this program
Okay - let's take a look of those lines...
here is a line new->next=l->head; From my thinking it means that in the "next" part of the new node it will store the what's in the head node(an address probably), but why?
That line is used to insert the new element in front of the current head element. So
new->next=l->head; // Make the new element point to current head
l->head = new; // Change head to point to the new element as it is now the front element
Also near the end new->next=p->next what does this mean.It makes the linked list circular again.
Well, it doesn't make the list circular. It simply insert the new element somewhere in the middle of the list.
new->next = p->next; // Make new point to the element after p
p->next = new; // Make p point to new
// In this way new has between inserted after p and
// before the element that folloed p
I am getting a segmentation fault when trying to print the nodes in my binary tree. It looks to be an issue with the third node. I have searched google and stack overflow for hours but I can not understand what the problem is. I am trying to teach myself data structures in C and am very much a novice so I may be doing something in a frowned upon way.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *left;
struct node *right;
} Node;
typedef struct
{
Node *root;
} BinarySearchTree;
void printInOrder(Node *);
void addNode(Node *, Node *);
int main (void)
{
BinarySearchTree tree;
BinarySearchTree *tree_ptr = &tree;
Node n1, n2, n3;
n1.data = 1;
n2.data = 2;
n3.data = 3;
Node *n1_ptr = &n1;
Node *n2_ptr = &n2;
Node *n3_ptr = &n3;
tree_ptr->root = n1_ptr;
addNode(tree_ptr->root, n2_ptr);
addNode(tree_ptr->root, n3_ptr);
printInOrder(tree_ptr->root);
}
void printInOrder(Node *root)
{
if (root == NULL)
{
return;
} else
{
printInOrder(root->left);
printf("%i\n", root->data);
printInOrder(root->right);
}
}
void addNode(Node *root, Node *node)
{
if (node->data < root->data)
{
if (root->left == NULL)
{
root->left = node;
} else
{
addNode(root->left, node);
}
}
else if (node->data > root->data)
{
if (root->right == NULL)
{
root->right = node;
} else
{
addNode(root->right, node);
}
}
}
output:
1
2
Segmentation fault: 11
There doesn't seem to be an issue with any but the third node. If I comment out the line that adds the second node I get the same error (with only 1 being printed, obviously).
Your initialization is incomplete
n1.data = 1;
n2.data = 2;
n3.data = 3;
should also set the pointers
n1.data = 1;
n1.left = NULL;
n1.right = NULL;
n2.data = 2;
n2.left = NULL;
n2.right = NULL;
n3.data = 3;
n3.left = NULL;
n3.right = NULL;
Problem is occurring because you are not initializing all the member of structure Node type variable.
I would suggest, you should write a function to initialize the Node type variable, like this:
void init_node(Node * nodeptr, int data)
{
nodeptr->data = data;
nodeptr->left = NULL;
nodeptr->right = NULL;
}
and in your main() (or from where ever you want to initialize) you can simply do:
init_node(&n1, 1);
init_node(&n2, 2);
init_node(&n3, 3);
With this, you will never miss assigning NULL to left and right pointer during initialization of Node type variable and chances of the error occurring because of it will be reduced to a greater extent.
I am working with the following code I found on here to begin my project that involves a tree data structure.
struct node{
int ID;
struct node* next;
struct node* child;
};
typedef struct node node;
node* new_node(int);
node* add_sibling(node*, int);
node* add_child(node*, int);
int main()
{
int i;
node *root = new_node(0);
for (i = 1; i <= 3; i++)
add_child(root, i);
}
node * new_node(int ID)
{
node* new_node =(node*) malloc(sizeof(node));
if (new_node) {
new_node->next = NULL;
new_node->child = NULL;
new_node->ID = ID;
}
return new_node;
}
node* add_sibling(node* n, int ID)
{
if (n == NULL)
return NULL;
while (n->next)
n = n->next;
return (n->next = new_node(ID));
}
node* add_child(node* n, int ID)
{
if (n == NULL)
return NULL;
if (n->child)
return add_sibling(n->child, ID);
else
return (n->child = new_node(ID));
}
I am a beginner with C/C++ and programming in general. I think I understand everything about the code except for the add_child function. The function seems to return a pointer to a node, but when it is called in main, it seems to be called as though it were a void function. I would have thought to call the function this way
*root = add_child(root,i);
like how new_node is called, or to write add_child as a void function, but both of these modifications results in errors (not to mention the implementation in the code I found does work). What am I missing?
This function rewritten will look like following.
node* add_child(node* n, int ID)
{
// For null pointer return null
if (n == NULL)
{
return NULL;
}
// If element has child add a sibling to that child
if (n->child)
{
node* sibling_for_child = add_sibling(n->child, ID);
return sibling_for_child;
}
else
{
// Otherwise just add element as a child
node* child_node = new_node(ID);
n->child = child_node;
return child_node;
}
}
The result of assignment is an assigned value(*) like in this chaining assignment:
int a, b;
a = b = 3;
which is actually:
a = (b = 3);
or
b = 3;
a = b;
I am trying to see if tree A is the preorder traversal of tree B and to do so, I created two trees which during a transversal were supposed to save the values. However, after hours of debugging I found out that the trees values were ALWAYS 0. I am confused as to why the trees values are 0. I've done a multitude of print statements (some of which I've left in the code posted below) and I just cannot seem to pinpoint why this is happening. Can someone please nudge me in the correct direction? I thought maybe the function was deleting variables as it exited and in effort to get to the bottom of the issue I had the preorder function return the tree ( as seen below), however, the output is ALWAYS 0 for the tree.
Code:
typedef struct node
{
// Each node holds a single integer.
int data;
// Pointers to the node's left and right children.
struct node *left, *right;
} node;
int tree_diff(node *a, node *b)
{
if (a == NULL && b == NULL)
return 0;
else if (a == NULL || b == NULL)
return 1;
else if (a->data != b->data)
return 1;
printf("A %d , B %d", a->data, b->data);
return tree_diff(a->left, b->left) || tree_diff(a->right, b->right);
}
node *preorder_recursive(node *root, node *A)
{
if (root == NULL)
return A;
printf("root %d ", root->data);
A = root;
printf("= data %d\n", A->data);
preorder_recursive(root->left, A->left);
preorder_recursive(root->right, A->right);
}
void postorder_recursive(node *root, node *B)
{
if (root == NULL)
return;
B = root;
postorder_recursive(root->left, B->left);
postorder_recursive(root->right, B->right);
printf("root %d ", root->data);
printf("= data %d\n", B->data);
}
int kindredSpirits(node *a, node *b)
{
// Get the preorder of a
node *A = malloc(sizeof(node));
A = preorder_recursive(a, A);
// Get the postorder of b
printf("\n\n");
node *B = malloc(sizeof(node));
postorder_recursive(b, B);
if(tree_diff(A,B) == 1)
return 0;
else
return 1;
}
The test case:
#include <stdio.h>
#include <stdlib.h>
#include "KindredSpirits.h"
node *create_node(int data)
{
node *n = malloc(sizeof(node));
n->data = data;
n->left = n->right = NULL;
return n;
}
node *forest_fire(node *root)
{
if (root == NULL)
return NULL;
forest_fire(root->left);
forest_fire(root->right);
free(root);
}
int main(void)
{
node *root;
root = create_node(23);
root->left = create_node(12);
root->left->left = create_node(5);
root->left->right = create_node(18);
root->right = create_node(71);
root->right->right = create_node(56);
printf("%s\n", !kindredSpirits(root, root) ? "Success!" : "fail whale :(");
forest_fire(root);
return 0;
}
Here's a code fragment that should get you started:
typedef struct node {
// Each node holds a single integer.
int data;
// Pointers to the node's left and right children.
struct node *left,
struct node *right;
} node;
typedef struct list {
int lst_max; // maximum number of allocated cells
int lst_cur; // current number of filled cells
int *lst_base; // traversal list
} list;
list list_a = { 0, 0, NULL };
list list_b = { 0, 0, NULL };
void
list_append(list *lst,int data)
{
int newidx;
newidx = lst->lst_cur;
if (newidx >= lst->lst_max) {
lst->lst_max += 100;
lst->lst_base = realloc(lst->lst_base,sizeof(int) * lst->lst_max);
if (lst->lst_base == NULL) {
printf("list_append: malloc error\n");
exit(1);
}
}
lst->lst_base[newidx] = data;
lst->lst_cur = newidx + 1;
}
void
preorder_recursive(node *root,list *lst)
{
if (root == NULL)
return;
list_append(lst,root->data);
preorder_recursive(root->left,lst);
preorder_recursive(root->right,lst);
}
void
postorder_recursive(node *root,list *lst)
{
if (root == NULL)
return;
postorder_recursive(root->left,lst);
postorder_recursive(root->right,lst);
list_append(lst,root->data);
}
int
main(void)
{
preorder_recursive(a,&list_a);
postorder_recursive(b,&list_b);
// compare list_a and list_b ...
return 0;
}
I'm trying to write a function that figures out if tree a's preorder is equal to tree b's postorder without altering a or b.
I use arrays to save the traversals and then compare the value of the two arrays.
#define MAX_TREE_SIZE 100
void preorder_recursive(node *root, int* arr, int *len) {
if (root != NULL){
arr[(*len)++] = root->data;
preorder_recursive(root->left, arr, len);
preorder_recursive(root->right, arr, len);
}
}
void postorder_recursive(node *root, int *arr, int *len) {
if (root != NULL){
postorder_recursive(root->left, arr, len);
postorder_recursive(root->right, arr, len);
arr[(*len)++] = root->data;
}
}
int kindredSpirits(node *a, node *b){
// Get the preorder of a
int *arr1 = malloc(MAX_TREE_SIZE * sizeof(int));
int len1 = 0;
preorder_recursive(a, arr1, &len1);
// Get the postorder of b
int *arr2 = malloc(MAX_TREE_SIZE * sizeof(int));
int len2 = 0;
postorder_recursive(b, arr2, &len2);
int ret = 0; // 2 traversals are equal
if (len1 != len2) {
ret = 1;
} else {
for (int i = 0; i < len1; i++){
if (arr1[i] != arr2[i]){
ret = 1;
break;
}
}
}
free(arr1);
free(arr2);
return ret;
}