I've done plenty of corrections of the previous code. Dangling pointers seem a fixed problem (correct me If I'm mistaken). The swap/reverse functions are going to be changed soon due to high time complexity. Also the LinkedList_Find()
function is not enough specialized for different types of data, such as Person, because it simply compares void
pointers: the intention was to write general purpose code, the choice of making this current linked list of type Person was done to show the adaptability of void*
to all types (sorry for my influence of java generics :p). Any suggestions and corrections on design patterns and more efficient code are highly appreciated.
LinkedList.h
#ifndef NYO_LINKED_LIST
#define NYO_LINKED_LIST
#include "stdbool.h"
#include "stdio.h"
#include "stdlib.h"
typedef struct Node
{
void *data;
struct Node *next;
} Node;
typedef struct LinkedList {
Node *head, *tail;
int length;
} LinkedList;
bool LinkedList_Init(LinkedList*);
bool LinkedList_Add(LinkedList*, Node*);
Node* createNode(void*);
bool LinkedList_PushFront(LinkedList*, Node*);
void* LinkedList_GetDataAt(LinkedList*,int);
Node *getNode(LinkedList*,int);
bool LinkedList_DeleteLast(LinkedList*);
bool LinkedList_Find(LinkedList*,void*);
void LinkedList_Reverse(LinkedList*, void(*)(int*,int*));
void LinkedList_Clear(LinkedList*);
bool LinkedList_InsertAt(LinkedList*,int,void*);
bool LinkedList_DeleteAt(LinkedList*,int);
void LinkedList_Free(LinkedList*);
#endif
LinkedList.c
#include "LinkedList.h"
#define DEBUG
#undef DEBUG
bool LinkedList_Init(LinkedList *list)
{
list->head = NULL;
list->tail = list->head;
list->length = 0;
return true;
}
bool LinkedList_Add(LinkedList *list, Node* node)
{
if(list->head!=NULL)
{
list->tail->next = node;
}
else
{
list->head = node;
}
list->tail = node;
++list->length;
return true;
}
Node* createNode(void* data)
{
Node *tmp = (Node*)malloc(sizeof(Node));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
bool LinkedList_PushFront(LinkedList *list, Node* node)
{
if(list->head==NULL){
LinkedList_Add(list, node);
} else {
node->next = list->head;
list->head = node;
++list->length;
}
return true;
}
void* LinkedList_GetDataAt(LinkedList *list, int index)
{
Node *tmp = list->head;
int count = 0;
if(index >= 0 && index < list->length)
{
while(tmp!=NULL)
{
if(count == index) return tmp->data;
++count;
tmp = tmp->next;
}
}
return 0;
}
Node *getNode(LinkedList *list, int index)
{
Node *tmp = list->head;
int count = 0;
if(index >= 0 && index < list->length)
{
while(tmp!=NULL)
{
if(count == index) return tmp;
++count;
tmp = tmp->next;
}
}
return NULL;
}
bool LinkedList_DeleteLast(LinkedList *list)
{
Node *tmp = list->head;
int i;
Node *beforeLast;
if(list->length>1)
{
for (i = 0; i < list->length; ++i)
{
if(i == list->length-2)
{
beforeLast = tmp;
}
tmp = tmp->next;
}
free(beforeLast->next);
beforeLast->next = NULL;
list->tail = beforeLast;
}
else
{
free(list->head);
LinkedList_Init(list);
}
if(list->length>0)
{
--list->length;
}
return true;
#ifdef DEBUG
printf("Actual length -> [%d]\n",list->length);
#endif
}
bool LinkedList_Find(LinkedList *list, void* toFind)
{
Node *tmp = list->head;
while(tmp!=NULL)
{
if(toFind==tmp->data) return true;
tmp = tmp->next;
}
return false;
}
void LinkedList_Reverse(LinkedList *list, void(*swap)(int*,int*))
{
int len, i;
for (i = 0, len = list->length-1; i < len; ++i, --len)
{
swap((int*)getNode(list,i), (int*)getNode(list,len));
}
}
bool LinkedList_InsertAt(LinkedList *list, int index, void* data)
{
Node *tmp = list->head;
Node *newNode = createNode(data);
Node *left, *right;
int count = 0;
if(index > list->length) return false;
if(index == 0) LinkedList_PushFront(list,createNode(data));
else if (index == list->length) LinkedList_Add(list,createNode(data));
else if(index > 0 && index < list->length)
{
{
while(tmp!=NULL)
{
left = tmp;
right = tmp->next;
if(count == index - 1)
{
left->next = newNode;
newNode->next = right;
++list->length;
break;
}
++count;
tmp = tmp->next;
}
}
}
return true;
}
bool LinkedList_DeleteAt(LinkedList *list, int index)
{
Node *left, *right;
Node *tmp = list->head;
int count = 0;
if(index > list->length) return false;
if(index > 0 && index < list->length-1)
{
while(tmp!=NULL)
{
left = tmp;
right = tmp->next;
if(count == index-1)
{
#ifdef DEBUG
printf("left -> %d right -> %d\n", left->data, right->data);
#endif
left->next = right->next;
free(right);
right = NULL;
break;
}
++count;
tmp = tmp->next;
}
--list->length;
}
else if (index == list->length-1)
{
LinkedList_DeleteLast(list);
}
else if(index == 0)
{
if(list->length > 1)
{
list->head = list->head->next;
free(tmp);
tmp = NULL;
--list->length;
}
else
{
LinkedList_DeleteLast(list);
}
}
return true;
}
void LinkedList_Free(LinkedList *list)
{
LinkedList_Clear(list);
free(list);
list = NULL;
}
void LinkedList_Clear(LinkedList *list)
{
while(list->head!=NULL)
{
LinkedList_DeleteAt(list,0);
}
}
Main.c
#include "LinkedList.h"
#define MAXSIZE 4
void swap(int*,int*);
void showData(LinkedList*);
typedef struct Person
{
const char* name;
int age;
} Person;
int main(int argc, char const *argv[])
{
Person defaultUsers[MAXSIZE];
int i;
for(i = 0; i < MAXSIZE; i++)
{
defaultUsers[i].age = i;
defaultUsers[i].name = "__generic__user__";
}
LinkedList *list = (LinkedList*)malloc(sizeof(LinkedList));
if(LinkedList_Init(list))
{
for(i = 0; i < MAXSIZE; i++)
{
LinkedList_Add(list,createNode((Person*)&defaultUsers[i]));
}
LinkedList_Reverse(list,&swap);
showData(list);
LinkedList_Free(list);
}
return 0;
}
void showData(LinkedList *list)
{
int i;
for(i = 0; i < list->length; i++)
{
printf("%s is %d\n",(*((Person*)LinkedList_GetDataAt(list,i))).name, (*((Person*)LinkedList_GetDataAt(list,i))).age);
}
}
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
Node
s when theLinkedList
is freed. \$\endgroup\$LinkedList_Clear
beforeLinkedList_Free
. \$\endgroup\$