C Data Structures - Doubly Linked List Other Related Topics

C - Delete last node by key of the Doubly Linked List



In this method, last node in the doubly linked list with specified key (value) is deleted. For example - if the given List is 10->20->30->20->40 and the last occurrence of 20 is deleted, the List becomes 10->20->30->40.

If the head of the doubly linked list is not null, create three nodes: 1. lastNode - to track the last node with value equal to key, 2. previousToLast - to track node previous to lastNode, and 3. temp - to traverse through the list. Then traverse the list to its end while updating lastNode and previousToLast whenever find a node with value equal to the specified key. At last delete lastNode and update links accordingly.

The function pop_last is created for this purpose. It is a 3-step process.

void pop_last(struct Node** head_ref, int key) {     

  //1. if head is not null create three nodes
  //   lastNode - to track last node with value
  //   equal to key, previousToLast - to track 
  //   node previous to lastNode, temp - to
  //   traverse through the list
  if(*head_ref != NULL) {
    struct Node *previousToLast, *lastNode, *temp; 
    previousToLast = NULL;
    lastNode = NULL;
    
    //2. traverse through the list and keep on updating
    //   lastNode and previousToLast whenever find a node
    //   with value equal to the specified key
    if((*head_ref)->data == key) 
      lastNode = *head_ref;
    
    temp = *head_ref;
    while(temp->next != NULL) {
      if(temp->next->data == key) {
        previousToLast = temp;
        lastNode = temp->next;
      }
      temp = temp->next;
    }
 
    //3. Delete the lastNode and update all links
    if(lastNode != NULL) {
      if(lastNode == *head_ref) {
        *head_ref = (*head_ref)->next;
        free(lastNode);
      } else {
        previousToLast->next = lastNode->next;
        if(previousToLast->next != NULL)
          previousToLast->next->prev = previousToLast;        
        free(lastNode);
      }
    }
  }
}    

The below is a complete program that uses above discussed concept to delete last occurrence of the specified key (if exists) of the doubly linked list.

#include <stdio.h>
#include <stdlib.h>

//node structure
struct Node {
  int data;
  struct Node* next;
  struct Node* prev;
};

//Add new element at the end of the list
void push_back(struct Node** head_ref, int newElement) {  
  struct Node *newNode, *temp;
  newNode = (struct Node*)malloc(sizeof(struct Node)); 
  newNode->data = newElement;  
  newNode->next = NULL;
  newNode->prev = NULL;
  if(*head_ref == NULL) {
    *head_ref = newNode;
  } else {
    temp = *head_ref;
    while(temp->next != NULL) {
      temp = temp->next;
    }    
    temp->next = newNode;
    newNode->prev = temp;
  }
}

//Delete last node by key
void pop_last(struct Node** head_ref, int key) {     

  if(*head_ref != NULL) {
    struct Node *previousToLast, *lastNode, *temp; 
    previousToLast = NULL;
    lastNode = NULL;

    if((*head_ref)->data == key) 
      lastNode = *head_ref;
    
    temp = *head_ref;
    while(temp->next != NULL) {
      if(temp->next->data == key) {
        previousToLast = temp;
        lastNode = temp->next;
      }
      temp = temp->next;
    }

    if(lastNode != NULL) {
      if(lastNode == *head_ref) {
        *head_ref = (*head_ref)->next;
        free(lastNode);
      } else {
        previousToLast->next = lastNode->next;
        if(previousToLast->next != NULL)
          previousToLast->next->prev = previousToLast;        
        free(lastNode);
      }
    }
  }
}  

//display the content of the list
void PrintList(struct Node* head_ref) {
  struct Node* temp = head_ref;
  if(head_ref != NULL) {
    printf("The list contains: ");
    while (temp != NULL) {
      printf("%i ",temp->data);
      temp = temp->next;  
    }
    printf("\n");
  } else {
    printf("The list is empty.\n");
  }   
}

// test the code
int main() {
  struct Node* MyList = NULL;

  //Add five elements at the end of the list.
  push_back(&MyList, 10);
  push_back(&MyList, 20);
  push_back(&MyList, 30);
  push_back(&MyList, 20);
  push_back(&MyList, 40);
  PrintList(MyList);

  //Delete the last occurrence of 20
  pop_last(&MyList, 20);
  PrintList(MyList);  

  return 0; 
}

The above code will give the following output:

The list contains: 10 20 30 20 40 
The list contains: 10 20 30 40