Understanding Data Structures - Linked Lists

A linked list is the most commonly used data structure and the base of other complicated data structures. Linked list is used to store data at runtime or dynamically while program is running.

We all know what linked list is, it is a series of nodes which contains a data and pointer pointing to other nodes. A linked list is accessed by using a pointer or object that points to the head or first node of the linked list.

There are many types of linked lists such as Singly Linked Lists, Doubly Linked Lists, Multiple Linked Lists, Circular Linked Lists, Generic Linked Lists etc. We will implement a linked list in structure oriented languages like C and also in object-oriented languages like C++,C#,Java,Python,VB.Net.

We will also use linked list to implement a simple Student Information System to store data in C#.
 

Let's see some uses of linked lists. 
  • File Systems
  • Memory manager
  • Reading/Writing data from/to peripheral devices such as Computer Screen, Printer, USB Flash drive etc.
  • UI operations like next or previous on applications like Video/Music player, Browser etc.
  • Sending/Receiving packet data over network or also in telecommunication system.
  • Enterprise Application Software(EAS)
  • To implement Stack,Queue,Hash Tables etc., Stack for Undo and Queue for Redo operations etc.
  • Compilers and Interpreters
There are some drawbacks of linked lists, such as random-access, searching, extra memory etc.

All right, let's go through Singly Linked Lists and Doubly Linked Lists. To verify the linked list we will also print the memory location of each node as well as next/prev node. See the thisNode number and validate it that linked list is formed correctly or not.

Singly Linked Lists

A singly linked list contains a data section and a pointer to next node. Data section may contain any kind of data or pointer or class objects. Next section contains the address of the next node or reference of the next node object.

See following image.

This image shows the singly linked list but not how to implement it. This is just the basic image over the internet for linked list. it doesn't describe much of the singly linked list. See the following modified image to understand it.
 

 
Each node is the record that stores some data. A record can be any type such as structures in C or classes in object-oriented languages. A data can be assigned to the each node of pointer or object.

See the following simple implementation of singly linked list in structure-oriented and in object-oriented.

In C and in C++ you must allocate a memory as well as releasing it once you have done with it. Other object-oriented languages support garbage collection, so no need to worry about memory releasing.
 
Structured Oriented (C)

First you must create an empty project in Visual Studio as Visual C++ and then add new item to it. First let's define the structure to store our data or to build an abstract data type.
  1. typedef struct node {  
  2.     int data;  
  3.     struct node *next;  
  4. }Node; 
As shown in the image you can directly assign a same type pointer variable to another pointer variable. In C you have to allocate memory using malloc() function.you can directly allocate memory and assign a data to it or can write a function for it.

Following function assigns data to newnode and next pointer to NULL after allocating memory to it and returns the allocated memory location. You can print a memory location in C using %p format specifier.

Download the source code.
  1. Node *getNewNode(int data)  
  2. {  
  3.     Node *newnode = (Node*)malloc(sizeof(Node));  
  4.     if (newnode != NULL){  
  5.         newnode->data = data;  
  6.         newnode->next = NULL;  
  7.     }  
  8.     return newnode;  

In main function, assign or form the next pointer by assigning other pointer nodes to it as shown in above image. First create a head and set it to NULL.You can directly assign allocated memory node to head by calling getNewNode(). Then create three nodes, assign node_1 to head and form a linked list by assigning pointer nodes to each other. 

You can also write a function for it that can add node to the list. Then we are printing data of each node,you can put it in while loop, as we generally do. Remember we are doing here only pointer assignment and nothing else to form a linked list.
  1. int main()  
  2. {  
  3.     Node *head = NULL;  
  4.     Node *node_1 = getNewNode(10);  
  5.     Node *node_2 = getNewNode(20);  
  6.     Node *node_3 = getNewNode(30);  
  7.     head = node_1;  
  8.     node_1->next = node_2;  
  9.     node_2->next = node_3;  
  10.     node_3->next = NULL;  
  11.     printf("node_1 = %d, node_2 = %d, node_3 = %d\n", head->data, head->next->data, head->next->next->data);  
  12.     getchar();  
  13.     return 0;  
  14. }  
Object Oriented

In object-oriented, the procedure is same as in structure oriented, only difference is to play with objects. First define the class of a node and then the procedure is the same. In object-oriented, you dont need a function like getNewNode(), you can directly allocate memory using new keyword. 
  1. class Node {  
  2.     int data;  
  3.     Node next;  
  4.     public Node(int data){  
  5.         this.data = data;  
  6.         this.next = null;  
  7.     }  
  8. }  
  9.   
  10. class Program{  
  11.     static void Main(string[] args){  
  12.         Node head = null;  
  13.         Node node_1 = new Node(10);  
  14.         Node node_2 = new Node(20);  
  15.         Node node_3 = new Node(30);  
  16.         head = node_1;  
  17.         node_1.next = node_2;  
  18.         node_2.next = node_3;  
  19.         node_3.next = null;  
  20.         Console.WriteLine("node_1 = %d, node_2 = %d, node_3 = %d\n", head.data, head.next.data, head.next.next.data);  
  21.         Console.Read();  
  22.     }  
  23. }  
Doubly Linked Lists

A doubly linked list contains a data section, a pointer to next node and a pointer to the previous node. Data section may contain any kind of data or pointer or class objects. Next section contains the address of the next node or reference of the next node object. Prev section contains the address of the previous node or reference of the previous node object. 

See following image. 
 
It doesn't describe much of the doubly linked list. See the following modified image to understand it.
 

 
Just add only one field to the singly linked list as before. And change pointer or object location of previous pointers or objects as shown in above image.
  1. typedef struct node {  
  2.     int data;  
  3.     struct node *next;  
  4.     struct node *prev;  
  5. }Node; 
  1. class Node {  
  2.     int data;  
  3.     Node next;  
  4.     Node prev;  

Many operations can be applied on linked list according to its uses as described above. We will see only a few operations such as adding node to end or front and deleting front or last node in linked list. We will implement both singly linked list as well as doubly linked list. Let's see the implementation of the linked list in various programming languages.
 
C

Download the source code for C to view the complete code. 
  1. typedef struct sll_node  
  2. {  
  3.     int data;  
  4.     struct sll_node *next;  
  5. }SLL_Node;  
  6.   
  7. typedef struct dll_node  
  8. {  
  9.     int data;  
  10.     struct dll_node *next;  
  11.     struct dll_node *prev;  
  12. }DLL_Node;  
  13.   
  14. SLL_Node *sll_getNewNode(int data)  
  15. {  
  16.     SLL_Node *newnode = NULL;  
  17.     newnode = (SLL_Node*)malloc(sizeof(SLL_Node));  
  18.     if (newnode != NULL){  
  19.         newnode->data = data;  
  20.         newnode->next = NULL;  
  21.     }  
  22.     return newnode;  
  23. }  
  24.   
  25. DLL_Node *dll_getNewNode(int data)  
  26. {  
  27.     DLL_Node *newnode = NULL;  
  28.     newnode = (DLL_Node*)malloc(sizeof(DLL_Node));  
  29.     if (newnode != NULL){  
  30.         newnode->data = data;  
  31.         newnode->next = NULL;  
  32.         newnode->prev = NULL;  
  33.     }  
  34.     return newnode;  
  35. }  
  36.   
  37. typedef struct singly_linked_list{  
  38.   
  39.     SLL_Node *head;  
  40.     SLL_Node*(*getNewNode)(int);  
  41.     void(*addNodeToEnd)(SLL_Node**, int);  
  42.     void(*addNodeToFront)(SLL_Node**, int);  
  43.     void(*deleteLastNode)(SLL_Node**);  
  44.     void(*deleteFrontNode)(SLL_Node**);  
  45.     void(*display)(SLL_Node*);  
  46.   
  47. }SinglyLinkedList;  
  48.   
  49. typedef struct doubly_linked_list{  
  50.   
  51.     DLL_Node *head;  
  52.     DLL_Node*(*getNewNode)(int);  
  53.     void(*addNodeToEnd)(DLL_Node**, int);  
  54.     void(*addNodeToFront)(DLL_Node**, int);  
  55.     void(*deleteLastNode)(DLL_Node**);  
  56.     void(*deleteFrontNode)(DLL_Node**);  
  57.     void(*display)(DLL_Node*);  
  58.   
  59. }DoublyLinkedList;  
  60.   
  61. SinglyLinkedList *initSinglyLinkedList()  
  62. {  
  63.     SinglyLinkedList *s_list = (SinglyLinkedList*)malloc(sizeof(SinglyLinkedList));  
  64.     s_list->head = NULL;  
  65.     s_list->getNewNode = sll_getNewNode;  
  66.     s_list->addNodeToEnd = sll_addNodeToEnd;  
  67.     s_list->addNodeToFront = sll_addNodeToFront;  
  68.     s_list->deleteLastNode = sll_deleteLastNode;  
  69.     s_list->deleteFrontNode = sll_deleteFrontNode;  
  70.     s_list->display = sll_display;  
  71.     return s_list;  
  72. }  
  73.   
  74. DoublyLinkedList *initDoublyLinkedList()  
  75. {  
  76.     DoublyLinkedList *d_list = (DoublyLinkedList*)malloc(sizeof(DoublyLinkedList));  
  77.     d_list->head = NULL;  
  78.     d_list->getNewNode = dll_getNewNode;  
  79.     d_list->addNodeToEnd = dll_addNodeToEnd;  
  80.     d_list->addNodeToFront = dll_addNodeToFront;  
  81.     d_list->deleteLastNode = dll_deleteLastNode;  
  82.     d_list->deleteFrontNode = dll_deleteFrontNode;  
  83.     d_list->display = dll_display;  
  84.     return d_list;  

There is no class in C, but we can implement class in C using pointer to functions and putting it in a structure. The structure singly_linked_list defines all the pointer to function methods. initSinglyLinkedList() and initDoublyLinkedList() initialize the pointer to function by assigning functions to it. And then we can access all functions from the variable of structure SinglyLinkedList or DoublyLinkedList.

C++

Download the source code for C++ to view complete code. 
  1. class SLL_Node{  
  2. public :  
  3.     int data;  
  4.     SLL_Node *next;  
  5.     SLL_Node(int data){  
  6.         this->data = data;  
  7.         this->next = nullptr;  
  8.     }  
  9. };  
  10.   
  11. class DLL_Node{  
  12. public:  
  13.     int data;  
  14.     DLL_Node *next;  
  15.     DLL_Node *prev;  
  16.     DLL_Node(int data){  
  17.         this->data = data;  
  18.         this->next = nullptr;  
  19.         this->prev = nullptr;  
  20.     }  
  21. };  
  22.   
  23. class SinglyLinkedList{  
  24. private:  
  25.     SLL_Node *head = nullptr;  
  26.     SLL_Node *lastNode = nullptr;  
  27.     int count = 0;  
  28. public:  
  29.     void addNodeToEnd(int);  
  30.     void addNodeToFront(int);  
  31.     void deleteLastNode();  
  32.     void deleteFrontNode();  
  33.     int getCount();  
  34.     void display();  
  35. };  
  36.   
  37. class DoublyLinkedList{  
  38. private:  
  39.     DLL_Node *head = nullptr;  
  40.     DLL_Node *lastNode = nullptr;  
  41.     int count = 0;  
  42. public:  
  43.     void addNodeToEnd(int);  
  44.     void addNodeToFront(int);  
  45.     void deleteLastNode();  
  46.     void deleteFrontNode();  
  47.     int getCount();  
  48.     void display();  
  49. }; 
C#

Download the source code for C# to view complete code. C# stores objects in hash tables, so you can print the hash code of the stored object for printing memory location. 

See following display() function. 
  1. class SLL_Node  
  2. {  
  3.     public int data;  
  4.     public SLL_Node next;  
  5.     public SLL_Node(int data){  
  6.         this.data = data;  
  7.         this.next = null;  
  8.     }  
  9. }  
  10.   
  11. class DLL_Node  
  12. {  
  13.     public int data;  
  14.     public DLL_Node next;  
  15.     public DLL_Node prev;  
  16.     public DLL_Node(int data){  
  17.         this.data = data;  
  18.         this.next = null;  
  19.         this.prev = null;  
  20.     }  
  21. }  
  22.   
  23. class SinglyLinkedList  
  24. {  
  25.     private SLL_Node head = null;  
  26.     private SLL_Node lastNode = null;  
  27.     private int count = 0;  
  28.       
  29.     ....  
  30. }  
  31.   
  32. class DoublyLinkedList  
  33. {  
  34.     private DLL_Node head = null;  
  35.     private DLL_Node lastNode = null;  
  36.     private int count = 0;  
  37.     ....  
  38. }  
  39.   
  40. public void display(){  
  41.     SLL_Node current = this.head;  
  42.     while(current != null){  
  43.         Console.Write("  data = " + current.data + ", thisNode = " + current.GetHashCode());  
  44.         if (current.next != null){  
  45.             Console.WriteLine(", next = " + current.next.GetHashCode());  
  46.         }else{  
  47.             Console.WriteLine(", next = null");  
  48.         }  
  49.         current = current.next;  
  50.     }  
Java

Download the source code for Java to NetBeans to view complete code. The source code for Java is the same as C#. 
  1. class SLL_Node{  
  2.     public int data;  
  3.     public SLL_Node next;  
  4.     public SLL_Node(int data){  
  5.         this.data = data;  
  6.         this.next = null;  
  7.     }  
  8. }  
  9.   
  10. class DLL_Node{  
  11.     public int data;  
  12.     public DLL_Node next;  
  13.     public DLL_Node prev;  
  14.     public DLL_Node(int data){  
  15.         this.data = data;  
  16.         this.next = null;  
  17.         this.prev = null;  
  18.     }  
  19. }  
Python

Download the source code for Python to view complete code. For Python, you need to install Python tools in Visual Studio. 
  1. class SLL_Node:  
  2.     def __init__(self, data):  
  3.         self.data = data  
  4.         self.next = None  
  5.   
  6. class DLL_Node:  
  7.     def __init__(self, data):  
  8.         self.data = data  
  9.         self.next = None  
  10.         self.prev = None  
  11.   
  12. class SinglyLinkedList:  
  13.     head = None  
  14.     lastNode = None  
  15.     count = 0  
  16.     ....  
  17.       
  18. class DoublyLinkedList:  
  19.     head = None  
  20.     lastNode = None  
  21.     count = 0  
  22.     ....  
VB.Net

Download the source code for VB.Net to view complete code. VB.Net stores objects in hash tables, so you can print the hash code of the stored object for printing memory location.

See following display() function. 
  1. Public Class SLL_Node  
  2.     Public data As Integer  
  3.     Public nextNode As SLL_Node  
  4.     Public Sub New(ByVal data_val As Integer)  
  5.         MyClass.data = data_val  
  6.         MyClass.nextNode = Nothing  
  7.     End Sub  
  8. End Class  
  9.   
  10.   
  11. Public Class DLL_Node  
  12.     Public data As Integer  
  13.     Public nextNode As DLL_Node  
  14.     Public prevNode As DLL_Node  
  15.     Public Sub New(ByVal data_val As Integer)  
  16.         MyClass.data = data_val  
  17.         MyClass.nextNode = Nothing  
  18.         MyClass.prevNode = Nothing  
  19.     End Sub  
  20.   
  21. End Class  
  22.   
  23.   
  24. Public Class SinglyLinkedList  
  25.     Private head As SLL_Node = Nothing  
  26.     Private lastNode As SLL_Node = Nothing  
  27.     Private count As Integer = 0  
  28.     ....  
  29.   
  30.   
  31. Public Class DoublyLinkedList  
  32.     Private head As DLL_Node = Nothing  
  33.     Private lastNode As DLL_Node = Nothing  
  34.     Private count As Integer = 0  
  35.     ....  
  36.       
  37.       
  38. Public Sub display()  
  39.     Dim current As SLL_Node = MyClass.head  
  40.     While current IsNot Nothing  
  41.         Console.Write("  data = " & current.data & ", thisNode = " & current.GetHashCode())  
  42.         current = current.nextNode  
  43.         If current Is Nothing Then  
  44.             Console.WriteLine(", next = null")  
  45.         Else  
  46.             Console.WriteLine(", next = " & current.GetHashCode())  
  47.         End If  
  48.     End While  
  49. End Sub  
If you compare the source codes in object oriented programming languages. You will find that they all are same but their syntax. To build the generic linked list in C# see following code.

It takes a type T as data with Data & Next properties and the remaining code is same as above C# code.  
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace GenericLinkedList  
  8. {  
  9.     public class Node<T>  
  10.     {  
  11.         private T data;  
  12.         private Node<T> next;  
  13.         public Node(T data)  
  14.         {  
  15.             this.data = data;  
  16.             this.next = null;  
  17.         }  
  18.   
  19.         public T Data  
  20.         {  
  21.             get { return this.data; }  
  22.             set { this.data = value; }  
  23.         }  
  24.   
  25.         public Node<T> Next  
  26.         {  
  27.             get { return this.next; }  
  28.             set { this.next = value; }  
  29.         }  
  30.     }  
  31.   
  32.     class LinkedList<T>  
  33.     {  
  34.         private Node<T> head;  
  35.         private Node<T> lastNode;  
  36.         private int count = 0;  
  37.   
  38.         public Node<T> Head { get { return this.head; } }  
  39.   
  40.         public Node<T> LastNode  
  41.         {  
  42.             get { return lastNode; }  
  43.             set { this.lastNode = value; }  
  44.         }  
  45.   
  46.         public void addNodeToEnd(T data)  
  47.         {  
  48.             Node<T> current = this.head;  
  49.             if (current == null)  
  50.             {  
  51.                 this.head = new Node<T>(data);  
  52.                 this.lastNode = this.head;  
  53.                 this.count++;  
  54.             }  
  55.             else  
  56.             {  
  57.                 if (this.lastNode != null)  
  58.                 {  
  59.                     this.LastNode.Next = new Node<T>(data);  
  60.                     this.lastNode = this.lastNode.Next;  
  61.                     this.count++;  
  62.                 }  
  63.             }  
  64.         }  
  65.   
  66.         public int getCount()  
  67.         {  
  68.             return this.count;  
  69.         }  
  70.   
  71.         public void display()  
  72.         {  
  73.             Node<T> current = this.head;  
  74.             while (current != null)  
  75.             {  
  76.                 Console.Write(current.Data+" ");  
  77.                 current = current.Next;  
  78.             }  
  79.             Console.WriteLine();  
  80.         }  
  81.   
  82.     }  
  83.   
  84.     class Program  
  85.     {  
  86.         static void Main(string[] args)  
  87.         {  
  88.             //linked list of int  
  89.             LinkedList<int> list = new LinkedList<int>();  
  90.             list.addNodeToEnd(10);  
  91.             list.addNodeToEnd(20);  
  92.             list.addNodeToEnd(30);  
  93.             list.display();  
  94.             //linked list of string  
  95.             LinkedList<String> strlist = new LinkedList<String>();  
  96.             strlist.addNodeToEnd("hello");  
  97.             strlist.addNodeToEnd("world");  
  98.             strlist.addNodeToEnd("!!!");  
  99.             strlist.display();  
  100.             //linked list of linked list of string  
  101.             LinkedList<LinkedList<String>> strListOfList = new LinkedList<LinkedList<String>>();  
  102.             strListOfList.addNodeToEnd(strlist);  
  103.             strListOfList.display();  
  104.             Console.Read();  
  105.         }  
  106.     }  
  107. }