Check if a Linked List is a Palindrome in C

This program demonstrates how to determine whether a singly linked list is a palindrome. A palindrome is a sequence that reads the same forward and backward. The challenge is to efficiently check this condition without converting the entire list into an array.

Program Explanation

The program is built around a linked list node structure and includes functions for adding nodes to the list, checking for palindrome properties, and displaying the list. It utilizes a fast and slow pointer technique to find the middle of the list, then reverses the second half of the list and compares it with the first half.

  • struct Node: Represents each node in the linked list, containing an integer data and a pointer to the next node.
  • push: Adds a new node to the front of the list.
  • isPalindrome: Checks if the list is a palindrome.
  • printList: Displays the content of the linked list.

Source Code


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

struct Node {
    int data;
    struct Node* next;
};

// Function to add a node at the front of the list
void push(struct Node** head_ref, int new_data) {
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}

// Function to check if the linked list is a palindrome
bool isPalindrome(struct Node* head) {
    struct Node *slow_ptr = head, *fast_ptr = head;
    struct Node *second_half, *prev_of_slow_ptr = head;
    struct Node *midnode = NULL;  // To handle odd size list
    bool result = true;  // Initialize result as true

    if (head != NULL && head->next != NULL) {
        // Get the middle of the list
        while (fast_ptr != NULL && fast_ptr->next != NULL) {
            fast_ptr = fast_ptr->next->next;
            prev_of_slow_ptr = slow_ptr;
            slow_ptr = slow_ptr->next;
        }

        // For odd sized lists, skip the middle node
        if (fast_ptr != NULL) {
            midnode = slow_ptr;
            slow_ptr = slow_ptr->next;
        }

        // Reverse the second half of the list
        second_half = slow_ptr;
        prev_of_slow_ptr->next = NULL;  // NULL terminate the first half
        struct Node* prev = NULL;
        struct Node* current = second_half;
        struct Node* next;
        while (current != NULL) {
            next = current->next;
            current->next = prev;
            prev = current;
            current = next;
        }
        second_half = prev;

        // Compare the two halves
        while (head != NULL && second_half != NULL) {
            if (head->data != second_half->data) {
                result = false;
                break;
            }
            head = head->next;
            second_half = second_half->next;
        }

        // Reconstruct the original list by reversing the second half again
        if (midnode != NULL) {
            prev_of_slow_ptr->next = midnode;
            midnode->next = prev;
        } else {
            prev_of_slow_ptr->next = prev;
        }
    }
    return result;
}

// Function to print nodes in a given linked list
void printList(struct Node* ptr) {
    while (ptr != NULL) {
        printf("%d -> ", ptr->data);
        ptr = ptr->next;
    }
    printf("NULL\\n");
}

int main() {
    struct Node* head = NULL;
    push(&head, 1);
    push(&head, 2);
    push(&head, 3);
    push(&head, 2);
    push(&head, 1);

    printf("Given linked list\\n");
    printList(head);

    if (isPalindrome(head)) {
        printf("Linked list is a palindrome.\\n");
    } else {
        printf("Linked list is not a palindrome.\\n");
    }

    return 0;
}
        

Conclusion

The provided C program checks if a linked list is a palindrome by using a fast and slow pointer technique to efficiently find the middle, reverse the second half, and then compare segments. This method minimizes space complexity by avoiding the need to convert the list into a different data structure and is efficient in terms of time complexity.

 

By Aditya Bhuyan

I work as a cloud specialist. In addition to being an architect and SRE specialist, I work as a cloud engineer and developer. I have assisted my clients in converting their antiquated programmes into contemporary microservices that operate on various cloud computing platforms such as AWS, GCP, Azure, or VMware Tanzu, as well as orchestration systems such as Docker Swarm or Kubernetes. For over twenty years, I have been employed in the IT sector as a Java developer, J2EE architect, scrum master, and instructor. I write about Cloud Native and Cloud often. Bangalore, India is where my family and I call home. I maintain my physical and mental fitness by doing a lot of yoga and meditation.

Leave a Reply

Your email address will not be published. Required fields are marked *

error

Enjoy this blog? Please spread the word :)