C Linked List Data Structure Explained with an Example C Program

Linked list is one of the fundamental data structures in C.

Knowledge of linked lists is must for C programmers. This article explains the fundamentals of C linked list with an example C program.

Linked list is a dynamic data structure whose length can be increased or decreased at run time.

How Linked lists are different from arrays? Consider the following points :

  • An array is a static data structure. This means the length of array cannot be altered at run time. While, a linked list is a dynamic data structure.
  • In an array, all the elements are kept at consecutive memory locations while in a linked list the elements (or nodes) may be kept at any location but still connected to each other.

When to prefer linked lists over arrays? Linked lists are preferred mostly when you don’t know the volume of data to be stored. For example, In an employee management system, one cannot use arrays as they are of fixed length while any number of new employees can join. In scenarios like these, linked lists (or other dynamic data structures) are used as their capacity can be increased (or decreased) at run time (as an when required).

How linked lists are arranged in memory?

Linked list basically consists of memory blocks that are located at random memory locations. Now, one would ask how are they connected or how they can be traversed? Well, they are connected through pointers. Usually a block in a linked list is represented through a structure like this :

struct test_struct
{
    int val;
    struct test_struct *next;
};

So as you can see here, this structure contains a value ‘val’ and a pointer to a structure of same type. The value ‘val’ can be any value (depending upon the data that the linked list is holding) while the pointer ‘next’ contains the address of next block of this linked list. So linked list traversal is made possible through these ‘next’ pointers that contain address of the next node. The ‘next’ pointer of the last node (or for a single node linked list) would contain a NULL.

How a node is created?

A node is created by allocating memory to a structure (as shown in above point) in the following way :

struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct));

So, as we can see above, the pointer ‘ptr’ now contains address of a newly created node. If the linked list is empty and first node is created then it is also known as head node.

Once a node is created, then it can be assigned the value (that it is created to hold) and its next pointer is assigned the address of next node. If no next node exists (or if its the last node) then as already discussed, a NULL is assigned. This can be done in following way :

...
...
ptr->val = val;
ptr->next = NULL;
...
...

How to search a node in a linked list?

Searching a node means finding the node that contains the value being searched. This is in fact a very simple task if we talk about linear search (Note that there can be many search algorithms). One just needs to start with the first node and then compare the value which is being searched with the value contained in this node. If the value does not match then through the ‘next’ pointer (which contains the address of next node) the next node is accessed and same value comparison is done there. The search goes on until last node is accessed or node is found whose value is equal to the value being searched. A code snippet for this may look like :

...
...
...
    while(ptr != NULL)
    {
        if(ptr->val == val)
        {
            found = true;
            break;
        }
        else
        {
            ptr = ptr->next;
        }
    }
...
...
...

How a node is deleted?

A node is deleted by first finding it in the linked list and then calling free() on the pointer containing its address. If the deleted node is any node other than the first and last node then the ‘next’ pointer of the node previous to the deleted node needs to be pointed to the address of the node that is just after the deleted node. Its just like if a person breaks away from a human chain then the two persons (between whom the person was) needs to join hand together to maintain the chain.

A Practical C Linked List Example

Here is a practical example that creates a linked list, adds some nodes to it, searches and deletes nodes from it.

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

struct test_struct
{
    int val;
    struct test_struct *next;
};

struct test_struct *head = NULL;
struct test_struct *curr = NULL;

struct test_struct* create_list(int val)
{
    printf("\n creating list with headnode as [%d]\n",val);
    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct));
    if(NULL == ptr)
    {
        printf("\n Node creation failed \n");
        return NULL;
    }
    ptr->val = val;
    ptr->next = NULL;

    head = curr = ptr;
    return ptr;
}

struct test_struct* add_to_list(int val, bool add_to_end)
{
    if(NULL == head)
    {
        return (create_list(val));
    }

    if(add_to_end)
        printf("\n Adding node to end of list with value [%d]\n",val);
    else
        printf("\n Adding node to beginning of list with value [%d]\n",val);

    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct));
    if(NULL == ptr)
    {
        printf("\n Node creation failed \n");
        return NULL;
    }
    ptr->val = val;
    ptr->next = NULL;

    if(add_to_end)
    {
        curr->next = ptr;
        curr = ptr;
    }
    else
    {
        ptr->next = head;
        head = ptr;
    }
    return ptr;
}

struct test_struct* search_in_list(int val, struct test_struct **prev)
{
    struct test_struct *ptr = head;
    struct test_struct *tmp = NULL;
    bool found = false;

    printf("\n Searching the list for value [%d] \n",val);

    while(ptr != NULL)
    {
        if(ptr->val == val)
        {
            found = true;
            break;
        }
        else
        {
            tmp = ptr;
            ptr = ptr->next;
        }
    }

    if(true == found)
    {
        if(prev)
            *prev = tmp;
        return ptr;
    }
    else
    {
        return NULL;
    }
}

int delete_from_list(int val)
{
    struct test_struct *prev = NULL;
    struct test_struct *del = NULL;

    printf("\n Deleting value [%d] from list\n",val);

    del = search_in_list(val,&prev);
    if(del == NULL)
    {
        return -1;
    }
    else
    {
        if(prev != NULL)
            prev->next = del->next;

        if(del == curr)
        {
            curr = prev;
        }
        else if(del == head)
        {
            head = del->next;
        }
    }

    free(del);
    del = NULL;

    return 0;
}

void print_list(void)
{
    struct test_struct *ptr = head;

    printf("\n -------Printing list Start------- \n");
    while(ptr != NULL)
    {
        printf("\n [%d] \n",ptr->val);
        ptr = ptr->next;
    }
    printf("\n -------Printing list End------- \n");

    return;
}

int main(void)
{
    int i = 0, ret = 0;
    struct test_struct *ptr = NULL;

    print_list();

    for(i = 5; i<10; i++)
        add_to_list(i,true);

    print_list();

    for(i = 4; i>0; i--)
        add_to_list(i,false);

    print_list();

    for(i = 1; i<10; i += 4)
    {
        ptr = search_in_list(i, NULL);
        if(NULL == ptr)
        {
            printf("\n Search [val = %d] failed, no such element found\n",i);
        }
        else
        {
            printf("\n Search passed [val = %d]\n",ptr->val);
        }

        print_list();

        ret = delete_from_list(i);
        if(ret != 0)
        {
            printf("\n delete [val = %d] failed, no such element found\n",i);
        }
        else
        {
            printf("\n delete [val = %d]  passed \n",i);
        }

        print_list();
    }

    return 0;
}

In the code above :

  • The first node is always made accessible through a global ‘head’ pointer. This pointer is adjusted when first node is deleted.
  • Similarly there is a ‘curr’ pointer that contains the last node in the list. This is also adjusted when last node is deleted.
  • Whenever a node is added to linked list, it is always checked if the linked list is empty then add it as the first node.

Also, as you see from the above Linked list example, it also uses pointers. If you are new to C programming, you should understand the fundamentals of C pointers.

The output of the above code looks like :

$ ./ll

 -------Printing list Start------- 

 -------Printing list End------- 

 creating list with headnode as [5]

 Adding node to end of list with value [6]

 Adding node to end of list with value [7]

 Adding node to end of list with value [8]

 Adding node to end of list with value [9]

 -------Printing list Start------- 

 [5] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Adding node to beginning of list with value [4]

 Adding node to beginning of list with value [3]

 Adding node to beginning of list with value [2]

 Adding node to beginning of list with value [1]

 -------Printing list Start------- 

 [1] 

 [2] 

 [3] 

 [4] 

 [5] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Searching the list for value [1] 

 Search passed [val = 1]

 -------Printing list Start------- 

 [1] 

 [2] 

 [3] 

 [4] 

 [5] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Deleting value [1] from list

 Searching the list for value [1] 

 delete [val = 1]  passed 

 -------Printing list Start------- 

 [2] 

 [3] 

 [4] 

 [5] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Searching the list for value [5] 

 Search passed [val = 5]

 -------Printing list Start------- 

 [2] 

 [3] 

 [4] 

 [5] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Deleting value [5] from list

 Searching the list for value [5] 

 delete [val = 5]  passed 

 -------Printing list Start------- 

 [2] 

 [3] 

 [4] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Searching the list for value [9] 

 Search passed [val = 9]

 -------Printing list Start------- 

 [2] 

 [3] 

 [4] 

 [6] 

 [7] 

 [8] 

 [9] 

 -------Printing list End------- 

 Deleting value [9] from list

 Searching the list for value [9] 

 delete [val = 9]  passed 

 -------Printing list Start------- 

 [2] 

 [3] 

 [4] 

 [6] 

 [7] 

 [8] 

 -------Printing list End-------

As you see from the above output, it does all the fundamental Linked list operations. It creates a linked list, adds some nodes to it, searches and deletes nodes from it.


转自:http://www.thegeekstuff.com/2012/08/c-linked-list-example/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值