Recursive tree traversal - c

struct Node {
char*label;
struct Node *children;
};
I am trying to traverse a tree and print the value/label of the nodes(as defined above) based on the current depth.
Output:
Output
My code:
void recurse_helper(struct Node **root, int level, int max_level){
if (level > max_level){
return;
}
struct Node* r = *root;
if(r->children == NULL){
}
else{
struct Node *current = r->children;
}
void traverse_and_print(struct Node* root, max_dep){
recurse_helper(&root, 0,max_dep);
}
My code doesn't seem to work properly. Does anyone have a better recursive solution or could someone please recommend how to change my current implementation?

This seemed to do the trick.
void printTree(Node *root, int level) {
if (root == NULL)
return;
for (int i = 0; i < level; i++) {
printf(" ");
}
printf("%s\n", root->data);
for (Node *child = root->children; child != NULL; child = child->next_sib) {
printTree(child, level + 1);
}
}
It doesn't implement max_level, I'll leave that to you to ad.

One obvious problem seems to be....you are calling recurse_helper() with max_level = 0 :
recurse_helper(&root, 0,0);
which you stated meant print out the entire tree, however this line in recurse_helper():
if (level > max_level){
return;
}
will cause the recursion to stop after the first iteration. The second call to recurse_helper() will pass in 1 for level and 0 for max_level:
recurse_helper(&((r->children)->children), level+1, max_level);
So you definitely need to specifically account for max_level = 0.
You didn't describe the erroneous behavior you were seeing, but this certainly seems like an issue.

Related

Recursive Binary Tree Insert in C

So I am trying to learn how to create a binary tree in C so far I have got this.
void addRecordsToTree(struct date *in, struct date *root) {
if (root == NULL) {
root = malloc(sizeof(struct date));
root = in;
return;
} else {
//Right side of tree processing
if (compareTwoRecords(in, root) >= 0) {
addRecordsToTree(in, root->right);
return;
} else {
root->right = in;
return;
}
//Left side of tree processing.
if (compareTwoRecords(in, root) < 0) {
addRecordsToTree(in, root->left);
return;
} else {
root->left = in;
return;
}
}
}
int main() {
loadFiles();
struct date treeRoot;
struct date *old = malloc(sizeof(struct date));
old = loadContentsIntoHeap(files[file2014]);
addRecordsToTree(&old[0], &treeRoot);
addRecordsToTree(&old[1], &treeRoot);
addRecordsToTree(&old[2], &treeRoot);
addRecordsToTree(&old[3], &treeRoot);
addRecordsToTree(&old[4], &treeRoot);
addRecordsToTree(&old[5], &treeRoot);
printRecord(7, old);
return 0;
}
The problem is when I check the state of the program in a debugger there is just jumbled up data. I think it could be a type problem somewhere, I find pointers are bit of a mind boggling concept. Im not sure if I have used them right. So here is a screen shot of the debugger.
As you can see at the bottom struct called 'old' is the data I am trying to make the tree out of and treeRoot is where I am trying to place it but I can't understand why I get these garbage values.
Also what is up with the memory address of left and right? am I not creating them correctly.
Another observation I made is when I watch my code in the debugger it seems that root is never == NULL and never gets set, why?
You just did the following:
int x = 2;
int y = x;
y = 5;
Is the second line here necessary or the third one. It is a totally illogical program if you did this. You just did the same thing with a pointer instead of integer. You firstly had a pointer to the base address of dynamic memory then you just overwrote it by initializing it the second time.
And, the iterative approach is far better in comparison to the recursive one. I share the code for inserting a node in a binary tree both recursively and iteratively:
void insert(struct node *temp, struct node **root)
{
while (*root != NULL)
root = (*root)->element < temp->element ? &(*root)->left : &(*root)->right;
*root = temp;
}
#if 0
/* Recursive approach */
void insert(struct node *temp, struct node **root)
{
if(*root == NULL)
*root = temp;
else if ((*root)->element < temp->element)
insert(temp, &(*root)->left);
else
insert(temp, &(*root)->right);
}
#endif
void create_node(int x, struct node **root)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (temp == NULL)
printf("Unable to allocate memory. Free some space.\n");
else
{
temp->left = NULL;
temp->right = NULL;
temp->element = x;
insert(temp, root);
}
}
int main()
{
struct node *root = NULL;
create_node(1, &root);
create_node(2, &root);
create_node(3, &root);
return 0;
}
I saw an additional Problem in your "addRecordsToTree"-function:
the IF-block of the
"//Right side of tree processing"
will allways return from the function. regardless wether the "IF"-Expression is true or false.
So your left-leaves of thew tree will never be inserted. So you probalby should check/debug that function.

Recursive function: for vs if

In one of the C exercises I had to create a function for binary tree traversal with a given depth.
My first thought was to use a for loop (traverse_preorder_bad). Finally, I could complete the task with a variable initialization + if (traverse_preorder_working), but I am still struggling to understand why the for solution didn't work.
Could someone explain me the difference? Is there an elegant solution?
Code on Ideone
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int RANGE = 1000;
typedef struct node_t
{
int data;
struct node_t *left;
struct node_t *right;
} node_t;
node_t *node_new(int data);
node_t *node_insert(node_t *tree, int data);
void traverse_preorder_working(node_t *tree, int depth);
void traverse_preorder_bad(node_t *tree, int depth);
int main(int argc, char *argv[])
{
node_t *tree = NULL;
// Random seed
srand((unsigned) time(NULL));
// Create the root node
tree = node_new(rand() % RANGE);
node_insert(tree, 5);
node_insert(tree, 1);
printf("Expected output:\n");
traverse_preorder_working(tree, 10);
printf("Bad output:\n");
traverse_preorder_bad(tree, 10);
return 0;
}
node_t *node_new(int data)
{
node_t *tree;
tree = malloc(sizeof(*tree));
tree->left = NULL;
tree->right = NULL;
tree->data = data;
return tree;
}
node_t *node_insert(node_t *tree, int data)
{
if (!tree)
return node_new(data);
if (data == tree->data)
return tree;
if (data < tree->data)
tree->left = node_insert(tree->left, data);
else
tree->right = node_insert(tree->right, data);
return tree;
}
void traverse_preorder_working(node_t *tree, int depth)
{
int i;
if (!tree)
return;
printf("%d\n", tree->data);
i = 1;
if (tree->left && i <= depth)
{
traverse_preorder_working(tree->left, depth - i);
i++;
}
i = 1;
if (tree->right && i <= depth)
{
traverse_preorder_working(tree->right, depth - i);
i++;
}
}
void traverse_preorder_bad(node_t *tree, int depth)
{
if (!tree)
return;
printf("%d\n", tree->data);
for (int i = 1; tree->left && i <= depth; i++)
traverse_preorder_bad(tree->left, depth - i);
for (int i = 1; tree->right && i <= depth; i++)
traverse_preorder_bad(tree->right, depth - i);
}
The problem is that traverse_preorder_working is correctly recursive, when visiting a node you call traverse_preorder_working recursively on the left subtree (and then right)
Instead traverse_preorder_bad is still recursive but it makes no sense, when you visit a node you then call traverse_preorder_bad n-times on the same subtree with a different depth.
If you check invocation tree for something like:
a
/ \
b c
/ \ / \
d e f g
You can see that traverse_preorder_working(a,5) goes traverse_preorder_working(b,4), traverse_preorder_working(d,3) .. while other function goes
traverse_preorder_bad(a,5),
traverse_preorder_bad(b,4), visit subtree
traverse_preorder_bad(b,3), visit subtree
traverse_preorder_bad(b,2), visit subtree
traverse_preorder_bad(b,1), visit subtree ...
from the same level of recursion, which means that each node will be visited multiple times with different depth limits; this doesn't happen in the first correct version.
If each invocation of traverse_preorder_bad should visit a node and start visiting both subtrees but inside the code you call visit recursively more than twice (which is the case, since you have a loop) then something is wrong.
The "for" version make no sense. You only want to print the tree for a given node once, so you should only call traverse on each node once.
Additionally, based on one of your comments in your post, I think you have some misunderstandings about your working function.
You have multiple checks for whether the tree is null (both as the current tree or as its children)
i ever only has a value of one while it is being used. You could simplify to
void traverse_preorder_working(node_t *tree, int depth){
if(!tree || depth <= 0){
return;
}
printf("%d\n", tree->data);
traverse_preorder_working(tree->left, depth - 1);
traverse_preorder_working(tree->right, depth - 1);
}
All of the checks to see if we not should explore a node - either because it doesn't exist or it is too deep - are done only once (at the start of the function), and not repeated twice for each child. No i variable that does nothing.
The elegant solution here (without recursion) is Morris Traversal. The idea is to add indirection edge from the left subtree's rightmost node to the current node.
The full explanation of the algorithm is here: http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
Of course you can modify this algorithm not to go deeper then you current depth.

Using a Binary Tree

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node_{
int val;
struct node_ *left;
struct node_ *right;
}node;
node* insert(node* root,int val);
void inorder(node* root);
int main(void)
{
int i;
int item;
node* root = NULL;
srand(time(NULL));
for( i = 0; i < 10; i++)
{
item = rand()%15;
insert(root,item);
}
inorder(root);
return 0;
}
node* insert(node* root,int val)
{
if(root == NULL)
{
root = malloc(sizeof(node));
if(root!= NULL)
{
(root)->val = val;
(root)->left = NULL;
(root)->right = NULL;
}
else
printf("%d not inserted. No memory available.\n",val);
}
else
{
if(val < (root)->val)
{
insert((root->left),val);
}
if(val>root->val)
{
insert(((root)->right),val);
}
}
}
void inorder(node* root)
{
printf("%p",root);
if(root != NULL)
{
inorder(root->left);
printf("%3d",root->val);
inorder(root->right);
}
}
I am trying to create a binary tree and print out the values in order. However when I run this code the printf of the address prints out nil obviously meaning that my tree is empty so the printf and recursion below does not run. I cannot figure out where I went wrong, any suggestions or answers would be appreciated because I can't figure out why the root would be null after calling all of those inserts in main.
You pass root as a parameter to insert() (which says it is going to return something but doesn't). Inside insert you malloc your node and assign it to the local variable root. Nothing you ever do makes it out of the insert function.
Try returning something from insert, or using a global root.
As #JoshuaByer hints in the comments below, another approach is to make your insert method "pass by reference" so it can effectively modify what was passed to it.
void insert(node** rootp,int val)
{
if(*rootp == NULL)
{
*rootp = malloc(sizeof(node));
}
/* and so on */
If you don't understand what this is saying, google "Pass by reference in C" and I'm positive you'll get some good information.
In main() after declaring and initializing root (node* root = NULL;) you're never assigning it. In order to fix you should probably change the lin insert(root,item); to root = insert(root,item);.
Also note that although insert is defined as returning node * it does not return any value.

Linked List of BST in C: Breadth First Search

I am writing a program that is a linked list of binary search trees. We are supposed to search for a number in the trees and print the tree and line number found. Because of this, we are supposed to use a Breadth-First Search function. I am getting a segmentation fault in my dequeue function and I am unsure why.
These are my structures:
typedef struct BST {
int value;
int treeNum;
struct BST* left;
struct BST* right;
}BST;
typedef struct rootList{
struct BST* root;
struct rootList* next;
}rootList;
typedef struct bfsQ{
struct BST* treeNode;
struct bfsQ* next;
}bfsQ;
This is my BFS function:
void BFS(rootList* listHead, int searchValue)
{
if(listHead->root == NULL)
{
printf("%d/tNO/tN/A/tN/A\n", searchValue);
}
else
{
bfsQ* newQueue = NULL;
BST* temp = NULL;
newQueue = malloc(sizeof(bfsQ));
newQueue->next = NULL;
enqueue(&newQueue, listHead->root);
while(newQueue != NULL)
{
temp = dequeue(&newQueue);
printf("Did this work?");
if(temp->value == searchValue)
printf("HI I WAS FOUND");
else
{
if(temp->left != NULL)
enqueue(&newQueue, temp->left);
if(temp->right != NULL)
enqueue(&newQueue, temp->right);
}
}
BFS(listHead->next, searchValue);
}
}
This is my enqueue:
void enqueue(bfsQ** qHead, BST* new_tree_node)
{
bfsQ *temp = malloc(sizeof(bfsQ));
BST *node;
temp->treeNode = new_tree_node;
temp->next = *qHead;
*qHead = temp;
node = temp->treeNode;
printf("%d\n", node->value);
}
This is my dequeue:
BST* dequeue(bfsQ** qHead)
{
bfsQ *temp, *first;
BST *newBST;
temp = (*qHead);
while(temp->next != NULL)
{
printf("THIS IS NOT NULL YET\n");
temp = temp->next;
}
first = temp;
newBST = first->treeNode;
free(temp);
return first->treeNode;
}
What am I doing wrong? The enqueue is working correctly, however my dequeue is not storing correctly.
EDIT: Apparently I need to:
"This function implements a variant of a level by level search or formally
called as the BREADTH FIRST SEARCH.
-> This function searches for a given value in the binary trees and it does that
by searching for level 1 in each binary trees, then moving on to level 2 if
it fails to find it that value in level 1 and so on.
-> Basically, you have to search for a given value in all the binary trees, one
level at a time, in the linked list simultaneously."
So I'm not sure if I need to search the whole tree, then move on, or look at each tree, line by line.
From the superficial look I had into the code, it looks generally ok (though I would have implemented some parts differently), but the last lines in dequeue() are certainly wrong:
first = temp;
newBST = first->treeNode;
free(temp);
return first->treeNode;
Accessing first->treeNode in the last line is catastrophic: first holds an address that has already been freed (temp and first refer to the same memory location). I think you wanted to return newBST instead:
return newBST;
You might as well throw first away, as it seems useless, and turn that into:
newBST = temp->treeNode;
free(temp);
return newBST;

Problem with pointers in binary search tree deletion

I am trying to implement binary search tree operations and got stuck at deletion.
11
/ \
10 14
Using inorder traversal as representation of tree initially output is 10 11 14.
Deleting node 10, output expected is 11 14 but I am getting 0 11 14.
Deleting node 14, output expected is just 11 but I am getting 0 11 67837.
Please explain why I am getting wrong output. I am not looking for any code :).
typedef struct _node{
int data;
struct _node *left;
struct _node *right;
} Node;
Node* bstree_search(Node *root, int key)
{
if(root == NULL){
return root;
}
// Based on binary search relation, key can be found in either left,
// right, or root.
if(key > root->data)
return bstree_search(root->right, key);
else if(key < root->data)
return bstree_search(root->left, key);
else
return root;
}
void bstree_insert(Node **adroot, int value)
{
// since address of address(root is itself address) is passed we can change root.
if(*adroot == NULL){
*adroot = malloc(sizeof(**adroot));
(*adroot)->data = value;
(*adroot)->right = (*adroot)->left = NULL;
return;
}
if(value > (*adroot)->data)
bstree_insert(&(*adroot)->right, value);
else
bstree_insert(&(*adroot)->left, value);
}
void bstree_inorder_walk(Node *root)
{
if(root != NULL){
bstree_inorder_walk(root->left);
printf("%d ",root->data);
bstree_inorder_walk(root->right);
}
}
void bstree_delete(Node **adnode)
{
//Node with no children or only one child
Node *node, *temp;
node = temp = *adnode;
if((*adnode)->right == NULL || (*adnode)->left == NULL){
if((*adnode)->right == NULL){
*adnode = (*adnode)->left;
}else{
*adnode = (*adnode)->right;
}
}else{ // Node with two children
}
free(temp);
}
int main()
{
Node *root = NULL;
Node *needle = NULL;
int i,elems[] = {11,10,14};
for(i = 0; i < 3; ++i)
bstree_insert(&root,elems[i]);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 10);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 14);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
}
Please explain why I am getting wrong
output.
Your delete function must also change the parent of the deleted Node. For example, when you delete the node holding 10, you must set the root Node's left child to NULL. Since you don't do this, when you later traverse the tree, you print out data that has already been freed.
I did not look at any code other than delete, so I can't make any guarantees about it working once this change is made.
You're getting wrong output because your deletion code is buggy (okay, maybe that's stating the obvious).
To delete from a binary search tree, you first find the node to be deleted. If it's a leaf node, you set the pointer to it in its parent node to NULL, and free the node. If it's not a leaf node, you take one of two leaf nodes (either the left-most child in the right sub-tree, or the right-most child in the left sub-tree) and insert that in place of the node you need to delete, set the pointer to that node in its previous parent to NULL, and delete the node you've now "spliced out" of the tree.
A couple of things really quick,
first when you allocate the node, you really should be doing the malloc on the sizeof the type (ie Node).
Second, if you have 2 children it looks like you are not really deleting the node and rebuilding the search tree by promoting one of the children.
Other people have already got you other obvious errors.

Resources