I am a beginner and working on a C binary search tree.I am trying to do a method that will return the number of leaves in my tree.By leaves I mean a node(parent) that has no child(left/right) Heres my tree struct:
struct Node {
int value;
struct Node *left;
struct Node *right;
};
typedef struct Node TNode;
typedef struct Node *binary_tree;
It is created like this:
binary_tree NewBinaryTree(int value_root) {
binary_tree newRoot = malloc(sizeof(TNode));
if (newRoot) {
newRoot->value = value_root;
newRoot->left = NULL;
newRoot->right = NULL;
}
return newRoot;
}
I add elements to it like:
void Insert(binary_tree *tree, int val) {
if (*tree == NULL) {
*tree = (binary_tree)malloc(sizeof(TNode));
(*tree)->value = val;
(*tree)->left = NULL;
(*tree)->right = NULL;
} else {
if (val < (*tree)->value) {
Insert(&(*tree)->left, val);
} else {
Insert(&(*tree)->right, val);
}
}
}
My actual method to count the number of leaves:
int nbleaves(binary_tree tree)
{
int nb;
if(tree->right==NULL && tree->left ==NULL){
nb=nb+1;
}
printf("%d",nb);
}
Of course this doesnt work first theres no actual loop,however I tried it it doesnt return any error but 0(ex after adding element 2222 and 3 to the tree this function return 0).I dont know how to do this function.
thank you!
Because you MUST initialize nb.
int nb = 0;
Since nb is uninitialized it contains a "random" or "garbage" value so the behavior you see is because that value can be very large. But there is no way to predict what that value is.
NOTE: Don't be "stingy" with white spaces, don't use too many of them but let your code breath a little.
Compare
if(tree->right==NULL && tree->left ==NULL){
nb=nb+1;
}
with
if ((tree->right == NULL) && (tree->left == NULL)) {
nb = nb + 1;
}
Besides initializing as #iharob pointed out, you just need to recurse on the left and right halves of the tree and add that to your total (as said in the comments). This approach worked for me on my tests so I'm not sure what error you're getting when you tried it. Here's my nbleaves() function:
int nbleaves(binary_tree tree)
{
int nb=0;
if(tree->right==NULL && tree->left ==NULL){
nb=nb+1;
}
else {
if(tree->left!=NULL)
nb += nbleaves(tree->left);
if(tree->right!=NULL)
nb += nbleaves(tree->right);
}
return nb;
}
For example, on this test case:
int main() {
binary_tree root=NULL;
root=NewBinaryTree(5);
Insert(&root,3);
Insert(&root,7);
Insert(&root,2);
Insert(&root,8);
Insert(&root,6);
Insert(&root,1);
Insert(&root,4);
Insert(&root,9);
traverse(root); /*Just a function I created for testing*/
printf("%d\n",nbleaves(root));
free_tree(root); /*Also a function I wrote*/
return 0;
}
It produces this output:
5: 3 7
3: 2 4
2: 1 NULL
1: NULL NULL
4: NULL NULL
7: 6 8
6: NULL NULL
8: NULL 9
9: NULL NULL
4
The last line is the leaves count and the rest are outputs of traverse().
For my full program: https://repl.it/Epud/0
Related
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;
}
}
Given the following struct:
typedef struct node_t {
int x;
struct node_t *next;
} *Node;
Please Note: the definition above is given to me as is and can't be changed.
I wrote the following function:
inline int getMin(Node *list1,Node *list2)
{
int first_value=INT_MAX,second_value=INT_MAX;
if (*list1)
{
first_value=(*list1)->x;
}
if (*list2)
{
second_value=(*list2)->x;
}
if (first_value<second_value)
{
*list1=(*list1)->next;
return first_value;
}
*list2=(*list2)->next;
return second_value;
}
It receives 2 pointers to a series of Nodes while each node has two attributes: x and next (a pointer to the next code)
My code should get the minimum value when comparing the values of the current two nodes, while it works fine with 99% of the cases it doesn't work with the case where list1 points to a node that its value is INT_MAX and next points to null and list2 is NULL
how can I fix this?
I fixed this by changing the following code:
if (first_value<second_value) to
if (first_value<=second_value)
but I have a new problem:
list2 points to a node that its value is INT_MAX and next points to null and list1 is NULL
Edit: Here is the last version of my code:
helper functions:
int advance(Node *node) {
int node_value = (*node)->x;
*node = (*node)->next;
return node_value;
}
int getMin(Node *list1, Node *list2) {
assert(*list1 || *list2);
if (!(*list1)) {
return advance(list2);
}
if (!(*list2)) {
return advance(list1);
}
if ((*list1)->x < (*list2)->x) {
return advance(list1);
}
return advance(list2);
}
main function:
ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out) {
if (!merged_out) {
return NULL_ARGUMENT;
}
if (!list1 || !list2) {
return EMPTY_LIST;
}
if (!isListSorted(list1) || !isListSorted(list2)) {
return UNSORTED_LIST;
}
Node ptr = *merged_out;
int total_len = getListLength(list1) + getListLength(list2);
for (int i = 0; i < total_len; i++) {
int min = getMin(&list1, &list2);
if (i != 0) {
ptr->next = malloc(sizeof(*ptr));
if (!ptr->next) {
destroyList(*merged_out);
return MEMORY_ERROR;
}
ptr = ptr->next;
}
ptr->x = min;
}
ptr->next = NULL;
return SUCCESS;
}
This is the classical merge sort code where you have four cases provided that not both lists are exhausted:
a is exhausted;
b is exhausted;
a < b and
a ≥ b.
You have tried to coalesce the two first cases where one of the nodes is null with the comparison, but because your lists can have INT_MAX as value, that solution isn't robust.
Write out these cases explicitly. First a little auxiliary function that advances a node and returns the value:
static int advance(Node *nd)
{
int res = (*nd)->x;
*nd = (*nd)->next;
return res;
}
Now your actual function is very simple:
int getMin(Node *list1, Node *list2)
{
assert(*list1 || *list2);
if (*list1 == NULL) return advance(list2);
if (*list2 == NULL) return advance(list1);
if ((*list1)->x < (*list2)->x) return advance(list1);
return advance(list2);
}
See it in action on ideone.
I am working on an algorithm to delete a node with a given key from a binary search tree. So far, I have been able to come up with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
typedef int ElType;
typedef struct Tree {
ElType key;
struct Tree *left;
struct Tree *right;
struct Tree *parent;
} Tree;
Tree* InsertBST(Tree* t, int k)
{
if (t == NULL) {
Tree* w = (Tree*) malloc(sizeof(Tree));
w->key = k;
w->left = NULL;
w->right = NULL;
w->parent = NULL;
return w;
}
if (k <= t->key) {
t->left = InsertBST(t->left, k);
t->left->parent = t;
}
else {
t->right = InsertBST(t->right, k);
t->right->parent = t;
}
return t;
}
Tree* DeleteMaxOfBST(Tree* t, ElType *deleted_value)
{
if (t == NULL) {
*deleted_value = -1;
return NULL;
}
if (t->right == NULL) {
*deleted_value = t->key;
Tree* w = t->left;
w->parent = t->parent;
free(t);
return w;
}
t->right = DeleteMaxOfBST(t->right, deleted_value);
return t;
}
Tree* DeleteNodeOfBST(Tree* t, int k)
{
if (t == NULL) return NULL;
if (k < t->key) {
t->left = DeleteNodeOfBST(t->left, k);
return t;
}
else if (k > t->key) {
t->right = DeleteNodeOfBST(t->right, k);
return t;
}
else if (t->left == NULL) {
Tree* w = t->right;
w->parent = t->parent;
free(t);
return w;
}
else {
ElType max_left;
t->left = DeleteMaxOfBST(t->left, &max_left);
t->key = max_left;
return t;
}
}
The general idea is that I want to work with a BST with pointers to parent nodes and be able to delete a node with whichever key I specify while preserving the structure of a BST.
My code works for some keys in some trees but crashes for other keys without any apparent pattern. I then get the following error:
Segmentation fault (core dumped)
I am inclined to think I have messed up the pointers to the parent nodes but cannot quite pinpoint where the fault is. I am relatively new to C, so I would appreciate any comments whether pointers are in fact the problem here and how to possibly fix this.
So, without any examples of how your code runs it's hard to say where exactly the segmentation fault is occurring when your program is running. When your program encounters a segmentation fault that means that the program is attempting to access memory that, for whatever reason, it is unable to. This generally means your pointers are trying to point at an address in memory that they shouldn't be.
My suggestion would be to run the code step by step and see where the problem occurs. Or find a debugger that can show you the memory issues your program is having. I know that the program Valgrind exists for Ubuntu and other Linux best machines, but I'm not sure what others are available for other OSes. You can read more about Valgrind here: http://valgrind.org/. I use it whenever I need to check for potential memory handling issues in my programs.
Other than that, just keep a real close eye on the space that you create using malloc, as well as where your pointers are pointing. Make sure to reconnect your tree properly when you delete the given node. Manually handling memory can be a pain, but you'll get the hang of it.
Here is the source code for C Program for Insertion and Deletion in Binary Search Tree Recursive..................
/* C Program for Insertion and Deletion in Binary Search Tree Recursive */
#include<stdio.h>
#include<stdlib.h>
struct node
{
struct node *lchild;
int info;
struct node *rchild;
};
struct node *insert(struct node *ptr, int ikey);
void display(struct node *ptr,int level);
struct node *del(struct node *ptr, int dkey);
int main( )
{
struct node *root=NULL,*ptr;
int choice,k;
while(1)
{
printf("\n");
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Display\n");
printf("4.Quit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter the key to be inserted : ");
scanf("%d",&k);
root = insert(root, k);
break;
case 2:
printf("Enter the key to be deleted : ");
scanf("%d",&k);
root = del(root,k);
break;
case 3:
display(root,0);
break;
case 4:
exit(1);
default:
printf("\nWrong choice\n");
}/*End of switch */
}/*End of while */
return 0;
}/*End of main( )*/
struct node *insert(struct node *ptr, int ikey )
{
if(ptr==NULL)
{
ptr = (struct node *) malloc(sizeof(struct node));
ptr->info = ikey;
ptr->lchild = NULL;
ptr->rchild = NULL;
}
else if(ikey < ptr->info) /*Insertion in left subtree*/
ptr->lchild = insert(ptr->lchild, ikey);
else if(ikey > ptr->info) /*Insertion in right subtree */
ptr->rchild = insert(ptr->rchild, ikey);
else
printf("\nDuplicate key\n");
return ptr;
}/*End of insert( )*/
void display(struct node *ptr,int level)
{
int i;
if(ptr == NULL )/*Base Case*/
return;
else
{
display(ptr->rchild, level+1);
printf("\n");
for (i=0; i<level; i++)
printf(" ");
printf("%d", ptr->info);
display(ptr->lchild, level+1);
}
printf("\n");
}/*End of display()*/
struct node *del(struct node *ptr, int dkey)
{
struct node *tmp, *succ;
if( ptr == NULL)
{
printf("dkey not found\n");
return(ptr);
}
if( dkey < ptr->info )/*delete from left subtree*/
ptr->lchild = del(ptr->lchild, dkey);
else if( dkey > ptr->info )/*delete from right subtree*/
ptr->rchild = del(ptr->rchild, dkey);
else
{
/*key to be deleted is found*/
if( ptr->lchild!=NULL && ptr->rchild!=NULL ) /*2 children*/
{
succ=ptr->rchild;
while(succ->lchild)
succ=succ->lchild;
ptr->info=succ->info;
ptr->rchild = del(ptr->rchild, succ->info);
}
else
{
tmp = ptr;
if( ptr->lchild != NULL ) /*only left child*/
ptr = ptr->lchild;
else if( ptr->rchild != NULL) /*only right child*/
ptr = ptr->rchild;
else /* no child */
ptr = NULL;
free(tmp);
}
}
return ptr;
}/*End of del( )*/
Hope it may help you. For more details, Visit here for More Operations on Binary Search tree ---> C Program for Insertion and Deletion in Binary Search Tree Recursive
and C Program for binary search tree deletion without recursion
I was working on the exercises here :
"http://cslibrary.stanford.edu/110/BinaryTrees.html#s2"
I wrote a function that decides if a Tree is a BST(return 1) or not(return 0) but I'm not sure if my code is totally good, I tested it for a BST and a non-BST Tree and it seems to work correctly. I want to know the opinion of the community :
Updated Code :
consider the Tree ( not a BST ) :
5
/ \
2 7
/ \
1 6
my Idea is to compare 2 with 5 if it's good, then 1 with 5, and if it's good then 6 with 5 if it's good then 1 with 2 if it's good then 6 with 2 if it's good then 5 with 7 ; if it's good isBST() returns 1. this code is supposed to do it recursively.
the node structure :
struct node {
int data;
struct node* left;
struct node* right;
};
the code :
int lisgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = lisgood(n1,n2->left)*lisgood(n1,n2->right);
if(r){
if(n1->data >= n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int risgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = risgood(n1,n2->right)*risgood(n1,n2->left);
if(r){
if(n1->data < n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int isBST(struct node* node)
{
if(node == NULL)
return 1;
else{
if(lisgood(node,node->left)&&risgood(node,node->right)){
return (isBST(node->left)&&isBST(node->right));
}
else return 0;
}
}
Your code doesn't really work - not even for the example you showed. You never compare 5 to 6. Basically you are comparing the root of a sub-tree with root->left, root->left->left, root->left->left->left, etc. Then you are comparing root with root->right, root->right->right, etc., but you never compare root with the other nodes in the subtree. The problem is that you don't compare a tree's root with every element on its right and left subtrees, and you should.
This is a known interview question. The simpler way to solve it is to pass in the minimum and maximum values allowed for a sub-tree as parameters.
Here's how it works with the example tree you showed: you see 5, thus, the maximum value for any node on 5's left subtree is 5. Similarly, the minimum value for any node on 5's right subtree is 5. This property is applied recursively to check that every node's value is consistent with the requirements. Here's a working implementation (assumes a tree with no duplicates):
#include <stdio.h>
#include <limits.h>
struct tree_node {
int key;
struct tree_node *left;
struct tree_node *right;
};
static int is_bst_aux(struct tree_node *root, int min, int max) {
if (root == NULL) {
return 1;
}
if (!(min < root->key && root->key < max)) {
return 0;
}
if (!is_bst_aux(root->left, min, root->key)) {
return 0;
}
return is_bst_aux(root->right, root->key, max);
}
int is_bst(struct tree_node *root) {
return is_bst_aux(root, INT_MIN, INT_MAX);
}
I'm working on a project where I must take an expression in reverse polish notation, push the integers and operators onto a stack, then pop them out off the stack as they are inserted into a binary search tree.
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct snode
{
int datum;
struct snode* bottom;
};
struct tnode
{
int datum;
struct tnode* left;
struct tnode*right;
};
struct snode*
push(struct snode* stack, int x) {
struct snode *S = (struct snode*)malloc(sizeof(struct snode));
S->datum = x;
S->bottom = stack;
return S;
}
struct snode* pop(struct snode* stack) {
struct snode *S;
if (stack == NULL)
return NULL;
S = stack->bottom;
free(stack);
return S;
}
int
peek(struct snode* stack){
return stack->datum;
}
struct tnode*
create_node(int x){
struct tnode* tmp;
tmp = (struct tnode*)malloc(sizeof(struct tnode));
tmp->datum = x;
tmp->right = NULL;
tmp->left = NULL;
return tmp;
}
void
print_table(struct tnode *AST){
if(AST !=NULL){
print_table(AST->left);
printf("%d ", AST->datum);
print_table(AST->right);
}
}
struct tnode*
build_tree(struct snode *S)
{
struct tnode* root;
if (S==NULL){
return NULL;
}else{
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77){
return create_node(top);
}else{
root= create_node(top);
root->right = build_tree(pop(S));
root->left = build_tree(pop(S));
return root;
}
}
}
int
main(int argc, const char *argv[])
{
int i = 1;
struct tnode *tree = NULL;
struct snode *stack = NULL;
while (argv[i]!= NULL){
stack = push(stack, argv[i][0]);
i++;
}
tree = build_tree(stack);
print_table(tree);
return EXIT_SUCCESS;
}
I feel like this should work. Everything compiles clean. I run it by saying
./project 5 4 A
and what comes out is
135208 135224 135208 135240 135208 135224 135208 0 135208 135224 135208 52 0 53 0
when it should be
4 65 5
I think this is happening where because of how I'm pushing the elements on to the stack.
EDIT:
I initialized i so that i = 1.
this is the result I am getting.
134480 134496 134480 0 5 4 5
EDIT2:
I decided to get rid of the atol(argv[i]) and change it to just argv[i][0].
see code.
Now my out put is just
65
Finally figured out what was going on!
Here is the newly modified sections that should make your code work (please view the // <== EDIT comments) :
struct tnode*
build_tree(struct snode *S)
{
struct tnode* root;
if (S == NULL)
return NULL;
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
{
root = create_node(top);
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
return root;
}
root= create_node(top);
return root;
}
int
main(int argc, const char *argv[])
{
int i = 1;
struct tnode *tree = NULL;
struct snode *stack = NULL;
int value = 0;
while (argv[i]!= NULL)
{
if ((value = atoi(argv[i])) == 0) // <== EDIT
value = argv[i][0];
stack = push(stack, value);
i++;
}
tree = build_tree(stack);
print_table(tree);
return EXIT_SUCCESS;
}
I have noticed 3 issues that are causing the values that you have.
First issue :
The result that you are looking for is 4 65 5, which means that if the input is a number (4, 5, etc) you must use the result of atoi(). If the input is not a number, you must use the ASCII value.
To do this, I have used the following lines :
if ((value = atoi(argv[i])) == 0) // <== EDIT
value = argv[i][0];
stack = push(stack, value);
In my implementation of atoi(), when the conversion fails, atoi() returns 0. Therefore, I check the value of the assignment : if atoi() returned 0, use the ASCII value.
Second issue :
The second problem you are having is that the build_tree() function seems to have faulty logic. Since this is a tree, I would expect the character A to be the root and the numbers 4 and 5 to be the branches, like so :
A
/ \
4 5
Your logic seems to reverse the situation, the way you are setup, the numbers become root values and the letters are branches. Reversing your logic solves this :
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
{
root = create_node(top);
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
return root;
}
root= create_node(top);
return root;
Last issue :
This is the big one. When you call build_tree(), you pass the result of pop() directly. The problem with that, is that you are not affecting the new root value to S. Because of this :
When you call build_tree(pop(S)) the first time, you end up freeing the memory space for S.
Later, when you call build_tree(pop(S)) a second time, you end up calling pop(S) on the initial value (the one that has been freed early on).
The solution is to reassign S when you call pop(), and calling build_tree(S) afterwards.
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
TL;DR :
I reformated your code a bit and the issue should be fixed now. Copy paste and you should be good.