I have implemented few functions of a linked list. Feedback is welcome. Please note I have specifically avoided using pointer to pointers.
#include <stdio.h>
#include <stdlib.h>
// Node data structure inside the linked list.
struct node {
int data;
struct node* next;
};
struct node* BuildOneTwoThree(void);
void printList(struct node * head);
int getListLength(struct node * head);
struct node* insertAtFront(struct node * const head, int value);
int getAt(struct node * head, int index, int *);
struct node* insertAtBack(struct node* head, int value);
int main() {
// Create sample linked list and obtain pointer to the head.
struct node * head = NULL;
head = insertAtBack(head, 700);
head = insertAtFront(head, 12);
head = insertAtFront(head, 3);
head = insertAtFront(head, 5);
head = insertAtFront(head, 55);
head = insertAtBack(head, 333);
printList(head);
printf("List length is: %d\n", getListLength(head));
return 0;
}
///
//
// Create a sample linked list with three nodes
// connected to each other.
//
// Parameter:
// nothing.
// Return
// pointer to the head of the linked list that was built.
//
struct node* BuildOneTwoThree(void)
{
struct node * one = NULL;
struct node * two = NULL;
struct node * three = NULL;
//
// Allocate memory for (three) nodes
//
one = malloc(sizeof(struct node));
if(one == NULL) return NULL;
two = malloc(sizeof(struct node));
if(two == NULL)
{
free(one);
return NULL;
}
three = malloc(sizeof(struct node));
if(three == NULL)
{
free(one);
free(two);
return NULL;
}
// Set data values for each node
one->data = 1;
two->data = 2;
three->data = 3;
// Chain nodes
one->next = two;
two->next = three;
three->next = NULL;
// Return pointer to head node
return one;
}
///
//
// Print contents of each node in the linked list.
//
// Parameter:
// head: pointer to the head of the node
// Return
// nothing. Prints content of each node on console.
//
void printList(struct node * head)
{
int i = 0;
int x = 0;
// If the list is empty, there is nothing to print.
if(NULL == head)
return;
// First let's get number of nodes in the linked list.
int length = getListLength(head);
// Let's iterate over the nodes now.
for(i = 0; i<length; i++)
{
// Get value of i-th node
if(-1 == getAt(head, i, &x))
break;
printf("%d \n", x);
}
}
///
//
// Get number of nodes in the linked list.
//
// Parameter:
// head: pointer to the head of the node
// Return
// number of nodes in the linked list.
//
int getListLength(struct node * head)
{
int size = 0;
// If head pointer is NULL - the size of the list is 0.
if(NULL == head)
return size;
while(1)
{
// Since head is not NULL, there is at least one node in the list.
size++;
// Move to the next node
head = head->next;
// If the next node is NULL, stop.
if(head == NULL)
return size;
}
}
///
//
// Insert new node in the beginning of the linked list.
//
// Parameter:
// head: pointer to the head of the node
// value: value for the new linked list node
// Return
// Pointer to the linked list which contains the added node in the beginning.
//
struct node* insertAtFront(struct node * const head, int value)
{
// Create a new node - and check if creation was success
struct node* result = malloc(sizeof(struct node));
if(result == NULL) return NULL;
result->next = NULL;
// If head is NULL, just return the new node.
if(head == NULL)
{
result->data = value;
return result;
}
// Otherwise make the new node point where head was pointing, and return the new node as new head
result->next = head;
result->data = value;
return result;
}
///
//
// Get element at some index. Index starts from 0.
//
// Parameter:
// head: pointer to the head of the node
// index: 0 based index of element we wish to retrieve
// value: [out] parameter where the value of the node found will be written
// Return
// -1 on error 0 on success.
//
int getAt(struct node * head, int index, int * value)
{
int currIndex = 0;
// Make sure requested index of element is not out of bounds
if(index >= getListLength(head))
return -1;
// If the head pointer is NULL, there is no point in searching further.
if(head == NULL)
{
return -1;
}
// Start an infinite loop
while(1)
{
if(index == currIndex)
{
*value = head->data; // Return value of the index-th element
return 0;
}
head = head->next;
currIndex++;
}
}
struct node* insertAtBack(struct node* head, int value)
{
struct node * current = head;
int length = 0;
int i = 0;
// Create a new node - and check if creation was success
struct node* result = malloc(sizeof(struct node));
if(result == NULL) return NULL;
result->next = NULL;
result->data = value;
// If initial list is empty just return the new node.
if(current == NULL)
{
return result;
}
// Get list length
length = getListLength(current);
for(i = 0; i < length - 1; i++)
{
current = current->next;
}
current->next = result;
return head;
}