convert array to binary tree with recursive strategy - c

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];
}

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;
}
}

How would you write this code in C using arrays instead

void storeBSTNodes(Node* root, vector<Node*> &nodes)
{
if (root == NULL)
return;
storeBSTNodes(root->left, nodes);
nodes.push_back(root);
storeBSTNodes(root->right, nodes);
}
How would you write this code in C (it's in C++ format currently) using an array? This is what I've got so far, but I'm confused about the part regarding nodes.push_back(root); and root->left, nodes
void storeBSTNodes(Node* root, int arr[])
{
if (root == NULL)
return;
storeBSTNodes(root->left, arr);
?
storeBSTNodes(root->right, arr);
}
Code from: https://www.geeksforgeeks.org/convert-normal-bst-balanced-bst/
The key is realloc.
But you'll soon realize that Node arr[] would have to be changed since you would need to know the existing number of elements in the array, and you would need to return the new number of elements in the array and the updated buffer pointer. Using a vector-like "class" or library would help.
Given the (untested) library below, you could use the following:
void storeBSTNodes(Node* root, Vector* nodes)
{
if (root == NULL)
return;
storeBSTNodes(root->left, nodes);
Vector_push(nodes, root); // Ignores failures.
storeBSTNodes(root->right, nodes);
}
Vector.h:
#ifndef VECTOR_H
#define VECTOR_H
#include <stdlib.h>
// A fixed-size circular buffer.
typedef struct {
size_t size;
size_t used;
void** buf;
} Vector;
// Returns NULL and sets errno on error.
// Free the vector with Vector_delete when done.
Vector* Vector_new(void);
// Returns 0 and sets errno on error.
// Destroy the vector with Vector_destroy when done.
int Vector_init(Vector* v);
// Inverse of Vector_new.
// Only call when the vector is empty.
void Vector_delete(Vector* v);
// Inverse of Vector_init.
// Only call when the vector is empty.
void Vector_destroy(Vector* v);
int Vector_is_empty(Vector* v);
// Appends an element to the vector.
// Returns 0 and sets errno on error.
int Vector_push(Vector* v, void* ele);
// Removes the last element of the vector and returns it.
// Note that this also NULL if empty.
void* Vector_pop(Vector* v);
#endif
Vector.c:
#include <assert.h>
#include <stdlib.h>
#include "Vector.h"
Vector* Vector_new(void) {
Vector v = malloc(sizeof(Vector));
if (v == NULL)
goto Error1;
if (!Vector_init(v))
goto Error2;
return v;
Error2:
free(v);
Error1:
return NULL;
}
int Vector_init(Vector* v) {
v->size = 0;
v->used = 0;
v->buf = NULL;
return 1;
}
void Vector_delete(Vector* v) {
Vector_destroy(v);
free(v);
}
void Vector_destroy(Vector* v) {
assert(v->used == 0);
free(v->buf);
}
int Vector_is_empty(Vector* v) {
return v->used == 0;
}
int Vector_push(Vector* v, void* ele) {
if (v->used == v->size) {
size_t new_size = v->size;
new_size = new_size ? new_size * 2 : 4;
void* new_buf = realloc(v->buf, new_size * sizeof(void*));
if (new_buf == NULL)
return 0;
v->size = new_size;
v->buf = new_buf;
}
v->buf[ (v->used)++ ] = ele;
return 1;
}
void* Vector_pop(Vector* v) {
if (v->used == 0)
return NULL;
return v->buf[ --(v->used) ];
}
Add other "methods" as needed.
Allocation of temporary storage would be more efficient if you could get the number of elements in the tree efficiently, for example by maintaining a counter. Failing that, a recursive function could be used to count the elements:
size_t CountBSTElements(Node *root) {
if (root)
return 1 + CountBSTElements(root->left) + CountBSTElements(root->right);
else
return 0;
}
Once the total number of elements is known, the following function can be called to allocate an array filled with an in-order traversal of the tree:
/*
* Allocates and fills array of node pointers from BST tree.
* root is the root node and n is the total number of elements in the tree.
*/
Node **GetInOrderBSTNodes(Node *root, size_t n) {
Node **nodes = malloc(n * sizeof(*nodes));
size_t front = 0;
size_t back = n;
if (!nodes)
return NULL;
while (front < back) {
if (root) {
nodes[--back] = root;
root = root->left;
} else {
root = nodes[back++];
nodes[front++] = root;
root = root->right;
}
}
return nodes;
}
Demonstration follows. The temporary storage needs to be freed once it has been used to build the balanced tree.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node Node;
struct Node {
int data;
Node *left;
Node *right;
};
/*
* Allocates and fills array of node pointers from BST tree.
* root is the root node and n is the total number of elements in the tree.
*/
Node **GetInOrderBSTNodes(Node *root, size_t n) {
Node **nodes = malloc(n * sizeof(*nodes));
size_t front = 0;
size_t back = n;
if (!nodes)
return NULL;
while (front < back) {
if (root) {
nodes[--back] = root;
root = root->left;
} else {
root = nodes[back++];
nodes[front++] = root;
root = root->right;
}
}
return nodes;
}
size_t CountBSTElements(Node *root) {
if (root)
return 1 + CountBSTElements(root->left) + CountBSTElements(root->right);
else
return 0;
}
/*
* N.B. The usage of the end index is slightly different in this version of
* buildTreeUtil() compared to the linked source:
* https://www.geeksforgeeks.org/convert-normal-bst-balanced-bst/
*
* In this version, end is one past the last index.
* I did it this way to keep the indices unsigned.
*/
/*
* Build BST from array of node pointers.
* nodes is the array of node pointers.
* start is start index in the array.
* end is one past the end index in the array.
*
* Sorry, it is recursive. :-)
*/
Node *BuildTreeUtil(Node **nodes, size_t start, size_t end)
{
Node *root;
size_t mid;
if (start >= end)
return NULL;
mid = (start + end - 1) / 2;
root = nodes[mid];
root->left = BuildTreeUtil(nodes, start, mid);
root->right = BuildTreeUtil(nodes, mid + 1, end);
return root;
}
Node *BuildTree(Node *root, size_t nelems) {
Node **nodes = GetInOrderBSTNodes(root, nelems);
if (nodes) {
/* Build BST from in-order node pointers. */
root = BuildTreeUtil(nodes, 0, nelems);
/* Free temporary storage. */
free(nodes);
} /* else leave it unbalanced */
return root;
}
/* Utility function to create a new node */
/* Borrowed from linked source. */
Node *NewNode(int data) {
Node *node = malloc(sizeof(*node));
if (node) {
node->data = data;
node->left = NULL;
node->right = NULL;
}
return (node);
}
/* Print in-order traversal of BST. */
/* Borrowed from linked source, but renamed. */
void PrintPreOrder(Node* node)
{
if (node == NULL)
return;
printf("%d ", node->data);
PrintPreOrder(node->left);
PrintPreOrder(node->right);
}
int main(void) {
Node *root;
size_t count;
/*
* Construct unbalanced BST:
*
* 4
* / \
* 3 5
* / \
* 2 6
* / \
* 1 7
*/
root = NewNode(4);
root->left = NewNode(3);
root->left->left = NewNode(2);
root->left->left->left = NewNode(1);
root->right = NewNode(5);
root->right->right = NewNode(6);
root->right->right->right = NewNode(7);
printf("Pre-order traversal of unbalanced BST is:\n");
PrintPreOrder(root);
printf("\n");
/* Get number of nodes. */
#if 0
count = 7; /* efficient :-) */
#else
count = CountBSTElements(root);
#endif
/*
* Build balanced BST:
*
* 4
* / \
* 2 6
* / \ / \
* 1 3 5 7
*/
root = BuildTree(root, count);
printf("Pre-order traversal of balanced BST is:\n");
PrintPreOrder(root);
printf("\n");
return 0;
}

preorder array from binary tree

I cannot seem to get this function to work. It is supposed to find the preorder of a given binary tree, and put those integers into an array. This function was adapted from a similar print preorder traversal that can be found on geeksforgeeks.
//node struct
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;
node *create_node(int data)
{
node *n = calloc(1, sizeof(node));
n->data = data;
return n;
}
unsigned int node_count_recursive(node *root)
{
unsigned int count = 1;
if (root->left != NULL)
count += node_count_recursive(root->left);
if (root->right != NULL)
count += node_count_recursive(root->right);
return count;
}
unsigned int node_count(node *root)
{
unsigned int count = 0;
if (root != NULL)
count = node_count_recursive(root);
return count;
}
// helper function that takes in the root, a dynamically allocated array, and count variable
// initialized to 0
// problem I believe is in this function
unsigned int preorder_helper(node *root, int *array, unsigned int count)
{
if (root == NULL)
return 0;
// This does not work
array[count++] = root->data;
count = preorder_helper(root->left, array, count);
count = preorder_helper(root->right, array, count);
return count;
}
// creates dynamically allocated array for helper function.
int *preorder_array(node *root)
{
int *array = malloc(sizeof(node) * node_count(root));
preorder_helper(root, array, 0);
return array;
}
// creates tree
int main(void)
{
node *root1;
int *preArray;
root1 = create_node(23);
root1->left = create_node(12);
root1->left->left = create_node(5);
root1->left->right = create_node(18);
root1->right = create_node(71);
root1->right->right = create_node(56);
// points preArray pointer to function
preArray = preorder_array(root1);
// loops through each integer in array
for (int i = 0; i < node_count(root1); i++) //node_count counts nodes in tree
printf("%d ", preArray[i]);
return 0;
}
The preorder_helper function seems to get the first 2 or 3 correct preorder values, but then the rest of the array is 0. The output of this code is this:
56 12 5 0 0 0
Any help is greatly appreciated, thanks.

C - recursion not working in a Binary Search Tree

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);
}

Structuring leafs in a hierarchical tree

This code fills a tree with values based on their depths. But when traversing the tree, I cannot manage to determine the actual number of children without iterating over the parent node. This is necessary because the subleafs are stored in in the node underneath the current one. Which conceptual changes are necessary to store the leafs directly within the current node?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef NULL
#define NULL ((void *) 0)
#endif
// ----
typedef struct _Tree_Node {
// data ptr
void *p;
// number of nodes
int cnt;
struct _Tree_Node **nodes;
// parent nodes
struct _Tree_Node *parent;
} Tree_Node;
typedef struct {
Tree_Node root;
} Tree;
void Tree_Init(Tree *this) {
this->root.p = NULL;
this->root.cnt = 0;
this->root.nodes = NULL;
this->root.parent = NULL;
}
Tree_Node* Tree_AddNode(Tree_Node *node) {
if (node->cnt == 0) {
node->nodes = malloc(sizeof(Tree_Node *));
} else {
node->nodes = realloc(
node->nodes,
(node->cnt + 1) * sizeof(Tree_Node *)
);
}
Tree_Node *res
= node->nodes[node->cnt]
= malloc(sizeof(Tree_Node));
res->p = NULL;
res->cnt = 0;
res->nodes = NULL;
res->parent = node;
node->cnt++;
return res;
}
// ----
void handleNode(Tree_Node *node, int depth) {
int j = depth;
printf("\n");
while (j--) {
printf(" ");
}
printf("depth=%d ", depth);
if (node->p == NULL) {
goto out;
}
int cnt = 0;
for (int i = 0; i < node->parent->cnt - 1; i++) {
if (node->parent->nodes[i] == node) {
cnt = node->parent->nodes[i + 1]->cnt;
}
}
printf("value=%s cnt=%i", node->p, cnt);
out:
for (int i = 0; i < node->cnt; i++) {
handleNode(node->nodes[i], depth + 1);
}
}
Tree tree;
int curdepth;
Tree_Node *curnode;
void add(int depth, char *s) {
printf("%s: depth (%d) > curdepth (%d): %d\n", s, depth, curdepth, depth > curdepth);
if (depth > curdepth) {
curnode = Tree_AddNode(curnode);
Tree_Node *node = Tree_AddNode(curnode);
node->p = malloc(strlen(s) + 1);
memcpy(node->p, s, strlen(s) + 1);
curdepth++;
} else {
while (curdepth - depth > 0) {
if (curnode->parent == NULL) {
printf("Illegal nesting\n");
return;
}
curnode = curnode->parent;
curdepth--;
}
Tree_Node *node = Tree_AddNode(curnode);
node->p = malloc(strlen(s) + 1);
memcpy(node->p, s, strlen(s) + 1);
}
}
void main(void) {
Tree_Init(&tree);
curnode = &tree.root;
curdepth = 0;
add(0, "1");
add(1, "1.1");
add(2, "1.1.1");
add(3, "1.1.1.1");
add(4, "1.1.1.1.1");
add(4, "1.1.1.1.2");
add(4, "1.1.1.1.3");
add(4, "1.1.1.1.4");
add(2, "1.1.2");
add(0, "2");
handleNode(&tree.root, 0);
}
I see two problems in you program
1) When you "realloc" the node list, you actually move in memory the node objects, so the parent pointer in their children must me updated as well. I suggest you to transform the array of nodes into an array of pointers to nodes, so you can realloc it without correcting pointers.
2) You forgot to terminate strings:
node->p = malloc(strlen(s));
memcpy(node->p, s, strlen(s));
should be:
node->p = malloc(strlen(s)+1);
memcpy(node->p, s, strlen(s)+1);
or also simply
node->p = strdup(s);
Maybe there are other issues, but I strongly suggest to correct these ones first.
I hope it may help you
Regards
If your structure is truly a tree, then the following pseudo code for recursively counting nodes may help:
def total_number_of_leaf_nodes(node):
if node does not have children:
return 1
else:
sum = 0
for each child of node:
sum += total_number_of_leaf_nodes(child)
return sum
If it is at all possible for you to use C++, then I would strongly advise it. Being able to use an std::vector or std::list to store your child nodes and being able to make the data element have a template type would greatly simplify the complexity of your code.

Resources