Skip to content

Instantly share code, notes, and snippets.

@storca
Last active November 13, 2021 11:03
Show Gist options
  • Save storca/d9e7c26be3ce1d1e3ba8860f432a78d2 to your computer and use it in GitHub Desktop.
Save storca/d9e7c26be3ce1d1e3ba8860f432a78d2 to your computer and use it in GitHub Desktop.
Single Linked list in C
/**
* @file sllist.c
* @author storca (storca@mail.com)
* @brief Generic implementation of a single-linked list
* Cells are added to the left, and deleted on the right
* @date 2021-11-11
*
* Illustration
*
* list_add(aa)
* list_add(bb)
* list_add(cc)
*
* list --> |C cc| --> |B bb| --> |A aa|
*/
#include <stdlib.h>
#include <string.h> //memcpy
#include <stdio.h>
struct Cell;
typedef struct {
char* content;
struct Cell *next; //next is on the right of this cell
} Cell;
typedef struct {
Cell *first;
uint lengh;
size_t type_size;
} List;
Cell* cell_init(char* content, Cell *next, size_t type_size)
{
Cell *cell;
cell = (Cell*) malloc(sizeof(Cell)); //allocate a new cell
cell->next = next;
cell->content = malloc(type_size); //allocate space for the content of the cell
memcpy(cell->content, content, type_size); //copy the content to the newly created cell
return cell;
}
Cell* cell_fetch_recursivly(Cell *cell)
{
if(cell->next == NULL)
{
return cell; //I am the last one ;(
}
else
{
return cell_fetch_recursivly(cell->next);
}
}
/**
* @brief Fetch the cell situated before the last cell
*
* @param cell Cell from which to start
* @return Cell* The cell before the last cell
*/
Cell* cell_fetch(Cell *cell)
{
Cell *curr = cell;
Cell *prev = NULL;
while(curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
return prev;
}
void cell_free(Cell *cell)
{
free(cell->content); //free the contents of the cell
//free(cell->next);
free(cell); //free the space reserved by the cell
}
List* list_init(size_t type_size)
{
List *list = malloc(sizeof(List));
list->lengh = 0;
list->first = NULL;
list->type_size = type_size;
return list; //return a pointer to the newly allocated list
}
int list_is_empty(List *list)
{
return list->lengh < 1;
}
void list_add(List *list, char* content)
{
list->first = cell_init(content, list->first, list->type_size);
list->lengh += 1;
}
/**
* @brief Returns a pointer to the last element of the list
* And removes the cell in which the item was contained
*
* @param list
* @return char*
*/
char* list_remove(List *list)
{
if(!list_is_empty(list))
{
Cell *before_last = cell_fetch(list->first);
Cell *curr;
if(before_last == NULL)
{
curr = list->first;
}
else
{
curr = before_last->next;
before_last->next = NULL;
}
char* content = curr->content;
cell_free(curr);
list->lengh -= 1;
return content;
}
}
void list_print(List *list)
{
Cell *curr = list->first;
printf("list --> ");
while (curr->next != NULL)
{
printf("|cell %p| --> ", (void*)curr);
curr = curr->next;
}
printf("NULL (end)\n");
}
/**
* @brief Return the last element of the list
*
* @param list
* @return char*
*/
char* list_last(List *list)
{
char* content;
Cell *last = cell_fetch_recursivly(list->first);
content = last->content;
return content;
}
/**
* @brief Delete a list and deallocate all of it's contents
* Complexity is O(n)
*
* @param list
*/
void list_delete(List *list)
{
if(list->lengh > 0)
{
//Free each cell on the list
Cell *curr = list->first;
Cell *next = NULL;
while (curr->next != NULL)
{
next = curr->next;
cell_free(curr);
curr = next;
}
cell_free(curr); //do not forget the last cell
}
free(list);
}
int main()
{
int data[20];
List *list = list_init(sizeof(int));
for (size_t i = 0; i < 20; i++)
{
data[i] = i*23;
list_add(list, (char*)&data[i]);
}
list_print(list);
printf("list_remove : %i\n", *(int*)list_remove(list));
printf("list_last : %i\n", *(int*)list_last(list));
list_delete(list);
printf("List size : %i\n", sizeof(List));
printf("Cell size : %i\n", sizeof(Cell));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment