Binary search tree - Iterative check for height - c

So, I'm having a bit of problem. I know how to traverse tree, using recursion or not, using stack or not. But, I also want to track height of every leaf, and if height(or depth) is less than given argument to print that leaf. Here is my code using stack:
void PrintLevelIter(struct tNode* tree, int h1){
if(h1==0){
printf("%d ",tree->info);
return;
}
struct sNode *stek = NULL;
push(&stek,tree);
struct tNode* current = tree;
while(!isEmptyStack(stek)){
pop(&stek);
printf("%d ",current->info);
if(current->left != NULL && current->right != NULL){
if(Depth(current) < h1){
push(&stek, current);
}
else return;
}
}
}
What am I doing wrong? Is it maybe because of my stack implementation? Here is code:
struct sNode{
struct tNode* t;
struct sNode* next;
};
/*Funkcije za stek*/
void push(struct sNode** top, struct tNode* t){
struct sNode* newNode = (struct sNode*)malloc(sizeof(struct sNode));
if(newNode==NULL)
{
return;
}
newNode->t = t;
newNode->next = (*top);
(*top) = newNode;
}
int isEmptyStack(struct sNode* top){
return top==NULL;
}
struct tNode* pop(struct sNode** top){
struct tNode* res;
struct sNode* sTop;
if(isEmptyStack(*top))
printf("Stack is empty!");
else{
sTop = *top;
res = sTop->t;
*top = sTop->next;
free(top);
}
return res;
}
The thing is, my output gives me only root value, nothing else. Does anyone know where I'm making a mistake? Or mistakes :)?

you don't change the value of current inside the loop, pop(&stek) should be current = pop(&stek)
return should be continue, it's not a recursion, return will exit the function before all the tree is traversed
you need to push the node children not the node himself
while (!isEmptyStack(stek))
{
current = pop(&stek);
if (current->left != NULL)
push(&stek, current->left);
if (current->right != NULL)
push(&stek, current->right);
if (Depth(current) < h1)
printf("%d ",current->info);
}
as #chux said, pop should return NULL if stack is empty

Related

How to implement the function delete of a binary search tree without recursion in C?

I try to implement the delete method but that doesn't work with me. I want to delete all nodes in the tree. The function has tree type of "struct tree" as a parameter so I can't use recursion; I want to do it with a loop.
That's my structure
typedef struct Node Node;
struct Node{
const void* data;
const void* value;
Node* left;
Node* right;
};
typedef struct Tree Tree;
struct Tree{
Node* root;
size_t size;
int (*comp)(const void *, const void *);
};
function delete
void freeTree(Tree* tree, bool TreeContent){
if(tree->root != NULL){
// free(tree->root->left);
// free(tree->root->right);
// free(tree->root);
}
}
function insert
bool insertInTree(Tree* bst, const void* key, const void* value){
if(bst->root == NULL){
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
return true;
}
else{
int isLeft = 0 ;
Node* Current = bst->root ;
Node* precedant = NULL;
while(Current != NULL){
int compare = bst->comp(&Current->data , &key);
precedant = Current;
if(compare == 1){
isLeft = 1;
Current = Current->left;
}
else if(compare == 0){
isLeft = 0;
Current = Current->right;
}
}
if(isLeft == 1){
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
precedant->left = newNode;
bst->size++;
return true;
}
else{
Node* newNode = (Node*) malloc(sizeof(Node));
if(newNode == NULL){
printf("erreur d'allocation dynamique \n");
exit(1);
}
newNode->left = newNode->right = NULL;
newNode->value = value;
newNode->data = key;
precedant->right = newNode;
bst->size++;
return true;
}
}
return false;
}
edit You don't want to use recursion because the freeTree function doesn't take a Node argument. In this case, you can remove that restriction by creating another function that is recursive, called initially by freeTree.
void freeTree(Tree* tree, bool TreeContent){
if(tree->root != NULL){
freeNode(tree->root);
tree->root = NULL;
}
}
The new freeNode could look like
void freeNode(Node *node) {
if (node->left) freeNode(node->left);
if (node->right) freeNode(node->right);
free(node);
}
Note that freeNode intent is to free the whole tree (otherwise the parent element's left or right [or root] would have to be set to NULL).
Your requirement is that you don't want to use recursion.
Any kind of traversal is not possible in O(n) time without use of a stack/queue (implicitly or explicitly). So we will use a stack (made using an array) and use it to delete all the nodes.
I understand that you have the size of the BST known, so you can create an array of appropriate size as -
struct Node* stack[bst->size];
int top = -1;
This stack will hold all the elements to be processed.
We will first add the root to the stack -
if(bst->root)
stack[++top] = bst->root;
Now we need to process all the nodes in the tree using a loop -
while(top>=0){
//Pop one node -
struct Node* node = stack[top--];
//Add its children to the stack;
if(node->left)
stack[++top] = node->left;
if(node->right)
stack[++top] = node->right;
// Now free the node as
free(node);
}
That is all, one by one each node will be added to the stack and the stack will become empty when all the nodes are done.
Also as a side note, in your insert function you need to do bst->size++ in the if(bst->root == NULL) branch. Else your size will be one less than actual number of nodes.

Binary Tree implementation on C

I am trying to implement tree in C but the thing is whenever i try to traverse it, it only shows the first three nodes of the tree and the rest are lost. like, if i enter 100, 200, 300, 400, 500, 600, 700 then only 100 ,200, 300 will be in the output. I think the problem is with insert function but i just can't figure it out.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *prev;
struct node *next;
};
typedef struct node list;
list *head, *tail, *current, *newn;
void inorder(struct node *t)
{
if(t != NULL)
{
inorder(t->prev);
printf("%d->",t->data);
inorder(t->next);
}
}
struct node * insert(int key, struct node *t)
{
if(t == NULL)
{
t = (list*)malloc(sizeof(list));
t->data = key;
t->prev = NULL;
t->next = NULL;
}
else if(t->prev == NULL)
{
t->prev = insert(key,t->prev);
}
else if(t->next == NULL)
{
t->next = insert(key,t->next);
}
return(t);
}
int main()
{
int x=1, y, z=1;
current = (list*)malloc(sizeof(list));
printf("Enter data:");
scanf("%d",&current->data);
current->next = NULL;
current->prev = NULL;
head = current;
while(z == 1)
{
printf("Enter data:");
scanf("%d",&y);
current = insert(y,current);
printf("want to insert more:");
scanf("%d",&z);
}
printf("\nInorder Traversal:");
newn = head;
inorder(newn);
}
only 100 ,200, 300 will be in the output.
at Insert function
if(t == NULL)
{
...
}
else if(t->prev == NULL)
{
...
}
else if(t->next == NULL)
{
...
}
return(t);
Because it is
When t, t->prev and t->next are not all NULL
Nothing (that is, inserting) is done.
When adding conditions and recursive calls like
else if(t->prev->prev == NULL)
{
t->prev->prev = insert(key, t->prev->prev);
}
Insertion of the node is done, but since growth becomes like depth-first search, the growth of the tree becomes biased.
So, as an approach you need to search for the next insertion point like breadth first search.
I think there are some methods,
As a method I propose, it is a way to keep it as a pool when creating a NULL node rather than searching.
A concrete implementation using a queue as a node pool is as follows(Please note that many checks are omitted And using global variables).
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *prev;
struct node *next;
};
typedef struct node list;
void inorder(struct node *t){
if(t != NULL){
inorder(t->prev);
printf("%d->",t->data);
inorder(t->next);
}
}
//node of queue
typedef struct null_node {
list **nodepp;
struct null_node *next;
} node_pool;
//queue
typedef struct queue {
node_pool *head;
node_pool *tail;
} queue;
//enqueue
void push(queue *q, list **nodepp){
node_pool *np = malloc(sizeof(*np));
np->nodepp = nodepp;
np->next = NULL;
if(q->head == NULL){
q->tail = q->head = np;
} else {
q->tail = q->tail->next = np;
}
}
//dequeue
list **pop(queue *q){
node_pool *head = q->head;
if(head == NULL)
return NULL;
q->head = q->head->next;
if(q->head == NULL)
q->tail = NULL;
list **nodepp = head->nodepp;
free(head);
return nodepp;
}
void clear_queue(queue *q){
while(pop(q));
}
list *Head;
queue Q;
struct node *insert(int key, struct node *root){
list *t = malloc(sizeof(*t));
t->data = key;
t->next = t->prev = NULL;
push(&Q, &t->prev);//enqueue a NULL node
push(&Q, &t->next);
if(root == NULL){
return t;
}
list **null_nodep = pop(&Q);//dequeue the node
*null_nodep = t;//Replace with new node
return root;
}
int main(void){
int /*x=1, unused x*/ y, z=1;
Head = NULL;
while(z == 1){
printf("Enter data:");
scanf("%d",&y);
Head = insert(y, Head);
printf("want to insert more:");
scanf("%d",&z);
}
printf("\nInorder Traversal:");
inorder(Head);
clear_queue(&Q);//Discard queued nodes
}

malloc in pointer received as argument

I'm implementing an binary search tree but for some reasons I 'm not able to add a node
my: input was :
a.value = 5;
add_bst_node(&t,a);
mystructures:
typedef struct BST_node{
entity value;
struct BST_node* left;
struct BST_node* right;
}BST_node;
typedef struct BST_tree{
BST_node* root;
}BST_tree;
my code for add a node:
void add_bst_node2(BST_node* root,entity* e){
if(!root){
root = (BST_node*)malloc(sizeof(BST_node));
root->value = *e;
root->left = NULL;
root->right = NULL;
return;
}
else if(great_than(&root->value,e))
add_bst_node2(root->left,e);
else
add_bst_node2(root->right,e);
}
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t->root,&e);
printf("%d\n",t->root==NULL);
}
Someone can explayn why I'can't add a node?
Apart from not passing double pointer to BST_node (i.e. BST_node**) in add_bst_node2() as noted in the comments, you also didn't implement the function properly.
Your implementation never really adds a node, but instead in enters into infinite recursion.
Here you can find some clean theory about BST - http://www.zentut.com/c-tutorial/c-binary-search-tree/
Here is an untested correction of your code. Note that here we pass pointer to BST_tree instead of BST_node
void add_bst_node2(BST_tree* tree,entity* e){
if(!tree->root){
/* If the binary search tree is empty, we just create a root node */
tree->root = bst_create_node(e);
return;
}
int is_left = 0;
BST_node* current_node = tree->root;
BST_node* prev = NULL;
/* Traverse the tree until we find the proper position for the new node.
* The position is denoted by 'current_node'
*/
while(current_node != NULL) {
prev = current_node;
if(greater_than(&current_node->value, e)) {
is_left = 1;
current_node = current_node->left;
} else {
is_left = 0;
current_node = current_node->right;
}
}
/* We finally know the position where we should add the new node */
if(is_left)
prev->left = bst_create_node(e);
else
prev->right = bst_create_node(e);
}
We introduce another function for creating and initializing a node...
BST_node *bst_create_node(entity *e)
{
BST_node *n = malloc(sizeof(BST_node));
n->value = *e;
n->left = NULL;
n->right = NULL;
return n;
}
And finally we change add_bst_node()
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t, &e);
printf("%d\n", t->root==NULL);
}
From what it seems, a is a struct BST_node and value is a variable in it. You have to either pass the value to the function and handle the node creation there, or pass the whole constructed node and just point to it from the existing tree.
first thing is that you put an unnecessary structure BST_tree.You do it in simple way like
struct node
{
int value;
node* left;
node* right;
};
struct node* root;
I suggest you try with this code
struct node* insert(struct node* r, int data)
{
if(r==NULL) // BST is not created created
{
r = (struct node*) malloc(sizeof(struct node)); // create a new node
r->value = data; // insert data to new node
// make left and right childs empty
r->left = NULL;
r->right = NULL;
}
// if the data is less than node value then we must put this in left sub-tree
else if(data < r->value){
r->left = insert(r->left, data);
}
// else this will be in the right subtree
else {
r->right = insert(r->right, data);
}
return r;
}`
`

Palindrome LinkedList

Method:
Traverse the given list from head to tail and push every visited node to stack.
Traverse the list again. For every visited node, pop a node from stack and compare data of popped node with currently visited node.
If all nodes matched, then return true, else false.
Edit: The program compiles without an error but stops working during run time
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
struct Node
{
int data;
struct Node *next;
};
struct Stack
{
unsigned capacity;
int top;
int * array;
};
struct Stack* createStack(unsigned capacity)
{
struct Stack* stack=(struct Stack*)malloc(sizeof(struct Stack));
stack->capacity=capacity;
stack->top=-1;
stack->array=(int *)malloc(sizeof(int)*stack->capacity);
return stack;
}
int isFull(struct Stack* stack)
{ return stack->top == stack->capacity - 1; }
// Stack
int isEmpty(struct Stack* stack)
{ return stack->top == -1; }
// stack.
void push(struct Stack* stack, int item)
{
if (isFull(stack))
return;
stack->array[++stack->top] = item;
printf("%d pushed to stack\n", item);
}
// stack.
int pop(struct Stack* stack)
{
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top--];
}
// stack
int peek(struct Stack* stack)
{
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top];
}
// linkedlist
void insert(struct Node** head_ref, int new_data)
{
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
bool compare(struct Stack* stack,struct Node* head)
{
struct Node* temp,* curr=head;
while(temp)
{
push(stack,temp->data);
temp=temp->next;
}
while(curr)
{
if(pop(stack)==curr->data)
{
curr=curr->next;
}
else
exit(0);
}
return true;
}
// Driver program to test above functions
int main()
{
struct Stack* stack = createStack(100);
struct Node* head=NULL;
insert(&head,1);
insert(&head,2);
insert(&head,1);
printf("%s",compare(stack,head));
return 0;
}
Function compare has at least two errors. The first one is that it uses uninitialized pointer temp
bool compare(struct Stack* stack,struct Node* head)
{
struct Node* temp,* curr=head;
while(temp) // <= temp is not initialized
{
The second one is that the function never returns false though according to the assignment it has to return false if values in the list and in the stack do not match.
Instead of returning false you call function exit
else
exit(0);
I would write the function the following way
bool compare(struct Stack *stack, struct Node *head )
{
struct Node *current = head;
for ( ; current != NULL && !isFull( stack ); current = current->next )
{
push( stack, current->data );
}
current = head;
while ( current != NULL && !isEmpty( stack ) && pop( stack ) == current->data )
{
current = current->next;
}
return current == NULL && isEmpty( stack );
}
It is the only correct function implementation among presented here function implementations in other answers.:)
As C does not have type bool then that you could use name bool in a program written in C you have to include header <stdbool.h> or define this name yourself as a typedef either of _Bool (if your compiler supports this type) or of int.
You could declare the return type of the function as int if you do not want to include header <stdbool.h>. For example
int compare(struct Stack *stack, struct Node *head );
Take into account that you need to write also functions that will free all allocated memory for the list and the stack.
For example you could free memory allocated for the stack the following way
void freeStack( struct Stack **stack )
{
if ( *stack != NULL ) free( ( *stack )->array );
free( *stack );
*stack = NULL;
}
The same way you could free the memory allocated for the list
void freeList( struct Node **head )
{
if ( *head != NULL )
{
Node *current = ( *head )->next;
while ( current != NULL )
{
Node *temp = current;
current = current->next;
free( temp );
}
}
free( *head );
*head = NULL;
}
struct Node* temp;
temp is not initialized in
bool compare(struct Stack* stack,struct Node* head)
struct Node* temp,* curr=head;
is not
struct struct Node* temp=head,* curr=head;
Using uninitialized variables lead to undefined behavior.
You've got an uninitialized local variable temp:
bool compare(struct Stack* stack,struct Node* head)
{
struct Node* temp,* curr=head;
while(temp) // NOT INITIALIZED
{
push(stack,temp->data);
temp=temp->next;
}
while(curr)
{
if(pop(stack)==curr->data)
{
curr=curr->next;
}
else
exit(0);
}
return true;
}
You need to fix that first; I think the following should work:
bool compare(struct Stack* stack,struct Node* head)
{
struct Node *curr;
for (curr = head; curr != NULL; curr = curr->next)
{
push(stack, curr->data);
}
for (curr = head; curr != NULL; curr = curr->next)
{
if (pop(stack) != curr->data)
return false;
}
return true;
}
Next, you're printing a boolean result with "%s", which is for strings. You need to do something like:
c=compare(stack,head);
printf("%d\n", c);
or alternatively
printf("%s\n", c ? "true" : "false");
At this point, it no longer crashes for me, and works for a couple simple test cases. You might think about how to handle the case of overflowing the stack, and also consider formatting your code to make it more readable.
bool compare(struct Stack* stack,struct Node* head) {
struct Node* temp=head;//<- Needs initialising. It wasn't.
struct Node* curr=head;
while(temp) {
push(stack,temp->data);
temp=temp->next;
}
while(curr) {
if(pop(stack)==curr->data) {
curr=curr->next;
} else {
//exit(0); <--Some mistake surely!
return false; //Slightly less drastic!
}
}
return true;
}
It's slightly a matter of taste but I find long series of variable declarations to be difficult to read and hence error-prone.
You only really need one local variable - but your compiler probably optimizes that away.
exit(0) will abruptly end the program. Most likely indicates 'success' (the exit of 0).
You should return false;.
PS: Credit for using #include <stdbool.h>.

Implementing Simple Linked List

Hi I wish to implement a simple linked list and all the values to the end of the list. As simple as that but I am not able to do so. Can you please tell me where I am doing it wrong ? Initially I am declaring a pointer and assigning NULL value to it. Later in each iteration I am allocating memory to the pointer that was initially NULL.
#include <stdio.h>
#include <malloc.h>
struct node{
int a;
struct node* next;
};
struct node* insert(struct node* start,int value);
void print(struct node* head);
int main()
{
int a;
struct node* head = NULL;
while(scanf("%d",&a) != EOF)//taking input
{
head = insert(head,a);
print(head);
}
return 0;
}
struct node* insert(struct node* start,int value)
{
struct node* head = start;
while(start != NULL)
{
start = start->next;//getting upto the end of the linked list
}
start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
return head;
}
void print(struct node* head)
{
while(head != NULL)
{
printf("%d\n",head->a);
head = head->next;
}
return;
}
You're losing your linkage between your tail and your new node, try this instead
struct node* insert(struct node* head,int value)
{
struct node* tail = head;
while(tail != NULL && tail->next != NULL)
{
tail= tail->next;//getting upto the end of the linked list
}
struct node* start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
else
{
tail->next = start;
}
return head;
}
struct node* insert(struct node* start,int value){
struct node* head = start;
struct node* np = (struct node*)malloc(sizeof(struct node));
np->a = value;
np->next = NULL;
if(head == NULL)
return np;
while(start->next != NULL){
start = start->next;
}
start->next = np;
return head;
}
What makes the approach I am using buggy ?
nodeX
|
+a
|
+next(address to OtherX)
nodeX.next = new_node;//update link(case of OK)
tempPointer = nodeX.next;//address to OtherX set to tempPointer
tempPointer = new_node;//contents of tempPointer changed, but orignal (nodeX.next not change)

Resources