Palindrome LinkedList - c

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>.

Related

Cannot push element to the head of the linked list

I'm trying to implement linked list in C and I've got a problem with wrong output. The first element seems not to be pushed in the head of the list.
I expect the below output in the program:
1
1
Actual output:
0
0
Have you ideas what's wrong with the code? Thanks
Problematic code:
main.c
#include <stdio.h>
#include "linked_list.h"
int main(void) {
struct ll_node *node = ll_new();
ll_push_front(node, 1);
printf("%d\n", ll_size(node)); // should print 1, actual output: 0
printf("%d\n", ll_pop_back(node)); // should print 1, actual output: 0
ll_destroy(node);
return 0;
}
linked_list.h
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <stdbool.h>
struct ll_node {
int data;
struct ll_node *prev;
struct ll_node *next;
};
struct ll_node *ll_new();
void ll_destroy(struct ll_node *node);
void ll_push_back(struct ll_node *node, int data);
void ll_push_front(struct ll_node *node, int data);
int ll_pop_back(struct ll_node *node);
int ll_pop_front(struct ll_node *node);
int ll_delete_at(struct ll_node *node, int index);
bool ll_contains(struct ll_node *node, int data);
int ll_find(struct ll_node *node, int data);
int ll_size(struct ll_node *node);
#endif //LINKED_LIST_H
linked_list.c
#include "linked_list.h"
#include <stdio.h>
#include <stdlib.h>
struct ll_node *ll_new() {
struct ll_node* node = (struct ll_node *) malloc(sizeof(struct ll_node *));
if (!node) {
fprintf(stderr, "Error: cannot allocate struct ll_node *node at ll_new");
exit(1);
}
node->prev = NULL;
node->next = NULL;
return node;
}
void ll_destroy(struct ll_node *node) {
while (node->next != NULL) {
struct ll_node *elem = node;
node = node->next;
free(elem);
}
}
void ll_push_back(struct ll_node *node, int data) {
while (node->next != NULL) {
node = node->next;
}
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node *));
current->data = data;
current->next = NULL;
current->prev = node;
node->next = current;
}
void ll_push_front(struct ll_node *node, int data) {
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node *));
current->data = data;
current->next = node;
current->prev = NULL;
node->prev = current;
}
int ll_pop_back(struct ll_node *node) {
struct ll_node *current = node;
while (current->next != NULL) {
current = current->next;
}
int old_data = current->data;
free(current);
return old_data;
}
int ll_pop_front(struct ll_node *node) {
// TODO: implement this
}
int ll_delete_at(struct ll_node *node, int index) {
// TODO: implement this
}
bool ll_contains(struct ll_node *node, int data) {
while (node->next != NULL) {
if (node->data != data) {
return false;
}
node = node->next;
}
return true;
}
int ll_find(struct ll_node *node, int data) {
// TODO: implement this
}
int ll_size(struct ll_node *node) {
int size = 0;
while (node->next != NULL) {
++size;
node = node->next;
}
return size;
}
When you push something on to the front of a list, don't you need to return a pointer to the new list?
Surely this code should be changed to return a pointer to current.
void ll_push_front(struct ll_node *node, int data) {
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node *));
current->data = data;
current->next = node;
current->prev = NULL;
node->prev = current;
}
Then in the calling function, you should be reading that result and storing it as the new list, I think?
struct ll_node *node = ll_new(); allocates a new node (let's call it root), obviously, but then you push a new node into front (let's call it node(1):
root->next = NULL
root->prev = node(1)
node(1)->next = root
node(1)->prev = NULL
In main() node * still points to root, and indeed, it's next pointer is NULL, so ll_size() returns 0. You probably want to return the new root node and do this in main() or pass in the node as struct ll_node ** so you can update it.
node = ll_push_front(node, 1);
Prefer to use the variable rather than type for allocations, and don't cast the void * pointer:
struct ll_node *current = malloc(sizeof *current);
This also fixes the defect of allocating size of a pointer but you require size of the object.
You have a ll_new() function but but ll_push_front() and ll_push_back() implements the same thing again. You should refactor the latter two to use ll_new().
It's not necessarily wrong just confusing that you use struct ll_node to both represent a node of your linked list, and the entire linked list. The root node, for instance, has uninitialized data.
You will need to make similar changes to ll_pop_back(), and you need to update all the relevant pointers.
What should ll_pop_back() do if the list is empty?
ll_destroy() doesn't free the current node.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct ll_node {
int data;
struct ll_node *prev;
struct ll_node *next;
};
struct ll_node *ll_new() {
struct ll_node* node = malloc(sizeof *node);
if (!node) {
fprintf(stderr, "Error: cannot allocate struct ll_node *node at ll_new");
exit(1);
}
return node;
}
void ll_push_front(struct ll_node **root, int data) {
if(!root) {
printf("root must be non-NULL");
exit(1);
}
struct ll_node *current = ll_new();
current->data = data;
current->prev = NULL;
current->next = *root;
if(*root)
(*root)->prev = current;
*root = current;
}
int ll_pop_back(struct ll_node **root) {
if(!root) {
printf("root must be non-NULL");
exit(1);
}
if(!*root) {
printf("*root must be non-NULL");
exit(1);
}
struct ll_node *current = *root;
while (current->next != NULL) {
current = current->next;
}
int data = current->data;
if(current->prev)
current->prev->next = NULL;
else
*root = NULL;
free(current);
return data;
}
int ll_size(struct ll_node *node) {
size_t n = 0;
for(; node; node = node->next, n++);
return n;
}
void ll_destroy(struct ll_node *root) {
while(root) {
struct ll_node *tmp = root->next;
free(root);
root = tmp;
}
}
int main(void) {
struct ll_node *root = NULL;
ll_push_front(&root, 'a');
ll_push_front(&root, 'b');
printf("%d\n", ll_size(root));
printf("%c\n", ll_pop_back(&root));
printf("%d\n", ll_size(root));
printf("%c\n", ll_pop_back(&root));
printf("%d\n", ll_size(root));
ll_destroy(root);
}
and the resulting output:
2
a
1
b
0
sizeof (struct node *) != sizeof (struct node):
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node *));
only allocates memory for the pointer, which will likely be 8 bytes on a 64-bit machine or 4 bytes on a 32-bit machine.
Change it to:
struct ll_node *current = malloc (sizeof *current);
Note that the cast is redundant and may hide a bug. There's an implicit conversion to and from a void *.
One advice I see most often on codereview.com is to allocate based on the size of what an object points to rather than the object type itself. This eases maintainability.
The function is also discarding the return value of malloc(). malloc() returns NULL to indicate failure. I'd suggest returning a bool type for ll_push_front(), true would indicate success, and false can indicate a memory allocation failure.
Changes to local parameters are never reflected back in the caller's memory:
The first element seems not to be pushed in the head of the list.
Your push function is very close to being correct. Remember that C has pass-by-value semantics and pointers are not exempt to that rule. As is, your push function only changes its local copy of head. This change will not be reflected back in the main() function. We need the push function to be able to change the caller's memory. The traditional method to allow a function to change it's caller memory is to pass a pointer to the caller's memory instead of a copy.
So instead of:
struct node *head = /* some value */;
push_node (head, /* some value */);
We pass a pointer to the head pointer, so the changes made to the head pointer in the push function are reflected back in main().
push_node (&head, /* some value */);
And dereference the pointer in the push function to access the caller's memory.
There are other issues in your code. I'd suggest implementing a singly linked list before moving on to this.
For starters within the function ll_new there is incorrectly allocated memory for a node of the list.
struct ll_node* node = (struct ll_node *) malloc(sizeof(struct ll_node *));
Instead you need to write either
struct ll_node* node = (struct ll_node *) malloc(sizeof(struct ll_node ));
or
struct ll_node* node = (struct ll_node *) malloc(sizeof( *node ));
The function does not make a great sense because it does not initialize the data member data of the created node.
The same problem with allocation memory exists also in the function ll_push_front
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node *));
Again you need to write either
struct ll_node *current = (struct ll_node *) malloc(sizeof(struct node ));
or
struct ll_node *current = (struct ll_node *) malloc(sizeof( *current ));
Actually everywhere in the code you are using incorrect expressions in calls of malloc.
Also the function does not change the pointer to the head node of the list.
It only sets its data member prev to the newly created node
As a result the function ll_size will always return 0 because the data member next of the node pointed to by the pointer node declared in main is equal to NULL
int ll_size(struct ll_node *node) {
int size = 0;
while (node->next != NULL) {
++size;
node = node->next;
}
return size;
}
The function ll_push_back can invoke undefine behavior if a null pointer is passed to the function due to this while loop within teh function
while (node->next != NULL) {
node = node->next;
}
The function ll_pop_back again does not check whether a null pointer is passed
while (current->next != NULL) {
current = current->next;
}
Also if the list contains only one node then the function does not change the passed pointer. The node will be deleted by the pointer that points to the deleted node will stay unchanged.
Or the function ll_destroy does not free all the allocated memory
void ll_destroy(struct ll_node *node) {
while (node->next != NULL) {
struct ll_node *elem = node;
node = node->next;
free(elem);
}
}
leaving the last node in the list undeleted that results in a memory leak due to the condition in the while loop
while (node->next != NULL) {
Your code contains many errors. You need to rewrite it. Start from this declaration in main
struct ll_node *head = NULL;
and try to write at first the function ll_push_front that adds one node to the empty list.
The list shall not have a dummy node.
Pay attention to that it would be better to declare one more structure like for example
struct linked_list {
size_t size;
struct ll_node *head;
struct ll_node *tail;
};
that will indeed specify the double-lonked list.
In this case there will be much efficient to add new nodes to teh tail of the list or to determine the size of the list.
You could define a list in main like
struct linked_list list = { .size = 0, .head = NULL, .tail = NULL };
And a function that adds a node to the beginning of the list could look like
int ll_push_front( struct linked_list *list, int data );
The function can be defined the following way
int ll_push_front( struct linked_list *list, int data )
{
struct ll_node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node_>data = data;
new_node->next = list->head;
new_node->prev = NULL;
if ( list->head != NULL )
{
list->head->prev = new_node;
}
else
{
list->tail = new_node;
}
list->head = new_node;
++list->size;
}
return success;
}
And the function is called in main like for example
ll_push_front( &list, 1 );
or
if ( !ll_push_front( &list, 1 ) )
{
puts( "Error: not enough memory!" );
}
In turn the function ll_push_back can look the following way
int ll_push_back( struct linked_list *list, int data )
{
struct ll_node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node_>data = data;
new_node->next = NULL;
new_node->prev = list->tail;
if ( list->tail != NULL )
{
list->tail->next = new_node;
}
else
{
list->head = new_node;
}
list->tail = new_node;
++list->size;
}
return success;
}
To get the size of the list you can write for example
size_t ll_size( const struct linked_list *list )
{
return list->size;
}

Pointer to beginning of linked list

I am practicing linked list structure while learning pointers and I have problem with appending item in list. Here is my code
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node {
int data;
node_t* next;
};
void append(node_t *head, int data) {
if (head == NULL) {
node_t *node = (node_t*)malloc(sizeof(node_t*));
node->data = data;
node->next = NULL;
head = node;
} else {
node_t *node = (node_t*)malloc(sizeof(node_t*));
node->data = data;
node->next = NULL;
if (head->next == NULL) {
head->next = node;
} else {
node_t *current = head;
while (1) {
if (current->next == NULL) {
current->next = node;
break;
}
current = current->next;
}
}
}
}
int main(void) {
node_t *head = NULL;
append(head, 4);
append(head, 6);
printList(head);
return 0;
}
My code breaks when I do head = node; It doesn't change value of head in main. I think I'm missing something but not sure what.
Thank you in advance
You are passing the pointer head by value in the function append. So the function deals with a copy of the passed to it pointer. Changing the copy does not influence on the original pointer. Either pass it by reference or return updated head from the function.
The first approach is much better.
The function can look the following way
int append( node_t **head, int data )
{
node_t *node = malloc( sizeof( node_t ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node
{
int data;
node_t *next;
};
int append( node_t **head, int data )
{
node_t *node = malloc( sizeof( node_t ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
void printList( node_t *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main(void)
{
node_t *head = NULL;
const int N = 10;
for ( int i = 0; i < N; i++ )
{
append( &head, i );
}
printList( head );
return 0;
}
Its output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
It seems the problem is you are passing the head pointer by value, so when you change it inside append(), you're only changing a local variable in that function - as opposed to the head variable within main().
This may be a bit confusing - if you pass a pointer, how can you be passing by value? Well, you might want to have a look at this question:
Is passing pointer argument, pass by value in C++?
... and the bottom line is that append() needs to take a node_t** head, and you'll call it from main with append(&head, 4);. See it working on Coliru.
Also you're allocating sizeof(node_t*) per node. You should be allocating sizeof(node_t).
It doesn't change value of head in main
Nor should it! If the value of head in main changed when you call append(), then your call to printList() would only print the last node in the list, and you'd have no way to refer to the other nodes in the list.
The reason that head isn't changed has been well explained in other answers, i.e. you're passing the head pointer by value. It's important to understand that the head in main() and the head parameter in append() are entirely different variables.
You pass the head of the list by value, so the append function cannot update the pointer in the caller's space, that happens to have the same name head. The head argument in append is a separate variable from the head local variable in main.
You should either pass a pointer to the head node so append can modify it:
void append(node_t **headp, int data) { ...
Or return the possibly modified head node to the caller which will store it back to its own variable:
node_t *append(node_t *head, int data) { ...
In both cases, it is advisable to signal memory allocation failure to the caller. Returning an error code in the first approach is easy, while returning a null pointer in the second approach can work, as long as the caller does not store the return value directly into its head variable, as in case of failure the previous value would be lost.
Here is a modified version with the first approach:
#include <stdio.h>
#include <stdlib.h>
typedef struct node node_t;
struct node {
int data;
node_t *next;
};
// append a new node to the list, return 0 for success, -1 for allocation failure
int append(node_t **headp, int data) {
node_t *node = (node_t *)malloc(sizeof(node_t *));
if (node == NULL)
return -1;
node->data = data;
node->next = NULL;
if (*headp == NULL) {
*headp = node;
} else {
node_t *current = *headp;
while (current->next != NULL) {
current = current->next;
}
current->next = node;
}
return 0;
}
int main(void) {
node_t *head = NULL;
if (append(&head, 4) || append(&head, 6))
printf("node allocation error\n");
printList(head);
// should free the list
return 0;
}

What is wrong in the stack implementation using linked lists?

I am trying to implement a stack using linked list. Here is my code:
#include<stdio.h>
//implementation of stack
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct Stack{
struct Node* headNode;
struct Node* presentNode;
int size;
};
struct Node* newNode()
{
struct Node* node;
return node;
}
struct Stack* newStack()
{
struct Stack* stack;
stack->headNode = newNode();
stack->presentNode = stack->headNode;
stack->size=0;
return stack;
}
int isempty(struct Stack* s)
{
if(s->headNode->next != NULL)
return 0;
return 1;
}
void push(struct Stack* s,int data)
{
struct Node* node = newNode();
node->data = data;
node->next = NULL;
s->presentNode->next = node;
node->prev = s->presentNode;
s->presentNode = node;
s->size ++;
}
int pop(struct Stack*s)
{
if(isempty(s)==1)
return 0;
int data = s->presentNode->data;
s->presentNode->prev->next = NULL;
s->presentNode = s->presentNode->prev;
s->size --;
return data;
}
int main()
{
struct Stack* stack = newStack();
int data = 0,type;
printf("Enter '1' if new element to be added or '0' if the latest element is to be deleted.\n");
while(data!=-1)//unbounded stack
//takes input until data==-1
{
scanf("%d",&type);
if(type)
{
printf("Enter the element:\t");
scanf("%d",&data);
if(data==-1)
continue;
push(stack,data);
}
else
printf("%d is popped out of the list!\n",pop(stack));
}
return 0;
}
But I am getting run-time error. Since I am new to pointers (I am a Java guy), I am pretty confused where my error is, although I am sure it is due to pointers.
You do not allocate memory for your new nodes:
struct Node* newNode()
{
struct Node* node;
return node;
}
Local variable node is an uninitialized pointer. As soon as you use the return value of this function, you have Undefined Behaviour.
Edit:
The same problem is true for newStack:
struct Stack* newStack()
{
struct Stack* stack;
stack->headNode = newNode();
...
return stack;
}
As soon as you dereference stack, you have Undefined Behaviour.
You have multiple problems. For starters
In your newStack() function, you do not have a return statement, so using the return value causes undefined behavior.
You need to allocate memory to pointers (i.e., make pointers to point to valid memory) before you can actually dereference them. In your case
struct Stack* stack;
stack->headNode
is an attempt to use uninitialized memory which again causes UB.

Binary search tree - Iterative check for height

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

What is wrong with my code for singly linked list?

I'm working on a singly linked list in C. This is what I've written so far.
C program
#include<stdio.h>
#include<stdlib.h>
struct Node{
int value;
struct Node *next;
};
struct Node* init()
{
struct Node* head=NULL;
head=malloc(sizeof(struct Node));
head->value=-1;
return head;
}
int length(struct Node* head)
{
struct Node* current=head;
int length=0;
while(current!=NULL)
{
length++;
current=current->next;
}
return length;
}
void print(struct Node* head)
{
int i=0;
int len=length(head);
for(i=0;i<len;i++)
{
printf("%d%d",i,head[i].value);
printf("\n");
}
}
struct Node* insert(int data,struct Node* head)
{
struct Node* current=NULL;
if(length(head) > 0)
{
int val=head->value;
if (val==-1)
{
head->value=data;
head->next=NULL;
}
else
{
current=malloc(sizeof(struct Node));
current->value=data;
current->next=head;
head=current;
}
}
else
{
printf("List is empty");
}
return head;
}
int main()
{
/* printf("Hello"); */
struct Node *head=init();
head=insert(20,head);
head=insert(30,head);
head=insert(40,head);
print(head);
printf("%d",length(head));
return 0;
}
The output values I get are:
Index Value
0 40
1 0
2 0
and for length is 3. I'm not able to grasp what I'm doing wrong here in pointer manipulation.
One obvious problem is not setting next to NULL on init - that would fail when checking length on the empty list
But your real problem is the print function
You can't use:
head[i].value
That notation is only valid for arrays, you need to use next to find each member
The Init function should set Next to NULL
struct Node* init()
{
struct Node* head=NULL;
head=malloc(sizeof(struct Node));
head->value=-1;
head->next=NULL;
return head;
}
otherwise the first call to length return an undefined result ( or GPF ).
Here:
for (i = 0; i < len; i++)
{
printf("%d%d", i, head[i].value);
printf("\n");
}
You need to advance from one node to another with head = head->next in the same manner as you do it in length(). head[i] won't do it.
It's unclear why your init() and insert() are so unnecessarily complicated and I don't even want to try to guess why. I want to suggest a better insert() and no init():
struct Node* insert(int data, struct Node* head)
{
struct Node* current;
current = malloc(sizeof(struct Node));
current->value = data;
current->next = head;
return current;
}
And then you do this:
int main(void)
{
struct Node *head = NULL;
head = insert(20, head);
head = insert(30, head);
head = insert(40, head);
print(head);
printf("%d", length(head));
return 0;
}
The notation head[i].value is only valid for arrays but not for linked lists. Arrays and linked lists are completely different, allocation of memory towards arrays is premeditated where as for linked lists it's dynamic. That is the reason why we use pointers for linked lists.
In init() you didn't assign null which causes the loop to run infinite times when you call length() for first time.
I am posting the modified code of print function:
void print(struct Node* head)
{
int i=0;
int len=0;
struct Node* current=head;
for(i=0;i<len;i++)
{
printf("%d %d",i,current->value);
print("\n");
current=current->next;
}
}

Resources