Open In App

Generic Linked List in C

Last Updated : 27 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A generic linked list is a type of linked list that allows the storage of different types of data in a single linked list structure, providing more versatility and reusability in various applications. Unlike C++ and Java, C doesn’t directly support generics. However, we can write generic code using a few tricks.

In this article, we will learn how to create a generic linked list in C so that the same linked list code can be worked with different data types.

How to Create a Generic Linked List in C?

In C, we can use a void pointer and a function pointer to implement the generic functionality. The great thing about void pointers is that they can be used to point to any data type. Also, the size of all types of pointers is always the same, so we can always allocate a linked list node. A function pointer along with the size of the data_type is needed to process actual content stored at the address pointed by the void pointer.

Generic Linked List Node Structure

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

C Program to Implement Generic Linked List

C
// C program for implementing a generic linked list
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Node {
  
    // Any data type can be stored in this node
    void  *data;
    struct Node *next;
};

// Function to insert data at head. This functions requires
// the size of the data type as extra argument
struct Node* insertAtHead(struct Node* head, void *data,
                   size_t data_size) {
  
    // Allocate memory for node
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

    newNode->data = malloc(data_size);
    newNode->next = head;

    // Copy contents of data to newly allocated memory.
    memcpy(newNode->data, data, data_size);

	return newNode;
}

// Function that access and prints the linked list. This function needs
// to know how many bytes of memory is to be read to print the data
// So a function pointer is required for printing different data type
void printList(struct Node *head, void (*fptr)(void *)) {
    while (head != NULL) {
        (*fptr)(head->data);
        head = head->next;
    }
}

// Helper function to print an integer
void printInt(void *n) {
   printf(" %d", *(int *)n);
}

// Helper function to print a float
void printFloat(void *f) {
   printf(" %f", *(float *)f);
}

int main() {

    // Create an int linked list
  	// 10 -> 20 -> 30 -> 40
  	struct Node *head = NULL;
 	unsigned i_size = sizeof(int);
 	int i_arr[4] = {40, 30, 20, 10};
  	head = insertAtHead(head, i_arr, i_size);
  	head = insertAtHead(head, i_arr + 1, i_size);
  	head = insertAtHead(head, i_arr + 2, i_size);
  	head = insertAtHead(head, i_arr + 3, i_size);
    
  
  	// Printing the Integer list
    printf("Created integer linked list is \n");
    printList(head, printInt);
    
    // Create an float linked list
  	// 10.1 -> 20.2 -> 30.3 -> 40.4
  	head = NULL;
 	unsigned f_size = sizeof(float);
 	float f_arr[4] = {40.4, 30.3, 20.2, 10.1};
  	head = insertAtHead(head, f_arr, f_size);
  	head = insertAtHead(head, f_arr + 1, f_size);
  	head = insertAtHead(head, f_arr + 2, f_size);
  	head = insertAtHead(head, f_arr + 3, f_size);
    
  
  	// Printing the Float list
    printf("\n\nCreated float linked list is \n");
    printList(head, printFloat);

    

    return 0;
}

Output
Created integer linked list is 
 10 20 30 40

Created float linked list is 
 10.100000 20.200001 30.299999 40.400002

Time Complexity: O(N), here N is number of nodes in linked list.
Auxiliary Space: O(N)

Advantages of Generic Linked List

  • This linked list handles different data types without changing the implementation.
  • The same linked list structure and functions can be reused across various applications.
  • Only one set of functions needs to be maintained for different data types.

Limitations of Generic Linked List

  • The use of void pointers can lead to type safety issues, requiring careful handling.
  • The implementation can be more complex than specific data type-linked lists due to generic handling.

Conclusion

A generic linked list in C provides a powerful tool for managing collections of various data types. By using void pointers and function pointers, the same linked list implementation can handle different types of data, enhancing flexibility and code reuse. However, it requires careful handling of memory and data types to avoid common pitfalls associated with generic programming in C.



Next Article

Similar Reads