I have this piece of code, it deletes the last element from a linked list. What changes do I have to make so it will delete the last TWO elements of the linked list?
void deletesEnd() {
struct node *temp, *last;
temp = head;
last = temp;
while (temp != NULL && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == temp) {
free(temp);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
}
The simplest solution to remove the last 2 elements of the list is to call deletesEnd() twice. Note that deletesEnd() should take head as an argument and return the new value. You would delete the last 2 by issuing a nested call:
struct node *deletesEnd(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
free(head);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
return head;
}
Delete the last element: head = deletesEnd(head);
Delete the last 2 elements: head = deletesEnd(deletesEnd(head));
The simplicity of the design more than compensates for the overhead of enumerating the list twice.
If you absolutely want a specific function, you can extend your approach this way:
struct node *deleteLast2Nodes(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL && temp->next->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
if (head) {
free(head->next);
}
free(head);
head = NULL;
} else {
free(last->next->next);
free(last->next);
last->next = NULL;
}
return head;
}
Here is a demonstrative program that shows how two last nodes can be deleted simultaneously. In fact the function is similar to your function except it checks not only the next node but also the next->next node.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
struct node *next;
} *head;
void push( int value )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->value = value;
tmp->next = head;
head = tmp;
}
void display()
{
for ( struct node *current = head; current; current = current->next )
{
printf( "%d ", current->value );
}
}
void deleteLastTwo()
{
struct node *current = head;
struct node *prev = head;
if ( current && current->next )
{
while ( current->next->next )
{
prev = current;
current = current->next;
}
}
if ( current )
{
if ( current->next )
{
free( current->next );
}
if ( prev == current )
{
head = NULL;
}
else
{
prev->next = NULL;
}
free( current );
}
}
int main(void)
{
const int N = 11;
for ( int i = N; i != 0; i-- ) push( i - 1 );
display();
printf( "\n" );
while ( head )
{
deleteLastTwo();
display();
printf( "\n" );
}
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6
0 1 2 3 4
0 1 2
0
Take into account that it is not a good idea when the head node is declared like a global variable. It is better when it can be declared like a local variable. In this case you will need to rewrite the methods of the list because in most cases the current methods will not work correctly.
This logic will delete your last 2 node in singly linked list.
void deletesEnd()
{
struct node *temp, *last;
temp = head;
last = temp;
while (temp->next->next != NULL)
{
last = temp->next;
if(last->next->next!=NULL)
temp = temp->next;
else
break;
}
struct node *ptr=last->next;
last->next=ptr->next;
free(ptr);
temp->next=last->next;
free(last);
}
For fun & education: simple recursive version.
The function return := the number of nodes below us
After the recursion returns, we can decide if we are too close to the tail.
and remove ourselves
because we pass a pointer to pointer, this should also work for lists of size=2 and smaller
unsigned del_tail_n(struct llist **pp, unsigned nn)
{
unsigned pos;
if (!*pp) return 0;
// this recursive call returns 0 iff (*pp)->next is NULL
pos = del_tail_n( &(*pp)->next, nn);
if (pos < nn) {
// free (*pp);
*pp = NULL;
}
return 1+pos;
}
For those who don't like recursion, here is a non-recursive version.
[do note that both versions work for empty lists (*pp == NULL) , or for lists smaller than nn ]
void del_tail_n2(struct llist **pp, unsigned nn)
{
struct llist *p;
/* Advance p pointer n positions down, starting from *pp. */
for (p= *pp; p; p=p->next) {
if (nn-- < 1) break;
}
/* Do a synchronous walk down for both p and *pp, until p is NULL. */
for ( ; p; p=p->next) {
pp = &(*pp)->next;
}
/* Now, *pp is the first node to delete
** Delete it and everything below it.
*/
for ( ;(p = *pp); ){
*pp = p->next;
// free (p);
}
return;
}
Related
In the code below, I try to change the first node with another node from the list. The problem is that I can't do it, I've been struggling for two days, and I still can't figure it out.
Description code :
enter the number of nodes from the keyboard.
pos1 = 1 - the position of the first node in the list
pos2 - the position of the node to be changed with the first node.
In the function Node *createLinkedList(int n) I create the list of nodes, the function void displayList(Node *head) displays the list, the function void swapFirstNode(Node *head, int pos1, int pos2) should exchange the first node with the node a whose position is read from the keyboard.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
}Node;
Node *createLinkedList(int n);
void displayList(Node *head);
void swapFirstNode(Node *head, int pos1, int pos2);
int main()
{
int n, pos1, pos2;
Node *HEAD = NULL;
printf("\n Enter the number of nodes : ");
scanf("%d", &n);
HEAD = createLinkedList(n);
displayList(HEAD);
printf("\n Enter first node position to swap : ");
scanf("%d", &pos1);
printf("\n Enter second node position to swap : ");
scanf("%d", &pos2);
if(pos1 == 1 && pos2 != 1)
swapFirstNode(HEAD, pos1, pos2);
displayList(HEAD);
}
Node *createLinkedList(int n)
{
int i, value;
Node *head = NULL;
Node *temp = NULL;
Node *curr = NULL;
head = (struct node*)malloc(sizeof(struct node));
if(head == NULL)
{
printf("\n Memory can not be allocated!");
}
else
{
printf("\n Input data for node 1 : ");
scanf("%d", &value);
head->data = value;
head->next = NULL;
temp = head;
for(i=2; i<=n; i++)
{
curr = (struct node *)malloc(sizeof(struct node));
if(curr == NULL)
{
printf(" Memory can not be allocated.");
break;
}
else
{
printf("\n Input data for node %d : ", i);
scanf("%d", &value);
curr->data = value;
curr->next = NULL;
temp->next = curr;
temp = temp->next;
}
}
}
return head;
}
void displayList(Node *head)
{
Node *curr = head;
printf("\n");
printf(" ");
while(curr != NULL)
{
printf("%d->", curr->data);
curr = curr->next;
}
printf("NULL\n");
}
void swapFirstNode(Node *head, int pos1, int pos2)
{
Node *curr = head, *node1 = NULL, *node2 = NULL, *prev_node1 = NULL, *prev_node2 = NULL, *temp = NULL;
int counter = 0, value, i = 1;
/// Find out how many nodes are in list
while(curr != NULL)
{
counter++;
curr = curr->next;
}
if(pos1 < 1 || pos1 > counter || pos2 < 1 || pos2 > counter)
exit(0);
/// Retain the maxim value between two position entered from the keyboard
value = pos1 > pos2 ? pos1 : pos2;
curr = head;
node1 = curr;
while(curr != NULL && i <= value)
{
if(pos2 != 1)
{
/// Set the previous node (the node before the second node), regarding the pos2-1
if(i == (pos2-1))
prev_node2 = curr;
/// Set the seconde node, regarding the pos2 entered from the keyboard
if(i == pos2)
node2 = curr;
}
curr = curr->next;
i++;
}
/// Try to swap the two nodes
if(node1 != NULL && node2 != NULL)
{
if(prev_node2 != NULL)
{
temp = head;
node1->next = node2->next;
node2 = temp;
prev_node2->next = node1;
node2->next = temp->next;
}
}
}
I'm sorry. I get dizzy trying to keep track of all of those counters and pointers and everything.
KISS
The following works quite well swapping the head node with another further down the list. Earlier validation ensures that pos > 1 (the user's idea of "first" node) and pos <= n, the count of the number of nodes in the LL. (ie. The user enters 'swap node 2' and this function is called with n - 1. The function then works with the head being considered node 0.)
Notice that the address of the pointer head is received as a ptr-to-ptr. This allows the function to update the caller's variable. Essential in this case because the function is definitely changing the LL's first node!
Anyway, walk & think your way through these lines. I hope it helps show that fewer moving parts can be more effective.
void swapFirstNode( Node **head, int pos ) {
Node *prev = *head, *cut;
if( pos == 1 ) { // special case of 1st & 2nd swapping
cut = prev->next;
prev->next = prev->next->next;
cut->next = prev;
} else {
while( --pos )
prev = prev->next; // Now pointing at node AHEAD of node to swap out.
cut = prev->next;
Node *cont = cut->next; // Now pointing at continuation (if any)
cut->next = (*head)->next; // Now two heads
prev->next = *head; // head spliced onto 1st section
(*head)->next = cont; // old head joined to continuation
}
*head = cut; // This is the new head!
}
I asked for clarification regarding pos1 but didn't get any so I just disregard that. swapFirstNode will always swap with the first node so pos1 will not be needed.
In order to do the swap, I suggest iterating from head pos2 times, then perform a swap of head->data and the data at the Node you're currently pointing at.
Example:
// pos2 is in the range [0, number of elements)
void swapFirstNode(Node *head, int pos2) {
Node *curr = head;
while(pos2-- > 0 && curr) curr = curr->next;
if(!curr) return; // pos2 was out of bounds
// swap
int tmp = curr->data;
curr->data = head->data;
head->data = tmp;
}
Note: pos2 is zero-based as-is common practice in C. You may present 1-based indices to the user, but I suggest not using 1-based arrays/lists in the rest of the code.
For starters the function createLinkedList has an unpredictable behavior because it creates a node even when the user passes to the function a non-positive value.
Node *createLinkedList(int n)
{
int i, value;
Node *head = NULL;
Node *temp = NULL;
Node *curr = NULL;
head = (struct node*)malloc(sizeof(struct node));
//...
At first it should check the value of the parameter n before starting creating nodes. Also the parameter should have an unsigned integer type as for example size_t because negative values do not make a sense.
The parameter of the function displayList should be declared with qualifier const because the function does not change the displayed list.
void displayList( const Node *head );
In C indices start from 0 not from 1. The index 0 corresponds to the head node.
Calculating the number of nodes in the list
while(curr != NULL)
{
counter++;
curr = curr->next;
}
is inefficient. For example if you want to swap the first two nodes then there is no sense to count all nodes in the list.
And if the user specified invalid positions then the program shall not end abruptly as in your function
if(pos1 < 1 || pos1 > counter || pos2 < 1 || pos2 > counter)
exit(0);
It is enough to report to the user that nodes were not swapped because the user specified invalid positions.
And the pointer to the head node must be passed by reference that is through a pointer to it because the pointer to the head node can be changed within the function.
So the function should be declared like
int swapFirstNode( Node **head, size_t pos1, size_t pos2 );
That is the function returns integer value 1 in case of success or 0 otherwise.
What you need to swap two nodes is to swap the pointers that point to the nodes and their data members next that in turn are pointers.
So write an auxiliary function swap that will swap two pointers.
Here is a demonstration program that shows how it can be done.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
}Node;
Node * createLinkedList( const int a[], size_t n )
{
Node *head = NULL;
Node **current = &head;
while ( n-- && ( *current = malloc( sizeof( Node ) ) ) != NULL )
{
( *current )->data = *a++;
( *current )->next = NULL;
current = &( *current )->next;
}
return head;
}
void displayList( const Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void swap( Node **ptr1, Node **ptr2 )
{
Node *tmp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = tmp;
}
int swapFirstNode( Node **head, size_t pos1, size_t pos2 )
{
int success = 0;
if ( pos1 != pos2 )
{
if ( pos2 < pos1 )
{
size_t tmp = pos1;
pos1 = pos2;
pos2 = tmp;
}
Node **first_node = head;
for ( size_t i = 0; *first_node != NULL && i < pos1; i++ )
{
first_node = &( *first_node )->next;
}
success = *first_node != NULL;
if ( success )
{
Node **second_node = first_node;
for ( size_t i = 0; *second_node != NULL && i < pos2 - pos1; i++ )
{
second_node = &( *second_node )->next;
}
success = *second_node != NULL;
if ( success )
{
swap( first_node, second_node );
swap( &( *first_node )->next, &( *second_node )->next );
}
}
}
return success;
}
int main( void )
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
size_t N = sizeof( a ) / sizeof( *a );
Node *head = createLinkedList( a, N );
displayList( head );
swapFirstNode( &head, 0, 1 );
displayList( head );
swapFirstNode( &head, 2, 9 );
displayList( head );
swapFirstNode( &head, 4, 5 );
displayList( head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 0 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 0 -> 9 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 2 -> null
1 -> 0 -> 9 -> 3 -> 5 -> 4 -> 6 -> 7 -> 8 -> 2 -> null
In fact it is this code snippet
if ( success )
{
swap( first_node, second_node );
swap( &( *first_node )->next, &( *second_node )->next );
}
that swaps two nodes by using the auxiliary function swap that swaps two pointers.
As you can see the function swapFirstNodeis very flexible. It can swap any two nodes of the list. And it indeed swaps two nodes not just data stored in nodes.
Pay attention to that you need to write a function that will clear the list that is that will free all the allocated memory.
The function below is the one I am trying to work on. The problem I am running into is that I do not know how to "keep" the pointer to the original head to the list as that is what I have to return after insertion.
There is no Driver code so everything must be done inside this function.
Because I must do this recursively I cannot just create a temporary node to point to the original head. I am just getting used to recursion and I cannot find a solution.
NOTE: There are some other problems with my function as I believe it wouldn't work well for inserting a new node into the beginning and end of the linked list but I am confident I could work out those edge cases.
The main thing I am trying to learn is how to "store" the original head of my list.
All help is appreciated.
Node* insert(Node* head, int index, int data)
{
if (head == NULL) return NULL; // if list is empty
if (index == 1) // if we have accessed node before insertion
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->next = head->next; // new_node->next now links to the node next in the list
head->next = new_node; // head->next links to new node
new_node->data = data; // assigns new node its data
return head; // not sure how to return original head
}
return insert(head->next, index - 1, data);
}
Node *insertRecursive(Node* head,int pos,int val)
{
if(pos==0 || head==NULL)
{
Node *newNode= new Node(val);
newNode->next=head;
head=newNode;
return head;
}
else
head->next = insertRecursive(head->next,pos-1,val);
}
For starters the parameter that specifies the position where a node has to be inserted should have an unsigned integer type, for example, size_t. Positions should start from 0.
The function can be defined the following way
struct Node * insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0 )
{
struct Node *new_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;
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.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 = 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;
}
void print( const struct Node *head )
{
for (; head != NULL; head = head->next)
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main( void )
{
struct Node *head = NULL;
head = insert( head, 0, 3 );
print( head );
head = insert( head, 0, 0 );
print( head );
head = insert( head, 1, 1 );
print( head );
head = insert( head, 2, 2 );
print( head );
}
The program output is
3 -> null
0 -> 3 -> null
0 -> 1 -> 3 -> null
0 -> 1 -> 2 -> 3 -> null
Node* insert_Node_recursively(Node* head,int data,int position){
//Inserting on the first node.
if(position==0){
Node* newNode=new Node(data);
newNode->next=head;
head=newNode;
return head;
}
if((head->next==NULL && position==0) /*for adding on the end of the list */ || position==1 /*Inserting on node in between */){
Node* newNode=new Node(data);
newNode->next=head->next;
head->next=newNode;
return head;
}
//in case the position exceeds the total number of nodes
if(head->next==NULL && position>0){
return head;
}
else{
head->next=insert_Node_recursively(head->next,data,position-1);
}
return head;
}
this will work I think, covered all the aspects
//if you have created a node using class then here is the solution
//to insert a node at a position recurssively
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//here is the full solution to add a node recursively at a position
#include<iostream>
using namespace std;
//the below code is for creation of class for node
class Node
{
public:
int data;
Node * next;
Node(int data) //constructor
{
this -> data = data;
next = NULL;
}
};
//the below code is for creation of linked list
//a terminator -1 is used to stop taking input
Node * takeInput()
{
int data;
cout<<"Enter the data of the node to be inserted ( use -1 to terminate
the insertion ) : ";
cin>>data;
Node * head = NULL;
Node * tail = NULL;
while(data != -1)
{
Node * newNode = new Node(data);
if(head == NULL)
{
head = newNode;
tail = newNode;
}
else
{
tail->next=newNode;
tail = tail -> next;
}
cout<<"Enter the data of the node to be inserted ( use -1 to
terminate the insertion ) : ";
cin>>data;
}
return head;
}
//the below code is to print the linked list
void print(Node * head)
{
if(head == NULL)
{
cout<<"The linked list id empty !"<<endl;
return;
}
Node * temp = head;
while(temp != NULL)
{
cout<<temp->data<<" ";
temp = temp -> next;
}
cout<<endl;
}
//the below part is the main solution to the problem
//insertion at a position using recursion
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//this is the main from where all the function calls happen
int main()
{
int data, key;
Node * head = takeInput();
print(head);
cout<<"Enter the data of the node to be inserted : ";
cin>>data;
cout<<"Enter the position of insertion : ";
cin>>key;
head = insertRecursive(head,data,key);
print(head);
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm writing a program that creates a doubly linked list and removes a element with negative value from it. Everything pretty much works, except for the part when I called the modify function and when I try to delete it, program crashes. Any suggestions?
/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#include<stdio.h>
#include<stdlib.h>
struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int);
void modify(struct list*);
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the count of node :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("\nDoubly linked list is created and the list is as follows : \n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
struct list* create(int value) {
struct list *new_node, *temp;
temp = head;
new_node = (struct list*)malloc(sizeof(struct list));
new_node -> data = value;
new_node -> next = NULL;
new_node -> prev = NULL;
if (head == NULL) {
head = new_node;
}
else {
while (temp -> next != NULL) {
temp = temp -> next;
}
temp -> next = new_node;
new_node -> prev = temp;
}
return head;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
current_node = temp;
prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
next_node -> prev = prev_node;
free(current_node);
}
}
printf("\nThe modified doubly linked list is : \n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}
See the examples of Vlad from Moscow to have a better understanding of what you were doing.
I shall go trough your code and tell you what I would change.
/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
First of all: you're making a (doubly linked) list of nodes, not a list of lists. Call it a Node. Also, you can do a typedef to prevent you from writing struct Node all the time.
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void append(struct Node** head, int value); // variable names aren't needed here
struct Node* findLastNode(struct Node** head);
void removeNegativeNodes(struct Node** head);
void removeNode(struct Node** head, struct Node* currNode);
int main(void)
{
Try not to use global variables. There are many reasons to be found why not to use them, but in here it's possible to don't use them as well. Imagine having thousands of lines of code, you won't be able to have a decent view on the code.
struct Node* head = NULL;
struct Node* p; // temp-<p>ointer
int n, value;
printf("Enter the count of node :");
scanf("%d", &n);
You only need i in the for-loop, so keep it there.
for (int i = 0; i < n; ++i) {
printf("Enter the value of node: ");
scanf("%d", &value);
Make sure your function names are clear and tell you what they do. create() would tell me it creates a Node, but not that it also appends the node.
append(&head, value);
}
// this can be in a function! (A) printData
p = head; // temp-<p>ointer
printf("\nDoubly linked list is created and the list is as follows : \n");
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULL\n");
Look at what you're doing: perhaps you want to make a general function to split the code? Here you're again going trough the list and printing out it's data members.
// this can be in a function! (B) printData
removeNegativeNodes(&head);
printf("\nThe modified doubly linked list is : \n");
p = head;
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULL\n");
}
struct Node* findLastNode(struct Node** head)
{
struct Node* p = *head;
if (p != NULL)
while (p->next != NULL)
p = p->next;
return p;
}
Since your head has to be changed, you'll have to pass the address of the head as well. Also, split your code a bit, so it's easier for yourself to have an idea of your code's structure. If your function is 40 rules long, it will take longer to find out where the cause of the bug is located (exactly).
void append(struct Node** head, int value)
{
struct Node* lastNode = findLastNode(head);
struct Node* nextNode = (struct Node*)malloc(sizeof(struct Node));
if (lastNode != NULL) {
lastNode->next = nextNode;
nextNode->prev = lastNode;
}
else {
*head = nextNode;
nextNode->prev = NULL;
}
nextNode->next = NULL;
nextNode->data = value;
}
Here as well: the first number can be negative, so make sure you can access the head variable by it's address. Also, again keep it simple and split your code in functions removeNegativeNodes > removeNode.
void removeNegativeNodes(struct Node** head)
{
struct Node* p = *head;
struct Node* temp;
while (p != NULL) {
temp = p->next;
if (p->data < 0)
removeNode(head, p);
p = temp;
}
}
void removeNode(struct Node** head, struct Node* currNode)
{
if (currNode->next != NULL)
currNode->next->prev = currNode->prev;
if (currNode->prev != NULL)
currNode->prev->next = currNode->next;
else
*head = currNode->next;
free(currNode);
}
I've tested the code and it should work. Having it worked properly is not important though, it's understanding what happens. I recommend you having a closer look to it. Goodluck!
Your definition of a doubly-linked list does not make great sense.
The list should contain two pointers: to the head node and to the tail node of the list.
So you need to define two structures. The first one defines the node and the second one defines the list itself.
In this case you need not to traverse the whole list to append a new node to the tail of the list.
The function create with the confusing name is based on the global variable head while the function modify instead gets the variable through a parameter.
This is very confusing. As result for example you can not create two lists in a program.
So as the function modify gets the pointer to the head node by value then it means that it deals with a copy of the pointer to the head node. As a result any changes of the pointer to the head node in the function does not influence on the original pointer to the head node.
This loop in the function modify
temp = head;
while (temp -> next != NULL) {
in general can invoke undefined behavior because it is not excluded that the pointer to the head node can be equal to NULL.
And in any case the condition of the loop does not make sense because within the loop you are considering not the next node but the current
while (temp -> next != NULL) {
if (temp -> data < 0) {
So a question arises if temp->next is equal to NULL but the value of the current node pointed to by the pointer temp is negative does it mean that this node will not be removed?
Pay attention to that if you will write the condition of the loop correctly nevertheless either data member prev of the removed node or the data member next of the removed node or even the both can be equal to NULL. In this case these statements
prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
^^^^^^^^^^^^^^^^^
next_node -> prev = prev_node;
^^^^^^^^^^^^^^^^^
again can invoke undefined behavior.
here is a demonstrative program that shows how the list and its functions can be defined. Investigate it.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
struct Node *prev;
};
struct List
{
struct Node *head;
struct Node *tail;
};
int push_back( struct List *list, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( list->head == NULL )
{
new_node->prev = NULL;
list->head = list->tail = new_node;
}
else
{
new_node->prev = list->tail;
list->tail = list->tail->next = new_node;
}
}
return success;
}
void remove_if( struct List *list, int predicate( int ) )
{
struct Node *prev = NULL;
for ( struct Node **current = &list->head; *current != NULL; )
{
if ( predicate( ( *current )->data ) )
{
struct Node *tmp = *current;
if ( ( *current )->next != NULL )
{
( *current )->next->prev = ( *current )->prev;
}
*current = ( *current )->next;
free( tmp );
}
else
{
prev = *current;
current = &( *current )->next;
}
}
list->tail = prev;
}
void display( const struct List *list )
{
for ( const struct Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
void display_reverse( const struct List *list )
{
for ( const struct Node *current = list->tail; current != NULL; current = current->prev )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int is_negative( int data )
{
return data < 0;
}
int main(void)
{
struct List list = { .head = NULL, .tail = NULL };
const size_t N = 10;
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
push_back( &list, rand() % N - N / 2 );
}
display( &list );
display_reverse( &list );
putchar( '\n' );
remove_if( &list, is_negative );
display( &list );
display_reverse( &list );
putchar( '\n' );
return 0;
}
The program output might look like
2 -> 4 -> 3 -> -5 -> 3 -> -3 -> -3 -> -2 -> 0 -> 2 -> null
2 -> 0 -> -2 -> -3 -> -3 -> 3 -> -5 -> 3 -> 4 -> 2 -> null
2 -> 4 -> 3 -> 3 -> 0 -> 2 -> null
2 -> 0 -> 3 -> 3 -> 4 -> 2 -> null
The create() function returns a linked list item. so you have to assign the return value to an item. Also the definition of pointers inside the struct is completely wrong.
struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int); //function prototype
void modify(struct list*);//function prototype
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the number of nodes :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("\nDoubly linked list is created and the list is as follows : \n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
void create(int value) {
struct list* point = head;
while(point->next){
if(point->data != value)
point = point->next;
else{
printf("Data exists\n");
return NULL;
}
}
struct list* item = (struct list*)malloc(sizeof(struct list));
item->data = value;
item->next = NULL;
item->prev = point;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
}
temp = temp->next;
}
printf("\nThe modified doubly linked list is : \n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}
I hope this will work for you.
typedef struct node
{
int a;
struct node *next;
}node;
void generate(struct node **head)
{
int num = 10, i; //the num here is the length
struct node *temp;
for (i = 0; i < num; i++)
{
temp = (struct node*)malloc(sizeof(struct node));
temp->a = 10-i;
if (*head == NULL)
{
*head = temp; //each time add another node to the start
(*head)->next = NULL;
}
else
{
temp->next = *head;
*head = temp;
}
}
}
void addSpecific(node* head,int n)
{
node* temp = NULL;
if (head->next == NULL)
{
temp = (node*)malloc(sizeof(node*)); //allocating memory
(temp)->a = n; //adding the wanted value
(temp)->next = NULL; //making the new node to point to the end
head->next = temp; //and the previous one to point to temp
}
else
{
addSpecific(head->next, n); //if this is not the wanted node we need to move to the next node
}
}
void deleteNode(struct node **head)
{
struct node *temp;
while (*head != NULL)
{
temp = *head;
*head = (*head)->next; //going to the next node
free(temp); //free the allocated memory
}
}
int main()
{
struct node *head = NULL;
generate(&head);
addSpecific(head, 7);
display(head);
deleteNode(&head);
system("PAUSE");
return 0;
}
I was trying to insert new node at the end using recursion, but the free memory (delete) function make an expansion, and I couldn't find the problem. I tried the generating function and adding the node at the end and it worked but the complier alert me for "heap corruption".
The function can look the following way as it is shown in the following demonstrative program
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int a;
struct node *next;
} node;
void addSpecific( node **head, int n )
{
if ( *head == NULL )
{
*head = malloc( sizeof( node ) ); //allocating memory
( *head )->a = n; //adding the wanted value
( *head )->next = NULL; //making the new node to point to the end
}
else
{
addSpecific( &( *head )->next, n ); //if this is not the wanted node we need to move to the next node
}
}
void display( node *head )
{
for ( ; head != NULL; head = head->next ) printf( "%d ", head->a );
printf( "\n" );
}
int main( void )
{
const int N = 10;
node *head = NULL;
for ( int i = 0; i < N; i++ )
{
addSpecific( &head, i );
display( head );
}
return 0;
}
The program output is
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9
As for the function deleteNode then it can look for example the following way
void deleteNode( node **head )
{
for ( node *current = *head; current != NULL; )
{
node *temp = current;
current = current->next; //going to the next node
free( temp ); //free the allocated memory
}
*head = NULL;
}
As for this implementation of the function
void deleteNode( node **head )
{
while ( *head != NULL )
{
node *temp = *head;
head = &( *head )->next; //going to the next node
free( temp ); //free the allocated memory
}
}
then it has undefined behavior because it tries to access a data member of the structure object that was already deleted.
Or you can make the function recursive. For example
void deleteNode( node **head )
{
if ( *head != NULL )
{
deleteNode( &( *head )->next );
free( *head );
*head = NULL;
}
}
A bit off-topic, but it is quite convenient to maintain single-linked lists with two pointers, rather than one. This way you can prepend and append the list in O(1) without having to use recursion. E.g.:
struct Node
{
struct Node* next;
};
struct List
{
struct Node *head, **tail;
};
void List_init(struct List* list) {
list->head = 0;
list->tail = &list->head;
}
void List_append(struct List* list, struct Node* node) {
node->next = 0;
*list->tail = node;
list->tail = &node->next;
}
void List_prepend(struct List* list, struct Node* node) {
node->next = list->head;
list->head = node;
if(list->tail == &list->head)
list->tail = &node->next;
}
void List_remove(struct List* list, struct Node* node) {
struct Node *cur = list->head, **prev = &list->head;
while(cur && cur != node) {
prev = &cur->next;
cur = cur->next;
}
if(cur) {
if(!(*prev = node->next))
list->tail = prev;
}
}
# For reference:
#
# SinglyLinkedListNode:
# int data
# SinglyLinkedListNode next
def insertNodeAtTail(node, data):
if node is None:
last = SinglyLinkedListNode(node_data=data)
last.next = None
return last
if node.next is None:
last = SinglyLinkedListNode(node_data=data)
last.next = None
node.next = last
return node
node.next = insertNodeAtTail(node.next, data)
return node
The below is my code to recursive swap the adjacent elements of a linked list. I am losing the pointer to every second element after the swap.
The input is 1->2->3->4->5->6->7, I expected the output 2->1->4->3->6->5->7,
but my output is 1->3->5->7.
void nodelist::swap(node* head)
{
node* temp = head->next;
if (head->next!= nullptr)
{
node* temp2 = temp->next;
temp->next = head;
head->next = temp2;
head = head->next;
temp = nullptr;
temp2 = nullptr;
swap(head);
}
}
Any help would be appreciated,thanks in advance.
In fact it is enough to swap only the data members of nodes. There is no need to swap the pointers themselves.
Nevertheless if to use your approach then the function can look like
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
Here is a demonstrative program
#include <iostream>
#include <utility>
struct node
{
int value;
node *next;
};
node * AddNode( node *head, int value )
{
head = new node { value, head };
return head;
}
void PrintList( node *head )
{
for ( ; head != nullptr; head = head->next )
{
std::cout << head->value << ' ';
}
}
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
int main()
{
node *head = nullptr;
for ( int i = 10; i != 0; )
{
head = AddNode( head, --i );
}
PrintList( head );
std::cout << std::endl;
SwapList( head );
PrintList( head );
std::cout << std::endl;
return 0;
}
The output is
0 1 2 3 4 5 6 7 8 9
1 0 3 2 5 4 7 6 9 8
You can use the shown function as a template (or base) for your function.
With no recursion:
void swap(node **head)
{
while (*head && (*head)->next)
{
node* tmp = *head;
*head = tmp->next;
tmp->next = (*head)->next;
(*head)->next = tmp;
head = &tmp->next;
}
}
Invoke swap( & list_head_ptr).
Alternatively, you can pass the head pointer by reference-to-pointer and utilize a local pointer-to-pointer member:
void swap(node*& head)
{
node **pp = &head;
while (*pp && (*pp)->next)
{
node* tmp = *pp;
*pp = tmp->next;
tmp->next = (*pp)->next;
(*pp)->next = tmp;
pp = &tmp->next;
}
}
and invoke as swap(list_head_ptr). Either method works.
Using recursion:
void nodelist::swap(node** head) {
if (!*head || !(*head)->next) return;
node* const sw = (*head)->next;
(*head)->next = sw->next;
sw->next = *head;
*head = sw;
swap(&(sw->next->next));
}
If head is the pointer which stores the address of firstNode (value=1), then try following function:
void nodelist::swap(node* head){
node* temp = head->next; //head->next is first-node which needs to switch with it's next node
if (temp!= nullptr && temp->next!=nullptr){
head->next=temp->next; //move second node to first
temp->next = head->next->next; //put second's next in first's
head->next->next = temp; //and first will be second's next
temp = nullptr; // swaping done
swap(head->next->next); //do it for next couple
}
}
http://coliru.stacked-crooked.com/a/e1cc0d02b5599da4
OR
http://coliru.stacked-crooked.com/a/a1e200b687825d80
If head itself is the firstNode (value=1), then passing head by value will not work, either you need to pass it by address/reference OR do it like in following link:
http://coliru.stacked-crooked.com/a/a1e200b687825d80