I am trying to write a function, which is deleting a specific element from my linked list, but it crash with segmentation fault when I reach the element.
Here is a part of my code
typedef struct dlist_t {
int data;
struct dlist_t *prev, *next;
} dlist_t;
typedef struct list_t {
dlist_t *head, *tail;
} list_t;
int delElement(list_t *list, int elem) {
while (list) {
if ((list->head)->data == elem) {
list->head->next = list->head->prev;
list->head->prev = list->head->next;
free(list);
return 1;
}
list = list->head->next;
}
return 0;
}
Your function definition does not make sense. For example in this assignment statement
list = list->head->next;
there are used objects of different types in the left hand side of the assignment (the type is list_t) and in the right hand side of the assignment (the type is dlist_t).
Or this call
free(list);
tries to free the list instead of only its one node. And so on.
The function can look the following way as it is shown in thje demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct dlist_t
{
int data;
struct dlist_t *prev, *next;
} dlist_t;
typedef struct list_t
{
dlist_t *head, *tail;
} list_t;
int delElement( list_t* list, int elem )
{
dlist_t **current = &list->head;
while ( *current != NULL && ( *current )->data != elem )
{
current = &( *current )->next;
}
int success = *current != NULL;
if ( success )
{
dlist_t *tmp = *current;
if ( ( *current )->next != NULL )
{
( *current )->next->prev = ( *current )->prev;
}
else
{
list->tail = ( *current )->prev;
}
*current = ( *current )->next;
free( tmp );
}
return success;
}
int pushFront( list_t *list, int elem )
{
dlist_t *new_node = malloc( sizeof( dlist_t ) );
int success = new_node != NULL;
if ( success )
{
new_node->next = list->head;
new_node->prev = NULL;
new_node->data = elem;
if ( list->head != NULL )
{
list->head->prev = new_node;
}
else
{
list->tail = new_node;
}
list->head = new_node;
}
return success;
}
int pushBack( list_t *list, int elem )
{
dlist_t *new_node = malloc( sizeof( dlist_t ) );
int success = new_node != NULL;
if ( success )
{
new_node->prev = list->tail;
new_node->next = NULL;
new_node->data = elem;
if ( list->tail != NULL )
{
list->tail->next = new_node;
}
else
{
list->head = new_node;
}
list->tail = new_node;
}
return success;
}
void printList( list_t *list )
{
for ( dlist_t *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
void printReverseList( list_t *list )
{
for ( dlist_t *current = list->tail; current != NULL; current = current->prev )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
list_t list = { .head = NULL, .tail = NULL };
const int N = 10;
for ( int i = 0; i < N; i++ )
{
if ( i % 2 == 0 ) pushFront( &list, N / 2 - i / 2 - 1 );
else pushBack( &list, N / 2 + i / 2 );
}
printList( &list );
printReverseList( &list );
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
if ( i % 2 == 0 ) delElement( &list, i / 2 );
else delElement( &list, N - i / 2 - 1 );
printList( &list );
printReverseList( &list );
putchar( '\n' );
}
return 0;
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> null
3 -> 4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> 3 -> null
4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> null
4 -> 5 -> null
5 -> 4 -> null
5 -> null
5 -> null
null
null
Play with the program and playing investigate it.
Do not forget to write yourself the function that frees all allocated nodes in the list.
Im not too sure what causes your crash yet, but here i have a sample of code that should work.
Struct definition:
typedef int item_type;
typedef struct _list* list;
struct node {
item_type data;
struct node *next,*prev;
};
struct _list {
struct node* head;
struct node* tail;
int size;
};
Function for "element" deletion
void list_del(list l,item_type data) {
if (list->size ==0) {
abort();
}
int i=0;
struct node* head = l->head;
while(i<list->size){
if(head->data==data){
head->prev = head->next;
l->size -= 1;
free(head);
return;
}else{
head=head->next;
}
}
}
"item_type" it's a typedef, if you have lots of functions and you shouldn't care much about types. In our example is as you wanted type int
don't worry just try this code out.This is simplest of implementation and deletion a node in linked list and still if you face any issue feel free to ask .
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
}*first=NULL;
void create(int A[],int n)
{
int i;
struct Node *t,*last;
first=(struct Node *)malloc(sizeof(struct Node));
first->data=A[0];
first->next=NULL;
last=first;
for(i=1;i<n;i++)
{
t=(struct Node*)malloc(sizeof(struct Node));
t->data=A[i];
t->next=NULL;
last->next=t;
last=t;
}
}
void Display(struct Node *p)
{
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
}
void RDisplay(struct Node *p)
{
if(p!=NULL)
{
RDisplay(p->next);
printf("%d ",p->data);
}
}
int Delete(struct Node *p,int index)
{
struct Node *q=NULL;
int x=-1,i;
if(index < 1 || index > count(p))
return -1;
if(index==1)
{
q=first;
x=first->data;
first=first->next;
free(q);
return x;
}
else
{
for(i=0;i<index-1;i++)
{
q=p;
p=p->next;
}
q->next=p->next;
x=p->data;
free(p);
return x;
}
}
int main()
{
int A[]={10,20,30,40,50};
create(A,5);
printf(“%d\n",Delete(first),2);
Display(first);
return 0;
}
So first we have created the linked list using malloc function . We have created a structure with variable which will build linked list i.e "data" and also created the pointer of struct type .
Then we have created a function name "create" to create our first node .And inserted the value according to it .
Then as you can see we g=have used for loop to fasten the process of creating the link list till the value of n.
Then for displaying the linked list we have created the function name "Display"
and if p!=NULL i.e node last column which contain address we have print the values/data of that node using for loop.
Then for deletion we have used function name "Delete" :
1st step: Is we need a pointer "p" that will point on first node .
2nd step: Now move first to next node.
3rd step: Now store the value of deleted node in new variable "x".
4th step: Delete p
The remaining code is for deleting the node from the specific position by using the two pointer, one pointer for previous node and next pointer for current node.
Just try this out or cross check with your code where you are going wrong .
Related
Update: we believe to find some bugs in both solutions , you are invited to share your ideas too :)
I was trying to implement my own data structure which combines list with queue in C.
my data structure has 2 pointers, front which points to the oldest member in the queue and rear which points to the newly added member which each member points to the one which got inserted after it.
For example if I insert 1 then 2 then 3, I will have:
NULL <-3 <- 2 <- 1 // 1 is front and 3 is rear.
Now I wanted to support removing element from this DS so I starting imeplemnting it and descovvered tens of edge cases like:
if the member is the front then change the front for DS and free the member, BUT if the front is null now then change rear to null too or the other code won't work as expected.
if the member is in middle release it then go back to prev member and update its next But this seems really hard
nearly the same for the rear member except we need to update rear now and only change the pointer to the element to its right (NULL is to its left)
How am I supposed to do something like this?
I already had tens of ideas and implementation for days but simply all failed or I did something really bad making the run time complexity much higher or I wrote 170 lines which had contradictions and left unfinished conditions (by using 2 pointers).
Any help please implementing this?
struct queue_node
{
int key;
struct queue_node *next;
};
struct queue
{
int queue_size;
struct queue_node *front, *rear;
};
int requeue(struct queue *q, int val)
{
struct queue_node *tmp = q->front;
while (tmp!=NULL)
{
if (tmp->key==val)
{
if (tmp==q->front)
{
q->front=tmp->next;
if (q->front == NULL)
{
q->rear = NULL;
}
free(tmp);
}else if (tmp == q->rear)
{
}
return 0; // found
}
tmp=tmp->next;
}
return -1; // not found
}
typedef struct queue_node
{
int key;
struct queue_node *next;
}node;
typedef struct
{
size_t size;
node *head;
node *tail;
}queue;
node *append(queue *q, int key)
{
node *n = malloc(sizeof(*n));
node *c = q -> head;
if(n)
{
if(!q -> head) q -> head = n;
else
{
while(c -> next) c = c -> next;
c -> next = n;
}
n -> key = key;
n -> next = NULL;
q -> size++;
q -> tail = n;
}
return n;
}
int removenode(queue *q, int key)
{
node *n = q -> head, *p = q -> head;
int result = 0;
while(n)
{
if(n -> key == key)
{
if(n == p)
{
q -> head = n -> next;
if(!n -> next) q -> tail = n;
}
else
{
p -> next = n -> next;
if(!p -> next) q -> tail = p;
}
free(n);
q -> size--;
result = 1;
break;
}
if(p != n) p = p -> next;
n = n -> next;
}
return result;
}
void printqueue(queue *q)
{
node *n = q -> head;
printf("The queue:\n");
while(n)
{
printf("Node key = %d\n", n -> key);
n = n -> next;
}
printf("--------------\n");
if(q -> head) printf("Head key: %d, Tail key: %d, Queue size: %zu\n -------------\n\n", q -> head -> key, q -> tail -> key, q -> size);
else printf("Queue empty\n------------\n\n");
}
int main(void)
{
queue q = {0,};
append(&q,1);
append(&q,2);
append(&q,3);
append(&q,4);
printqueue(&q);
removenode(&q,3);
printqueue(&q);
removenode(&q,1);
printqueue(&q);
removenode(&q,4);
printqueue(&q);
removenode(&q,2);
printqueue(&q);
}
Result:
The queue:
Node key = 1
Node key = 2
Node key = 3
Node key = 4
--------------
Head key: 1, Tail key: 4, Queue size: 4
-------------
The queue:
Node key = 1
Node key = 2
Node key = 4
--------------
Head key: 1, Tail key: 4, Queue size: 3
-------------
The queue:
Node key = 2
Node key = 4
--------------
Head key: 2, Tail key: 4, Queue size: 2
-------------
The queue:
Node key = 2
--------------
Head key: 2, Tail key: 2, Queue size: 1
-------------
The queue:
--------------
Queue empty
------------
Program demo
The function can be defined the following way
int requeue( struct queue *q, int val )
{
struct queue_node **current = &q->front;
struct queue_node *prev = NULL;
while ( *current && ( *current )->key != val )
{
prev = *current;
current = &( *current )->next;
}
int success = *current == NULL ? -1 : 0;
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct queue_node
{
int key;
struct queue_node *next;
};
struct queue
{
int queue_size;
struct queue_node *front, *rear;
};
int requeue( struct queue *q, int val )
{
struct queue_node **current = &q->front;
struct queue_node *prev = NULL;
while ( *current && ( *current )->key != val )
{
prev = *current;
current = &( *current )->next;
}
int success = *current == NULL ? -1 : 0;
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
return success;
}
int push( struct queue *q, int key )
{
struct queue_node *node = malloc( sizeof( struct queue_node ) );
int success = node != NULL;
if ( success )
{
node->key = key;
node->next = NULL;
if ( q->rear == NULL )
{
q->front = q->rear = node;
}
else
{
q->rear = q->rear->next = node;
}
++q->queue_size;
}
return success;
}
void display( const struct queue *q )
{
for ( struct queue_node *current = q->front; current; current = current->next )
{
printf( "%d -> ", current->key );
}
puts( "null" );
}
int main(void)
{
struct queue q = { .front = NULL, .rear = NULL };
push( &q, 1 );
push( &q, 2 );
push( &q, 3 );
push( &q, 4 );
display( &q );
requeue( &q, 4 );
display( &q );
push( &q, 4 );
display( &q );
requeue( &q, 1 );
display( &q );
requeue( &q, 3 );
display( &q );
requeue( &q, 4 );
display( &q );
requeue( &q, 2 );
display( &q );
push( &q, 1 );
push( &q, 2 );
push( &q, 3 );
push( &q, 4 );
display( &q );
return 0;
}
The program output is
1 -> 2 -> 3 -> 4 -> null
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
2 -> 3 -> 4 -> null
2 -> 4 -> null
2 -> null
null
1 -> 2 -> 3 -> 4 -> null
If for testing to add a call of the function printf to this code snippet within the function requeue
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
printf( "tmp->key == %d, tmp == %p\n", tmp->key, ( void * )tmp );
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
Then the output of the demonstrative program can look like
1 -> 2 -> 3 -> 4 -> null
tmp->key == 4, tmp == 0x55b55f9e02c0
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
tmp->key == 1, tmp == 0x55b55f9e0260
2 -> 3 -> 4 -> null
tmp->key == 3, tmp == 0x55b55f9e02a0
2 -> 4 -> null
tmp->key == 4, tmp == 0x55b55f9e02c0
2 -> null
tmp->key == 2, tmp == 0x55b55f9e0280
null
1 -> 2 -> 3 -> 4 -> null
I have an assignment to do.. the task is to delete only the first occurrence of an odd value in a doubly linked list, and I have to take in consideration all the special cases such as: if odd # beginning, middle or last. so far, my code works fine i checked it out, its work with deleting the front only (if its odd), but in the other cases such as deleting the last/ middle.. I couldn't manage to get an output for them. basically the running command shows me nothing :(
int DeleteFirstODD(Node **front) {
int oddnum;
Node *temp = *front;
if (*front == NULL) //Checking if the list is empty
return;
while (temp != NULL && temp->data % 2 == 0)
temp = temp->next;
if (temp == NULL)
return -1;
else if (temp == *front) { //if odd num founded # the begining of the doubly linked list!
oddnum = (*front)->data;
*front = (*front)->next;
(*front)->previous = NULL;
free(temp);
}
else if (temp->next == NULL) { //if odd num founded # the end
oddnum = temp->data;
temp->previous->next = NULL;
free(temp);
}
else { // if the odd somewhere in the middle
temp->previous->next = temp->next;
temp->next->previous = temp->previous;
oddnum = temp->data;
free(temp);
}
return oddnum;
}
my code works fine i checked it out, its work with deleting the front
only
You are wrong. This code snippet
else if (temp == *front) { //if odd num founded # the begining of the doubly linked list!
oddnum = (*front)->data;
*front = (*front)->next;
(*front)->previous = NULL;
free(temp);
}
can invoke undefined behavior when the list contains only one node because after this statement
*front = (*front)->next;
the pointer front will be equal to NULL and you may not use this null pointer in the following statement
(*front)->previous = NULL;
The function can be defined the following way. I suppose that if such a node with an odd value is found when the stored value is returned. Otherwise -1 is returned.
int DeleteFirstODD( Node **front )
{
int oddnum = -1;
Node *temp = *front;
while ( temp != NULL && temp->data % 2 == 0 )
{
temp = temp->next;
}
if ( temp != NULL )
{
oddnum = temp->data;
if ( temp == *front )
{
if ( temp->next != NULL )
{
temp->next->previous = temp->previous;
}
*front = temp->next;
}
else if ( temp->next == NULL )
{
temp->previous->next = temp->next;
}
else
{
temp->previous->next = temp->next;
temp->next->previous = temp->previous;
}
free( temp );
}
return oddnum;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
struct Node *previous;
} Node;
int push_front( Node **head, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = *head;
if ( *head ) ( *head )->previous = new_node;
new_node->previous = NULL;
*head = new_node;
}
return success;
}
void display( const Node *head )
{
for ( ; head; head= head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int DeleteFirstODD( Node **front )
{
int oddnum = -1;
Node *temp = *front;
while ( temp != NULL && temp->data % 2 == 0 )
{
temp = temp->next;
}
if ( temp != NULL )
{
oddnum = temp->data;
if ( temp == *front )
{
if ( temp->next != NULL )
{
temp->next->previous = temp->previous;
}
*front = temp->next;
}
else if ( temp->next == NULL )
{
temp->previous->next = temp->next;
}
else
{
temp->previous->next = temp->next;
temp->next->previous = temp->previous;
}
free( temp );
}
return oddnum;
}
int main(void)
{
Node *head = NULL;
const int N = 10;
for ( int i = N; i != 0; i-- )
{
push_front( &head, i );
}
display( head );
for ( int num; ( num = DeleteFirstODD( &head ) ) != -1; )
{
printf( "The value of the deleted node is %d\n", num );
display( head );
}
return 0;
}
The program output is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The value of the deleted node is 1
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The value of the deleted node is 3
2 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The value of the deleted node is 5
2 -> 4 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The value of the deleted node is 7
2 -> 4 -> 6 -> 8 -> 9 -> 10 -> null
The value of the deleted node is 9
2 -> 4 -> 6 -> 8 -> 10 -> null
I have a singly linked list where I get the struct Node* head, and the return value is void. I'd like to swap in pairs without copying the data.
For example, if the input is 2->4->6 then the output is 4->2->6. But if the input is 2->4->6->7 then the output is 4->2->7->6.
Here is my code but it doesn't work.
void swapPairs(struct Node *head) {
struct Node *node;
while (head && head->next) {
struct Node *nxt = head->next;
head->next = nxt->next;
nxt->next = head;
node->next = nxt;
node = head;
head = node->next;
}
}
You need to pass the pointer to the head (or current) node by reference. Otherwise the function will deal with a copy of the value of the passed pointer. Changing the copy does not influence on the original pointer.
Here is a demonstrative program that shows how a function that swaps adjacent nodes can be written.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0)
{
struct Node *new_node = ( struct Node * )malloc( sizeof( struct Node ) );
new_node->next = head;
new_node->data = data;
head = new_node;
}
else
{
head->next = insert( head->next, pos - 1, data );
}
return head;
}
FILE * display( const struct Node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null\n", fp );
return fp;
}
void swap( struct Node **current )
{
/*
| A | -> | A | B | -> | B | C |
head
Step 1:
| B | | A | C | | B | C |
head
Step 2:
| B | | A | C | | B | A |
head
*/
// Step 1:
struct Node *tmp = *current;
*current = ( *current )->next;
tmp->next = ( *current )->next;
// Step 2:
( *current )->next = tmp;
}
void swapPairs( struct Node **head )
{
for ( ; *head && ( *head )->next; head = &( *head )->next->next)
{
swap( head );
}
}
int main()
{
struct Node *head = NULL;
const int N = 10;
srand( ( unsigned int )time( NULL ) );
for ( int i = 0; i < N; i++ )
{
head = insert( head, rand() %( i + 1 ), rand() % N );
}
fputc( '\n', display( head, stdout ) );
swapPairs( &head );
fputc( '\n', display( head, stdout ) );
}
The program output might look like
4 -> 7 -> 8 -> 1 -> 4 -> 8 -> 9 -> 0 -> 4 -> 6 -> null
7 -> 4 -> 1 -> 8 -> 8 -> 4 -> 0 -> 9 -> 6 -> 4 -> null
I am trying to perform Insertion Sort on linked list in C using following function, it gets stuck in a infinite loop. I debugged the code and found out that it works for the first pass and gets stuck in infinite loop in the second pass.
void insertion_sort()//Insertion Sort function
{
struct Node *p = root->next;
struct Node *a = NULL, *b = NULL;
while(p != NULL)
{
a = root;
while(a != p)
{
b = a;
a = a->next;
}
if(b != NULL)
b->next = a->next;
a->next = NULL;
struct Node *q = root;
struct Node* r = NULL;
while(p->data > q->data)
{
r = q;
q = q->next;
}
p->next = q;
if(r != NULL)
r->next = p;
p = p->next;
}
}
For starters it is a bad idea when a function depends on a global variable. In case of your program it means for example that you can not have two lists in one program.
I do not see where the pointer root is changed in the function insertion_sort. So even if all other code is valid nevertheless the function is incorrect because it does not change the pointer root when the value of the pointed node is unordered.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
};
int push_front( struct Node **head, int data )
{
struct Node *node = malloc( sizeof( struct Node ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = *head;
*head = node;
}
return success;
}
void insertion_sort( struct Node **head )
{
for ( struct Node **current = head; *current != NULL; )
{
struct Node **sorted = head;
while ( *sorted != *current && !( ( *current )->data < ( *sorted )->data ) )
{
sorted = &( *sorted )->next;
}
if ( *sorted != *current )
{
struct Node *tmp = *current;
*current = ( *current )->next;
tmp->next = *sorted;
*sorted = tmp;
}
else
{
current = &( *current )->next;
}
}
}
FILE * output( struct Node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int main(void)
{
enum { N = 13 };
struct Node *head = NULL;
srand( ( unsigned int )time( NULL ) );
for ( int i = 0; i < N; i++ )
{
push_front( &head, rand() % N );
}
fputc( '\n', output( head, stdout ) );
insertion_sort( &head );
fputc( '\n', output( head, stdout ) );
return 0;
}
The program output might look like
1 -> 12 -> 0 -> 4 -> 0 -> 12 -> 3 -> 7 -> 12 -> 2 -> 5 -> 9 -> 7 -> null
0 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 7 -> 7 -> 9 -> 12 -> 12 -> 12 -> null
hey for some reason my linked list is printing in the reversed ordear for example if my input is 2->4->6
my output is 6->4->2
list* add_int_list(list* a,int b)
{
list *temp;
temp = (list*)malloc(sizeof(list*));
temp->next = NULL;
if (a->next == NULL)//insert to the first node
{
temp->data = b;
temp->next = a;
a = temp;
}
else
{
temp->data = b;
temp->next = a;
a = temp;//I think the problem is here, couldnt find how to fix
}
For starters in this statement
temp = (list*)malloc(sizeof(list*));
^^^^^
there is allocated memory of the size equal to the size of pointer instead of the size of the node. You have to write either
temp = (list*)malloc(sizeof(list));
or
temp = (list*)malloc(sizeof( *temp));
This if statement
if (a->next == NULL)
can invoke undefined behavior because initially the list can be empty. So the pointer a can be equal to NULL. That is there is used a null pointer to access memory.
There is no difference between these two code blocks after the if and else parts of the if-else statement
if (a->next == NULL)//insert to the first node
{
temp->data = b;
temp->next = a;
a = temp;
}
else
{
temp->data = b;
temp->next = a;
a = temp;//
}
That is the both code snippet try insert a new-node in the beginning of the list.
It is a general approach to insert a new node in a singly-linked one-sided list in its beginning. To append a node to such a list to its end is inefficient because the whole list must be traversed.
If you want to append a node to the end of a singly linked list then make it two-sided.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef struct List
{
Node *head;
Node *tail;
} List;
int push_front( List *list, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = list->head;
list->head = new_node;
if ( list->tail == NULL ) list->tail = list->head;
}
return success;
}
int push_back( List *list, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( list->tail == NULL )
{
list->head = list->tail = new_node;
}
else
{
list->tail = list->tail->next = new_node;
}
}
return success;
}
void output( const List *list )
{
for ( const Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
List list = { .head = NULL, .tail = NULL };
const int N = 10;
for ( int i = 0; i < N; i++ )
{
if ( i % 2 != 0 )
{
push_front( &list, i );
}
else
{
push_back( &list, i );
}
output( &list );
}
return 0;
}
Its output is
0 -> null
1 -> 0 -> null
1 -> 0 -> 2 -> null
3 -> 1 -> 0 -> 2 -> null
3 -> 1 -> 0 -> 2 -> 4 -> null
5 -> 3 -> 1 -> 0 -> 2 -> 4 -> null
5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> null
7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> null
7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> 8 -> null
9 -> 7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> 8 -> null
In this demonstrative program even numbers are inserted in the end of the list using the function push_back and odd numbers are inserted in the beginning of the list using the function push_front.
If you C compiler does not support designated initializers then this declaration
List list = { .head = NULL, .tail = NULL };
can be changed the following way
List list = { NULL, NULL };
The problem is that your code is appending the node to the front of the list in both cases. If you want to always append to the end of the list, you need to walk the list until the end and then add temp there.
I wrote this code off-the-cuff, so take it as pseudo-code:
// Assuming this function returns the front (head) of the list.
list* append_element_to_list(list* a, int b)
{
list *newNode;
newNode = (list*)malloc(sizeof(list*));
newNode->data = b;
// Handle the case where `a` is NULL. This means
// no list was passed in, so the newly created node
// will be returned to start the list.
if (a == NULL)
{
return newNode;
}
// If we get this far, it means `a` contains at least
// one node. So walk the list until the end.
list *currentNode = a;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
}
// Once you reach the end of the list, set
// `newNode` as the last node.
currentNode->next = newNode;
// The front of the list hasn't changed, so return that.
return a;
}
You have some mistakes in your code, I am making correction in your code, just changing what required.
first I want to focus on main issue, before inserting at last of any list, you should iterate the complete list.
i = a; // to iterate
while(i->next != NULL)
{
i = i->next;
}
// Now i is last node of list a
i->next = temp;
Now the below code, I just check it on TurboC, I am using your function and inserting three values and then printing the list.
Please see all the line comments:
#include <stdio.h>
#include <malloc.h>
typedef struct node{
int data;
struct node *next;
}list;
list* add_int_list(list* a,int b)
{
list *temp;
list *i;
temp = (list*)malloc(sizeof(list*));
temp->next = NULL;
temp->data = b;
if (a == NULL)//insert to the first node
{
//temp->data = b; - done above
//temp->next = a; no reason for this line
a = temp;
}
else
{
// temp->data = b; - done above
//temp->next = a; wrong logic
// a = temp;//I think the problem is here, couldnt find how to fix : Yes it is also wrong
//Here it required to iterate complete list and go to end
i = a; // to iterate
while(i->next != NULL)
{
i = i->next;
}
// Now i is last node of list a
i->next = temp;
}
return a;
}
void printList(list *root)
{
list *i;
if(root == NULL)
{
printf("List is empty");
}
else
{
i = root;
while(i != NULL){
printf("%d,",i->data);
i = i->next;
}
}
}
int main()
{
list *root = NULL;
clrscr();
root = add_int_list(root, 3);
root = add_int_list(root, 4);
root = add_int_list(root, 5);
printList(root);
return 0;
}