Singly Linked List Implementation

In this post, you will see the implementation of a singly linked list. It is one of the main data structures in computer programming.

A singly linked list consists of nodes which are bound to each other with their "next" pointers.

A simple node is represented at least 2 fields. A "next" node pointer and a "data" field.


/*
 * node structure.
 */
struct node {
struct node *next;
int data;

};

Some of the basic methods of a linked list and node data structures are implemented below.

Create a Node Method:


/*
 * node_create()
 * Creates a node.
 */
struct node *node_create(int data)
{
    struct node *n = malloc(sizeof(struct node));
    if (!n) {
        printf("Unable to allocate memory for node\n");
        return NULL;
    }

    n->data = data;
    n->next = NULL;

    return n;

}

Free a Node Method:

/*
 * node_free()
 * Frees a node.
 */
void node_free(struct node *n)
{
    if (!n) {
        return;
    }

    free(n);

}

List Length Get Method:

/*
 * list_lenght_get()
 * Gets the length of a list.
 */
int list_lenght_get(struct node *list)
{
    int count = 0;

    while (list) {
        count++;
        list = list->next;
    }
    return count;

}

Add Head Method with Data:

/*
 * list_add_data_head()
 * Adds a node by data to the head of the linked list.
 */
void list_add_data_head(struct node **list, int data)
{
struct node *n = (struct node *)malloc(sizeof(struct node));
if (!n) {
printf("Unable to allocate memory for node\n");
return;
}

n->data = data;
n->next = *list;
*list = n;

}

Add Tail Method with Data:

/*
 * list_add_data_tail()
 * Adds a node by data to the tail of the linked list.
 */
void list_add_data_tail(struct node **list, int data)
{
struct node *nd = (struct node *)malloc(sizeof(struct node));
if (!nd) {
printf("Unable to allocate memory for node\n");
return;
}

nd->data = data;
nd->next = NULL;

if (!(*list)) {
*list = nd;
return;
}

struct node *n = *list;

while(n->next) {
n = n->next;
}

n->next = nd;

}

Add  a Node to Tail Method:

/*
 * list_add_node_tail()
 * Adds an allocated node to a linled list tail.
 */
void list_add_node_tail(struct node **list, struct node *n)
{
    struct node *curr = *list;

    if (!*list) {
        *list = n;
        return;
    }

    while (curr->next) {
        curr = curr->next;
    }

    curr->next = n;

}

Remove Node by Data:

/*
 * list_remove_node_by_data()
 * Remove a node by data from linked list.
 */
void list_remove_node_by_data(struct node **list, int data)
{
/*
* If list is empty, just return.
*/
if (!*list) {
printf("list is empty\n");
return;
}

/*
* curr is our list head.
*/
struct node *curr = *list;
struct node *tmp;

/*
* If there is multiple occurences at the head of the list,
* remove all of them.
* 1->1->1->5->6->null
*/
while (curr && (curr->data == data)) {
tmp = curr;
*list = curr->next;
curr = *list;
free(tmp);
}

/*
* Check the list. Did we remove all the nodes?
*/
if (!*list) {
printf("list is empty. All the occurences removed from the head\n");
return;
}

/*
* There are more nodes in the list. Check them as well.
* If we find more occurence, prev->next will be bound to curr->next.
*/
struct node *prev = curr;
curr = curr->next;

while (curr) {
if (curr->data == data) {
tmp = curr;
prev->next = curr->next;
curr = curr->next;
free(tmp);
continue;
}

prev = curr;
curr = curr->next;
}

}

Reverse List:

/*
 * list_reverse()
 * Reverses a linked list.
 */
void list_reverse(struct node **list)
{
struct node *prev = NULL;
struct node *curr = *list;
struct node *next_node = *list;

/*
* If list is empty, just return.
*/
if (!*list) {
printf("list is empty\n");
return;
}

while (curr) {
next_node = curr->next;
curr->next = prev;
prev = curr;
curr = next_node;
}
*list = prev;

}

Look Up a Data in the List:

/*
 * list_data_look_up()
 * Look ups a node by a data inside the linked list.
 */
bool list_data_look_up(struct node *list, int data)
{
while (list) {
if (list->data == data) {
return true;
}

list = list->next;
}

return false;

}

Print List:

/*
 * list_print()
 * Prints linked list.
 */
void list_print(struct node *list)
{
if (!list) {
printf("list is empty, cannot print\n");
return;
}

struct node *n = list;

while (n) {
printf("%d->", n->data);
n = n->next;
}

printf("NULL\n");


}

Test Code:

/*
 * Global list object.
 */
struct node *list = NULL;

/*
 * Test Code.
 */
int main(void)
{
printf("Creating link list\n");

list_add_data_head(&list, 1);
list_add_data_head(&list, 1);
list_add_data_tail(&list, 5);
list_add_data_tail(&list, 6);
list_add_data_tail(&list, 1);
list_add_data_tail(&list, 7);
list_add_data_tail(&list, 1);
list_add_data_tail(&list, 12);
list_add_data_tail(&list, 1);

list_print(list);

printf("\nLook up 3 in the list\n");
if (list_data_look_up(list, 3)) {
printf("Yes, list has 3\n");
} else {
printf("No, list does not have 3\n");
}

printf("\nLook up 5 in the list\n");
if (list_data_look_up(list, 5)) {
printf("Yes, list has 5\n");
} else {
printf("No, list does not have 5\n");
}

printf("\nRemove 1s from the list\n");
list_remove_node_by_data(&list, 1);

list_print(list);

printf("\nReverse list\n");
list_reverse(&list);
list_print(list);

return 0;

}

Test Output:

Creating link list
1->1->5->6->1->7->1->12->1->NULL

Look up 3 in the list
No, list does not have 3

Look up 5 in the list
Yes, list has 5

Remove 1s from the list
5->6->7->12->NULL

Reverse list
12->7->6->5->NULL

Source Download:

https://github.com/sezginmurat/list_lib.git


Comments

Popular posts from this blog

How to Use container_of in Linux Kernel Development

Notification Chains in Linux Kernel

Linux Dynamic Debugging