Deleting and inserting nodes in a linked list behave differently (?) - c

I'm trying to learn linked lists from King (2008) "C Programming: A Modern Approach", 2nd ed and I'm puzzled by the behaviour of the deletion operation as compared to the insertion operation.
The author writes (p. 429):
Note that add_to_list doesn't modify the list pointer. Instead, it
returns a pointer to the newly created node....Getting add_to_list
to update first, turns out to be tricky.
Now while deleting the first node doesn't modify the original list, deleting nodes in the interior or the end does modify the original list. But delete_from_list is also making a copy of the first pointer, so why can it modify first (while add_to_list cannot)?
What am I missing here?
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
struct node *delete_from_list(struct node *, int);
struct node *add_to_list(struct node *, int n);
int main(int argc, char **argv) {
// setup a linked list
// list's head
struct node *first= NULL;
// first node
struct node *new_node= malloc(sizeof(struct node));
new_node->value= 10;
new_node->next= first;
first= new_node;
//second node
new_node = malloc(sizeof(struct node));
new_node->value= 20;
new_node->next= first;
first= new_node;
//third node
new_node= malloc(sizeof(struct node));
new_node->value= 40;
new_node->next= first;
first= new_node;
//fourth node
new_node= malloc(sizeof(struct node));
new_node->value= 30;
new_node->next= first;
first= new_node;
int i;
struct node *head= first;
printf("\n------------------------\n");
printf(" Original nodes: ");
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
struct node *first_no20= delete_from_list(first, 20);
struct node *head_no20= first_no20;
printf("\n------------------------\n");
printf(" Nodes without 20: ");
for(i=0; head_no20!= NULL; head_no20= head_no20->next, i++)
printf("\n%d-ith value: %d ", i,head_no20->value);
printf("\n------------------------\n");
printf("\n------------------------\n");
head=first;
printf(" Original nodes: ");
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
struct node *first_no30= delete_from_list(first, 30);
struct node *head_no30= first_no30;
printf("\n------------------------\n");
printf(" Nodes without 30: ");
for(i=0; head_no30!= NULL; head_no30= head_no30->next, i++)
printf("\n%d-ith value: %d ", i,head_no30->value);
printf("\n------------------------\n");
printf("\n------------------------\n");
printf(" Original nodes: ");
head=first;
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
return 0;
}
struct node *delete_from_list(struct node *list, int n) {
struct node *cur, *prev;
for(cur=list, prev=NULL;
cur != NULL && cur->value !=n;
prev= cur, cur= cur->next)
;
if(cur == NULL)
return list;
if(prev== NULL)
list= list->next;
else
prev->next= cur->next;
free(cur);
return list;
}
struct node *add_to_list(struct node *list, int n) {
struct node *new_node;
new_node= malloc(sizeof(struct node));
if(new_node == NULL) {
printf("Error: malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = n;
new_node->next= list;
return new_node;
}

I think that this quote
Note that add_to_list doesn't modify the list pointer. Instead, it
returns a pointer to the newly created node....Getting add_to_list to
update first, turns out to be tricky.
denotes the following.
When a new node is added to the list then all pointers to nodes (as for example the passed pointer and values of the data member next) that already exist in the list are not changed.
On the other hand, when a node is deleted then pointers to nodes (as for example the pointer that points to the deleted node or the value of the data member next of the preceding node) can be changed.

Having tried, in the comments under the OP, to teach that the plethora of pointers in the OP code was the source of the problem, there is little else one can do but demonstrate the correct use of ONE pointer to the first node of the evolving LL (and one useful pointer that can traverse the LL.)
Here is the main() function written to perform the apparently desired task.
int main( void ) {
struct node *first = NULL;
struct node *p = NULL;
// first node
p = malloc(sizeof(struct node));
p->value = 10;
p->next = first; first = p;
//second node
p = malloc(sizeof(struct node));
p->value = 20;
p->next = first; first = p;
//third node
p = malloc(sizeof(struct node));
p->value = 40;
p->next = first; first = p;
//fourth node
p = malloc(sizeof(struct node));
p->value = 30;
p->next = first; first= p;
puts( "Created nodes:" );
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 20 );
puts( "Nodes without 20:" );
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 30 );
puts( "Nodes without 30:");
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 10 );
puts( "Nodes without 10:");
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
printf( "There are no \"original nodes\". There are only those nodes on the list." );
return 0;
}
Omitted is the verification of the success of those multiple malloc() calls. An exercise for the reader.

Related

Creating an entire doubly linked list in one function

I'm new to DSA and currently learning linked-list. I was trying to create an entire linked list in one function. The first scanf in createList function doesn't seem to assign the input to the address provided(i.e. &n). I tried printing n right after scanf. It doesn't print n to console at all.
As a result, the output is not the way I expected. I can't figure out why.
//ENTIRE CODE HERE
#include<stdio.h>
#include<stdlib.h>
struct node {
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
struct node* addAtEnd(struct node*, int);
struct node* createList(struct node*);
int main() {
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head) {
struct node* ptr = head;
while (ptr != NULL) {
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data) {
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
head = temp;
return head;
}
struct node* addAtEnd(struct node* head, int data) {
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL) {
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return head;
}
struct node* createList(struct node* head) {
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d ", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d ", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++) {
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
your problem is so simple , instead of scanf("%d ", &n); , just write scanf("%d", &n); by which I mean to remove the wite space after %d as it's producing some strange behavior in your case , as if you refer to scanf() manual page , they say that :
A sequence of white-space characters (space, tab, newline,
etc.; see isspace(3)). This directive matches any amount
of white space, including none, in the input.
which is supposed to ignore any whitespace after the number entered till getting a valid char.
and here is the full code but with this only small modification:
#include<stdio.h>
#include<stdlib.h>
struct node {
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
struct node* addAtEnd(struct node*, int);
struct node* createList(struct node*);
int main() {
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head) {
struct node* ptr = head;
while (ptr != NULL) {
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data) {
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
head = temp;
return head;
}
struct node* addAtEnd(struct node* head, int data) {
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL) {
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return head;
}
struct node* createList(struct node* head) {
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++) {
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
and this is the output:
Enter the number of nodes:3
Enter the element of node 1:1
Enter the element of node 2:2
Enter the element of node 3:3
1 2 3
I tried out your code and found issues with the space in the literal string in the "scanf" statements. I see that someone else found that and offered up the solution to that with the cleanup of the "scanf" statements. I would say that if you are to accept an answer, select the first one. However, I just wanted to also offer up my code snippet with a couple of additional tweaks.
#include<stdio.h>
#include<stdlib.h>
struct node
{
struct node* prev;
int data;
struct node* next;
};
void print_nodes(struct node* );
struct node* addToEmpty(struct node*, int);
void addAtEnd(struct node*, int); /* No requirement for a node to be returned as the pointers are all set up in the function */
struct node* createList(struct node*);
int main()
{
struct node* head = NULL;
head = createList(head);
print_nodes(head);
}
void print_nodes(struct node* head)
{
struct node* ptr = head;
while (ptr != NULL)
{
printf("%d ", ptr->data);
ptr = ptr->next;
}
printf("\n");
}
struct node* addToEmpty(struct node* head, int data)
{
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
//head = temp;
return temp; /* Return the pointer to the new struct - no need for update of head here */
}
void addAtEnd(struct node* head, int data)
{
struct node* tp = head;
struct node* temp = malloc(sizeof(struct node));
temp->prev = NULL;
temp->data = data;
temp->next = NULL;
while (tp->next != NULL)
{
tp = tp->next;
}
tp->next = temp;
temp->prev = tp;
return;
}
struct node* createList(struct node* head)
{
int n, data, i;
printf("Enter the number of nodes: ");
scanf("%d", &n);
if (n == 0)
return head;
printf("Enter the element of node 1: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for (i = 1; i < n; i++)
{
printf("Enter the element of node %d: ", i + 1);
scanf("%d", &data);
addAtEnd(head, data);
}
return head;
}
First off, since there is not a need to return a "struct" pointer in the function "addAtEnd", I revised that to be a "void" function return signature. Second, in the "addToEmpty" function, one can just return the pointer value in "temp" instead of placing the value into the input parameter "head"; however, it works either way. It is just a matter of choice.
As a sample, here is some output data at the terminal.
#Una:~/C_Programs/Console/CompleteList/bin/Release$ ./CompleteList
Enter the number of nodes: 4
Enter the element of node 1: 65535
Enter the element of node 2: 2458
Enter the element of node 3: -44
Enter the element of node 4: 3258779
65535 2458 -44 3258779
I would suggest trying out both iterations.
Other answers have pointed at the specific problem you experienced (bad scanf() parameter string).
Going beyond that, however, there are two other "issues(?)".
First is to "create an entire linked list in one function".
In your code, main() calls only one function, but that function uses two "helper" functions to get the job done.
Every line of code is an opportunity for a bug to lurk unseen.
Re-using code is a way to reduce the chances for bugs to appear.
Secondly, the code appears to be correct, but does not prove that the doubly linked list is anything more than a singly linked list.
Both of these matters are addressed below creating (in one function, and later demonstrating) a circular doubly linked list.
Comments explain changes from the original code to this version.
Finally, an additional function is used here to prevent memory leaks.
#include <stdio.h>
typedef struct node { // Using 'typedef' saves lots of typing (and reading
int data;
struct node *next;
struct node *prev; // conventional layout of members
} node_t; // Notice '_t' as conventional suffix for user declared datatypes
node_t *print_nodes( node_t *head ) { // return pointer for use by caller
if( head ) { // insurance against NULL pointer
node_t *pn = head;
printf( "Forward: " ); // exercise circular LL in both directions
do {
printf( "%d ", pn->data );
pn = pn->next; // NB: 'next'
} while( pn != head ); // circular, not linear! One full circuit
puts( "" );
printf( "Reverse: " );
pn = pn->prev; // shift 'back' one node to begin
do {
printf( "%d ", pn->data );
pn = pn->prev; // NB: 'prev'
} while( pn != head->prev ); // circular, not linear! One full circuit
puts( "" );
}
return head;
}
node_t *createList() { // Create "one ring to rule them all"
int n = 0; // ALWAYS initialise variables
do {
printf( "Number of nodes (min 3): ");
scanf( "%d", &n ); // 'while' protects against bad input
} while( n < 3 );
node_t *head = NULL;
for( int i = 0; i < n; i++ ) {
printf( "Enter the element of node %d: ", i + 1 );
node_t *pn = (node_t *)calloc( 1, sizeof *pn ); // 'calloc()' zeros the block
/* check 'pn == NULL' omitted for brevity */
scanf("%d", &pn->data ); // read directly into destination (fewer variables)
if( head == NULL )
head = pn->prev = pn->next = pn; // 1st node, circular
else {
pn->prev = head->prev; // other nodes spliced-in ahead of 'head'
pn->next = head;
head->prev->next = pn;
head->prev = pn;
}
}
return head;
}
void freemem( node_t *head ) { // VERY important to respect "heap" storage!
if( head == NULL ) return;
node_t *pn = head; // traverse releasing nodes along the way
do {
node_t *pdel = pn;
pn = pn->next;
free( pdel );
} while( pn != head );
}
int main() {
// create, print, release, done...
freemem( print_nodes( createList() ) );
return 0;
}
Output
Number of nodes (min 3): 5
Enter the element of node 1: 42
Enter the element of node 2: 56
Enter the element of node 3: 10
Enter the element of node 4: -5
Enter the element of node 5: 256
Forward: 42 56 10 -5 256
Reverse: 256 -5 10 56 42
This code implements and proves a circular doubly linked list. The example can be trivially adapted to a linear dbl-LL by severing the connection between head and head->prev after the ring has been formed, and then making necessary adjustments at other locations to account for the change.

C program to traverse a singly linked lisk

I have written a C program to implement the concept of traversing a singly linked list. The program first creats the list by asking for the user input and then displays/ traverses through the created list. When i run this code, it sucessfully creates the linked list, but on displaying the created list, it produces an infinite loop.
`
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
} *head;
int main(){
struct node *newNode, *temp;
int n;
printf("Enter number of Nodes: ");
scanf("%d",&n);
if(n <= 1){
printf("Invalid Input Nodes should Nodes should be greater than 1");
exit(0);
}
else{
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL){
printf("No Memory Allocation");
exit(0);
}
else{
printf("Node Data 1: ");
scanf("%d",&head -> data);
head -> next = NULL;
temp = head;
}
newNode = (struct node *)malloc(sizeof(struct node));
if(newNode == NULL){
printf("No Memory Allocation");
exit(0);
}
else{
for(int i = 2; i <= n; ++i){
printf("Node Data %d: ",i);
scanf("%d",&newNode -> data);
newNode -> next = NULL;
temp -> next = newNode;
temp = temp -> next;
}
}
//Traversal
struct node *ptr;
ptr = head;
if(ptr == NULL)
{
printf("Empty list..");
}
else
{
while (ptr != NULL){
printf("\n%d",ptr->data);
ptr = ptr -> next;
}
}
}
return 0;
}
`
In this for loop
for(int i = 2; i <= n; ++i){
printf("Node Data %d: ",i);
scanf("%d",&newNode -> data);
newNode -> next = NULL;
temp -> next = newNode;
}
the same pointer newNode is assigned to the data member temp->next that is equivalent to the expression head->next because within the loop the pointer temp is not changed.
You need to allocate new nodes in the loop and reassign the pointer temp.
Also you need to check the entered value for the variable n. For example if n is set to 1 then there will be a memory leak.
And there is neither infinite loop provided that the entered value for the variable n is not equal to INT_MAX.
The program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
struct node
{
int data;
struct node *next;
} *head = NULL;
unsigned int n = 0;
printf( "Enter number of Nodes: " );
scanf( "%u", &n );
if (n != 0)
{
head = malloc( sizeof( struct node ) );
if (!head)
{
puts( "No Memory Allocation" );
exit( 0 );
}
else
{
printf( "Node Data 1: " );
scanf( "%d", &head->data );
head->next = NULL;
unsigned int i = 0;
for (struct node *temp = head; ++i < n; temp = temp->next)
{
if (( temp->next = malloc( sizeof( struct node ) ) ) == NULL)
{
puts( "No Memory Allocation" );
break;
}
temp->next->next = NULL;
printf( "Node Data %u: ", i + 1 );
scanf( "%d", &temp->next->data );
}
for (const struct node *current = head; current != NULL; current = current->next)
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
}
}
The program output is
Enter number of Nodes: 5
Node Data 1: 1
Node Data 2: 2
Node Data 3: 3
Node Data 4: 4
Node Data 5: 5
1 -> 2 -> 3 -> 4 -> 5 -> null
Pay attention to that you need to append the program with the code that will free all the allocated memory.

linked list program is not functioning properly

The given program is not showing all the elements of the linked list.
I am having problem in identifying the error.
At first I initialized the head with a null value then made a temporary variable and assigned it an integer value and pointer to the next node.
Then I made an another node named temp1 and linked it with the head.
It will only be linked when "i" will be equal to 1.
Then equated temp1 to the next node and did the same.
//Linked list
//Inserting the nodes.
#include <stdio.h>
struct node
{
int n;
struct node *next;
};
struct node *head;
int main ()
{
int i, s, x, y;
i = 0;
struct node *temp;
struct node *temp1;
struct node *cur;
head = NULL;
scanf ("%d", &s); //No. of nodes.
while (i < s)
{
scanf ("%d", &x);
if (head == NULL)
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1 = temp;
if (i == 1)
{
head->next = temp1;
}
temp1 = temp1->next; //Assigning the next node.i.e. NULL value
}
i = i + 1;
}
cur = head;
while (cur != NULL)
{
printf ("%d", cur->n);
cur = cur->next;
}
return 0;
}
Check the following changed section
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
temp1 = head;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1->next = temp;
temp1 = temp1->next; //Assigning the next node.i.e. NULL value
}
Instead of relying on
if (i == 1) {
head->next = temp1;
}
I assign head on temp1 while creating the head, which is meant to be happen only first time.
There were also some linkage issues in your else portion.
You lose nodes beyond the first two, since you never link them to the list. Use meaningful names for variables: rename temp1 to tail and initialize it to NULL in the beginning. Then the loop body becomes:
if (scanf(" %d", &x) != 1) {
// FIXME: handle error
}
temp = malloc(sizeof(*temp));
temp->n = x;
temp->next = NULL;
if (tail == NULL) {
head = temp;
} else {
tail->next = temp;
}
tail = temp;
++i;
(Untested.)
Rationale: You want to add new nodes to the end (tail) of the list. The easiest way is to keep track of the tail in an appropriately-named variable, and simply link every node to tail->next instead of convoluted logic like checking for the node count, etc. The only special case is the empty list, i.e., both head and tail are NULL, and the difference is just one line, so don't duplicate the whole block of code to set up the new node.
For starters you have to include the header <stdlib.h>.
The problem is in this statement
temp1 = temp;
if i is not equal to 1 then after this statement
temp1 = temp1->next;
temp1 becomes equal to NULL.
So all other nodes are not added to the list because there is a cycling
temp1 = temp;
//...
temp1 = temp1->next;
Change the loop the following way
while (i < s)
{
scanf ("%d", &x);
if (head == NULL)
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
head = temp;
temp1 = head;
}
else
{
temp = (struct node *) malloc (sizeof (struct node));
temp->n = x;
temp->next = NULL;
temp1->next = temp;
temp1 = temp;
}
i++;
}
Pay attention to that you should declare variables in a block scope where they are used. Otherwise the program will be unreadable.
The approach you are using can be called as an Java approach.
In C the program can look much simpler. For example
#include <stdio.h>
#include <stdlib.h>
struct node
{
int n;
struct node *next;
};
struct node *head;
int main( void )
{
struct node **temp = &head;
size_t n = 0;
scanf( "%zu", &n );
for ( size_t i = 0; i < n; i++ )
{
*temp = (struct node *) malloc ( sizeof ( struct node ) );
int value = 0;
scanf ( "%d", &value);
( *temp )->n = value;
( *temp )->next = NULL;
temp = &( *temp )->next;
}
for ( struct node *cur = head; cur != NULL; cur = cur->next )
{
printf ("%d -> ", cur->n );
}
puts( "NULL" );
return 0;
}
Its output might look like
1 -> 2 -> 3 -> NULL

How to implement a [copy array to linked list] function?

What this supposed to do is:
Create an array with 4 elements.
Print these 4 elements.
Copy array elements to a created linked list in copy fucntion.
Print linked list with print and traverse fuction.
I tried this and it compiles, but crashes after printing the array.
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ELEMENTS 4
struct node {
int data;
struct node *next;
};
struct node *head;
void insert(int x) {
struct node *temp = malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head != NULL)
temp->next = head;
head = temp;
}
void copy(struct node *head, int array[ELEMENTS], int n) {
//copying array elements and create linked list
struct node *temp = malloc(sizeof(struct node));
temp->data = array[0];
temp->next = NULL;
head = temp;
int i;
for (i = 1; i < n; i++) {
struct node *temp2 = malloc(sizeof(struct node));
temp->next = temp2;
temp2->data = array[i];
temp2->next = NULL;
temp = temp2;
}
}
void printlist() {
struct node*temp = head;
printf("List is : ");
while (temp->next != NULL) {
printf(" %d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
int *array = (int*)calloc(ELEMENTS , sizeof(int));
int i = 0;
for (i = 0; i < ELEMENTS; i++) {
printf("arrays = [%d] ", i);
scanf("%d", &array[i]);
}
for (i = 0; i < ELEMENTS; i++)
printf("array [%d] = %d \n", i, array[i]);
copy(head, array[ELEMENTS], ELEMENTS);
printlist();
getchar();
return(0);
}
How to fix it?
You dont need to pass head to the copy function because it is global and when you do you create a local pointer named head which gets destroyed as soon as function is over.
So copy should look like this
void copy(int array[ELEMENTS],int n) //copying array elements and create linked list
{
struct node*temp = malloc(sizeof(struct node));
temp->data=array[0];
temp->next=NULL;
head =temp;
int i;
for(i=1;i<n;i++)
{
struct node*temp2= malloc(sizeof(struct node));
temp->next= temp2;
temp2->data = array[i];
temp2->next = NULL;
temp=temp2;
}
}
Also while printing change while to
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp=temp->next;
}
When you call the function copy, you are passing "array[ELEMENTS]" as an argument, but you want to pass only "array". What you're passing is value after your array, which the copy function is trying to interpret as an address of an array it's actaully expecting.
Note that accessing a value that is not yours like this results in undefined behaviour and can actually make the system kill your application. But what probably happened after is there will be a 0 in the memory, which gets passed to the copy function and it then tries to access values at memory 0x0 to 0xF, which almost always results in segmentation fault, which as you experienced first hand, causes the program to stop working.
Bottom line, delete [ELEMENTS] at the line where you call the copy function and I believe the program should start working. I implore you though to do further research on pointers and passing them as function parameters.
(And since I cannot comment yet I will just put this in here, as Sniper stated, you don't have to pass reference to global variable, but he is wrong about the structure being destroyed at the end of the function. That would have been true, if it was created at stack, but you are allocating space for it at heap, which means it will stay there until you either free() it or the program ends.)
I have simple dimple answer:
#include<stdio.h>
#include<stdlib.h>
struct Node{
int current;
struct Node *next;
};
struct LinkedList{
struct Node *head;
};
int main(){
int i, data[5] = {10, 20, 30, 40, 50};
struct Node *node = malloc(sizeof(struct Node));
struct LinkedList *llist = malloc(sizeof(struct LinkedList));
node->current = data[0];
node->next = NULL;
llist-> head = node;
for(i = 1; i <= sizeof(data) / sizeof(data[0]) - 1; i++){
struct Node *new_node = malloc(sizeof(struct Node));
node->next = new_node;
new_node->current = data[i];
new_node->next = NULL;
node = new_node;
}
node = llist->head;
printf("llist: ");
while(node != NULL){
printf("%d->", node->current);
node = node->next;
}
return 0;
}

Implement a doubly linked list in C

I want to insert a node at the beginning of linked list, whenever insertAtBeginning method is called. My code builds well, but i don't get the desired output.
I get the following output:
0------>NULL
The desired output is:
9------>8------>7------>6------>5------>4------>3------>2------>1------>0------>NULL
Following is my code:
#include<stdio.h>
#include<stdlib.h>
struct dll{
int data;
struct dll* previous;
struct dll* next;
};
struct dll* insertAtBeginning(int a, struct dll* head){
if(head == NULL){
head->data = a;
head->previous = NULL;
head->next = NULL;
return head;
}
else{
struct dll *first;
first = (struct dll*) malloc( sizeof(struct dll));
first->data = a;
first->next = head;
head->previous = first;
first->previous = NULL;
head = first;
free(first);
return head;
}
}
void display_from_first(struct dll* head){
struct dll *temp;
temp = head;
printf("\nThe linked list contains: ");
while(temp != NULL) {
printf("%d------>",temp->data);
temp = temp->next;
}
printf("NULL\n");
free(temp);
}
int main(){
int i = 0;
struct dll *head1, *tail1;
head1 = (struct dll*) malloc( sizeof(struct dll));
head1->next = NULL;
head1->previous = NULL;
for(i=0; i<10; i++){
insertAtBeginning(i, head1);
}
display_from_first(head1);
return 0;
}
The code for a doubly linked list is much cleaner if you start with an empty list of two nodes as shown below.
That way you don't have to deal with special cases like if(head==NULL). There's always a node before and after the node that is being inserted (or deleted), so you just hook things up and you're done.
#include <stdio.h>
#include <stdlib.h>
typedef struct s_node Node;
struct s_node
{
Node *prev;
Node *next;
int data;
};
Node *insertAtBeginning( Node *head, int value )
{
// allocate memory for the new node
Node *node = malloc( sizeof(Node) );
if ( node == NULL )
return NULL;
// insert the node at the beginning of the list
Node *temp = head->next;
head->next = node;
temp->prev = node;
// fill in the fields of the node
node->prev = head;
node->next = temp;
node->data = value;
return node;
}
void showList( Node *head )
{
Node *node;
printf( "The list contains: " );
for ( node = head->next; node->next != NULL; node = node->next )
printf( "%d--->", node->data );
printf( "NULL\n" );
}
int main( void )
{
// create an empty list with two nodes
Node head = { NULL , NULL, 0 };
Node tail = { &head, NULL, 0 };
head.next = &tail;
// insert more nodes
for ( int i = 0; i < 10; i++ )
insertAtBeginning( &head, i );
// display the list
showList( &head );
}
There are mainly two problems here :
free(first) : This is not required as you wish to save the memory you just allocated, not delete it.
Your insertAtBeginning() function returns a pointer to head, so in main(), where you are calling this function change it to head1=insertAtBeginning(i, head1); This way your head is also saved.
Here's the code with the two edits :
http://ideone.com/nXwc8z
You have several mistakes here.
1) Your function insertAtBeginning returns pointer to changed list, but you do not update pointer to head of list in the main function.
2) You are freeing just allocated pointer to new node in the insertion function. You think that you are freeing pointer, but actually you say that this place in memory is not needed more and so your node can't be there.
You can't free(first); in insertAtBeginning().
code here.
And btw when you have empty list your display_from_first() prints The linked list contains: 0------>NULL because of
head1 = (struct dll*) malloc( sizeof(struct dll));
head1->next = NULL;
head1->previous = NULL;
in main(). Remove it from main to have correct output

Resources