A linked list is a linear data structure, in which the elements are not stored at contiguous memory locations. The elements in a linked list are linked using pointers as shown in the image below:
In simple words, a linked list consists of nodes where each node contains a data field and a reference(link) to the next node in the list.
Arrays can be used to store linear data of similar types, but arrays have the following limitations.
- The size of the arrays is fixed: So we must know the upper limit on the number of elements in advance. Also, generally, the allocated memory is equal to the upper limit irrespective of the usage.
- Inserting a new element in an array of elements is expensive because the room has to be created for the new elements and to create room existing elements have to be shifted but in Linked list if we have the head node then we can traverse to any node through it and insert new node at the required position. For example, in a system, if we maintain a sorted list of IDs in an array id[]. id[] = [1000, 1010, 1050, 2000, 2040]. And if we want to insert a new ID 1005, then to maintain the sorted order, we have to move all the elements after 1000 (excluding 1000). Deletion is also expensive with arrays until unless some special techniques are used. For example, to delete 1010 in id[], everything after 1010 has to be moved due to this so much work is being done which affects the efficiency of the code.
Advantages over arrays :
- Dynamic size
- Ease of insertion/deletion
Drawbacks:
- Random access is not allowed. We have to access elements sequentially starting from the first node(head node). So we cannot do binary search with linked lists efficiently with its default implementation. Read about it here.
- Extra memory space for a pointer is required with each element of the list.
- Not cache friendly. Since array elements are contiguous locations, there is locality of reference which is not there in case of linked lists.
- Singly Linked List
- Circular Linked List
- Doubly Linked List
Here we will be studying about Doubly Linked Lists.
A Doubly Linked List (DLL) contains an extra pointer, typically called previous pointer, together with next pointer and data which are there in singly linked list.
Following are the important terms to understand the concept of doubly linked list.
-
Link β Each link of a linked list can store a data called an element.
-
Next β Each link of a linked list contains a link to the next link called Next.
-
Prev β Each link of a linked list contains a link to the previous link called Prev.
-
Insertion β Adds an element at the beginning of the list.
-
Deletion β Deletes an element at the beginning of the list.
-
Insert Last β Adds an element at the end of the list.
-
Delete Last β Deletes an element from the end of the list.
-
Insert After β Adds an element after an item of the list.
-
Delete β Deletes an element from the list using the key.
-
Display forward β Displays the complete list in a forward manner.
-
Display backward β Displays the complete list in a backward manner.
- A DLL can be traversed in both forward and backward direction.
- The delete operation in DLL is more efficient if pointer to the node to be deleted is given.
- We can quickly insert a new node before a given node.
Given a Doubly Linked List, the task is to reverse the given Doubly Linked List.
- Original Doubly Linked List :
- Reversed Doubly Linked List :
- Swap prev and next pointers for all nodes.
- Change prev of the head (or start).
- Change the head pointer in the end.
Time Complexity : O(n), where N denotes the number of nodes in the doubly linked list.
Space Complexity : O(1), (since no extra space is used.)
- Keep traversing through the entire doubly linked list until current does not become equal to NULL.
- While traversing, for each node store the value of the previous pointer of current node in a variable temp. => temp = current->prev;
- Then place the value of current->next into current->prev.
- Now put the value of temp into current -> next.
- Now move to the next node by shifting current to current->prev, because the next node will now be accessible through the previous pointer since the values of the pointers have been swapped.
We can also swap data instead of pointers to reverse the Doubly Linked List. Method used for reversing array can be used to swap data. Swapping data can be costly compared to pointers if the size of the data item(s) is more.