I recently learned about linked lists and here is my first try to write one in C. I know it's a lot of code, but I hope someone takes a look. Any tips memory allocation and improvements are welcome.
SinglyLinkedList.h
#ifndef SINGLYLINKEDLIST_
#define SINGLYLINKEDLIST_
#include <stdlib.h>
#include <stdio.h>
typedef struct SLNode SLNode;
typedef struct SLList SLList;
struct SLNode {
void *data;
SLNode *next;
};
struct SLList {
size_t size;
SLNode *head;
};
SLList *createSLList(void);
SLNode *createSLNode(void *data);
// OPERATIONS
int addSLNode(SLList *list, SLNode *node, size_t positon);
int removeSLNode(SLList *list, size_t position);
int containsData(SLList *list, void *data, int compare(void *, void*));
void clearSLList(SLList *list);
// FREEING
void freeSLList(SLList *list);
void freeSLNode(SLNode *node);
// UTILS
void printSLList(SLList *list, void printSLNode(SLNode *));
#endif
SinglyLinkedList.c
#include "SinglyLinkedList.h"
/**
* createSLNode: Stores passed data in SLNode and
* returns pointer to node.
*
* @param data Data to store in node. This data should be
* allocated with malloc/calloc/etc., since
* free is used in freeSLNode.
*
* @return Pointer to created SLNode.
* NULL if memory allocation failed.
*/
SLNode *createSLNode(void *data) {
SLNode *node = malloc(sizeof(SLNode));
if (node == NULL) {
return NULL;
}
node->data = data;
node->next = NULL;
return node;
}
/**
* createSLList: Allocates space for an SLList and
* assigns default values (list->head: NULL,
* list->size: 0)
*
* @return Pointer to creates SLList.
* Null if memory allocation failed.
*/
SLList *createSLList(void) {
SLList *list = malloc(sizeof(SLList));
if (list == NULL) {
return NULL;
}
list->head = NULL;
list->size = 0;
return list;
}
/**
* addSLNode: Adds SLNode to SLList at passed index.
*
* @param list SLList to add node to.
* @param node SLNode which should be added to list.
* @param index Index at which the node should be added
* to list.
*
* @return 0 for success,
* 1 for failure (NULL-arguments, invalid index)
*/
int addSLNode(SLList *list, SLNode *node, size_t index) {
if (list == NULL || node == NULL) {
return -1;
} else if (index > list->size) {
return -1;
} else {
if (index == 0) {
node->next = list->head;
list->head = node;
} else {
SLNode *tmp = list->head;
size_t currIndex = 0;
while (currIndex < index-1) {
tmp = tmp->next;
currIndex++;
}
node->next = tmp->next;
tmp->next = node;
}
list->size++;
return 0;
}
}
/**
* removeSLNode: Remove element at specific index
* in SLList.
*
* @param list SLList to remove element from.
* @param index Index of element to remove.
*
* @return 0 for success.
* 1 for failure (NULL-arguments, invalid index)
*/
int removeSLNode(SLList *list, size_t index) {
if (list == NULL) {
return -1;
} else if (index >= list->size) {
return -1;
} else {
if (index == 0) {
if (list->size == 1) {
freeSLNode(list->head);
list->head = NULL;
} else {
SLNode *tmp = list->head->next;
freeSLNode(list->head);
list->head = tmp;
}
} else {
SLNode *tmp = list->head;
size_t pos = 0;
while (pos < index-1) {
tmp = tmp->next;
pos++;
}
SLNode *del = tmp->next;
tmp->next = del->next;
freeSLNode(del);
}
list->size--;
return 0;
}
}
/**
* containsData: Checks if SLList contains specific data/element.
*
* @param list SLList to search in.
* @param data Data to compare with.
* @param compare Pointer to function, which is used
* to test for equality.
*
* @return 1 if the list contains the passed data according
* to the passed compare function.
* 0 otherwise (not contained/ NULL passed as list).
*/
int containsData(SLList *list, void *data, int compare(void *, void*)) {
if (list == NULL) {
return 0;
}
SLNode *node = list->head;
while (node != NULL) {
if (compare(data, node->data)) {
return 1;
}
node = node->next;
}
return 0;
}
/**
* freeSLNode: Frees SLNode and contained data.
*
* @param node SLNode to free.
*/
void freeSLNode(SLNode *node) {
if (node == NULL) {
return;
}
free(node->data);
free(node);
}
/**
* clearSLList: Removes/frees all nodes in SLList.
* The data of the nodes is freed as well.
*
* @param list SLList to clear.
*/
void clearSLList(SLList *list) {
if (list == NULL) {
return;
} else {
SLNode *curr = list->head;
while (curr != NULL) {
SLNode *tmp = curr->next;
freeSLNode(curr);
curr = tmp;
}
list->head = NULL;
list->size = 0;
}
}
/**
* freeSLList: Removes/frees all nodes in SLList and
* frees SLList afterwards.
*
* @param list SLList to free.
*/
void freeSLList(SLList *list) {
if (list == NULL) {
return;
}
clearSLList(list);
free(list);
}
static void printSLArrow();
/**
* printSLList: Prints an SLList (debug as main purpose).
*
* @param list SLList to print.
* @param printSLNode Pointer to function,
* which prints a single SLNode.
*/
void printSLList(SLList *list, void printSLNode(SLNode *)) {
if (list == NULL) {
return;
}
SLNode *tmp = list->head;
while (tmp != NULL) {
printSLNode(tmp);
printSLArrow();
tmp = tmp->next;
}
printf("NULL\n");
}
void printSLArrow() {
printf("-->");
}