UNIT 3 part 2
UNIT 3 part 2
There are many applications of linked lists, be it in computer science or the real world.
In music players, we can create our song playlist and can play a song either from
starting or ending of the list. And these music players are implemented using a linked
list.
We watch the photos on our laptops or PCs, and we can simply see
the next or previous images easily. This feature is implemented using a linked list.
You must be reading this article on your web browser, and in web browsers, we open
multiple URLs, and we can easily switch between those URLs using the previous and
next buttons because they are connected using a linked list.
The doubly linked list is used to implement data structures like a stack, queue,
binary tree, and hash table.
It is also used in algorithms of LRU (Least Recently used) and MRU(Most Recently
Used) cache.
The undo and redo buttons can be implemented using a doubly-linked list.
The doubly linked list can also be used in the allocation and deallocation of memory.
Representation:
A multilevel linked list is represented by a pointer to the first node of the linked lists.
Similar to the linked list, the first node is called the head. If the multilevel linked list is
empty, then the value of head is NULL. Each node in a list consists of at least three parts:
1. Data.
2. Pointer to the next node.
3. Pointer to the child node.
Each node of a multilevel linked list is represented as:
class Node
{
public:
int data;
Node *next;
Node *child;
};
insertion
if (head == NULL) {
tmp = head = new Node();
}
else {
tmp->next = new Node();
tmp = tmp->next;
}
// Created a node with data and
// setting child and next pointer
// as NULL.
tmp->data = arr[i];
tmp->next = tmp->child = NULL;
Instead of using array, we can also use linked list to implement stack. Linked list allocates the
memory dynamically. However, time complexity in both the scenario is same for all the
operations i.e. push, pop and peek.
In linked list implementation of stack, the nodes are maintained non-contiguously in the
memory. Each node contains a pointer to its immediate successor node in the stack. Stack is
said to be overflown if the space left in the memory heap is not enough to create a node.
The top most node in the stack always contains null in its address field. Lets discuss the way
in which, each operation is performed in linked list implementation of stack.
C implementation :
1. void push ()
2. {
3. int val;
4. struct node *ptr =(struct node*)malloc(sizeof(struct node));
5. if(ptr == NULL)
6. {
7. printf("not able to push the element");
8. }
9. else
10. {
11. printf("Enter the value");
12. scanf("%d",&val);
13. if(head==NULL)
14. {
15. ptr->val = val;
16. ptr -> next = NULL;
17. head=ptr;
18. }
19. else
20. {
21. ptr->val = val;
22. ptr->next = head;
23. head=ptr;
24.
25. }
26. printf("Item pushed");
27.
28. }
29. }
Deleting a node from the top of stack is referred to as pop operation. Deleting a node
from the linked list implementation of stack is different from that in the array
implementation. In order to pop an element from the stack, we need to follow the
following steps :
30. Check for the underflow condition: The underflow condition occurs when we
try to pop from an already empty stack. The stack will be empty if the head
pointer of the list points to null.
31. Adjust the head pointer accordingly: In stack, the elements are popped only
from one end, therefore, the value stored in the head pointer must be deleted
and the node must be freed. The next node of the head node now becomes the
head node.
C implementation
1. void pop()
2. {
3. int item;
4. struct node *ptr;
5. if (head == NULL)
6. {
7. printf("Underflow");
8. }
9. else
10. {
11. item = head->val;
12. ptr = head;
13. head = head->next;
14. free(ptr);
15. printf("Item popped");
16.
17. }
18. }
Displaying all the nodes of a stack needs traversing all the nodes of the linked list
organized in the form of stack. For this purpose, we need to follow the following steps.
C Implementation
1. void display()
2. {
3. int i;
4. struct node *ptr;
5. ptr=head;
6. if(ptr == NULL)
7. {
8. printf("Stack is empty\n");
9. }
10. else
11. {
12. printf("Printing Stack elements \n");
13. while(ptr!=NULL)
14. {
15. printf("%d\n",ptr->val);
16. ptr = ptr->next;
17. }
18. }
19. }
Although, the technique of creating a queue is easy, but there are some drawbacks of using this
technique to implement a queue.
o Memory wastage : The space of the array, which is used to store queue elements, can
never be reused to store the elements of that queue because the elements can only be
inserted at front end and the value of front might be so high so that, all the space before
that, can never be filled.
The above figure shows how the memory space is wasted in the array representation of queue.
In the above figure, a queue of size 10 having 3 elements, is shown. The value of the front
variable is 5, therefore, we can not reinsert the values in the place of already deleted element
before the position of front. That much space of the array is wasted and can not be used in the
future (for this queue).
On of the most common problem with array implementation is the size of the array which
requires to be declared in advance. Due to the fact that, the queue can be extended at runtime
depending upon the problem, the extension in the array size is a time taking process and almost
impossible to be performed at runtime since a lot of reallocations take place. Due to this reason,
we can declare the array large enough so that we can store queue elements as enough as possible
but the main problem with this declaration is that, most of the array slots (nearly half) can never
be reused. It will again lead to memory wastage.
Due to the drawbacks discussed in the previous section of this tutorial, the array
implementation can not be used for the large scale applications where the queues are
implemented. One of the alternative of array implementation is linked list implementation of
queue.
The storage requirement of linked representation of a queue with n elements is o(n) while the
time requirement for operations is o(1).
In a linked queue, each node of the queue consists of two parts i.e. data part and the link part.
Each element of the queue points to its immediate next element in the memory.
In the linked queue, there are two pointers maintained in the memory i.e. front pointer and rear
pointer. The front pointer contains the address of the starting element of the queue while the
rear pointer contains the address of the last element of the queue.
Insertion and deletions are performed at rear and front end respectively. If front and rear both
are NULL, it indicates that the queue is empty.
There are two basic operations which can be implemented on the linked queues. The operations
are Insertion and Deletion.
Insert operation
The insert operation append the queue by adding an element to the end of the queue. The new
element will be the last element of the queue.
Firstly, allocate the memory for the new node ptr by using the following statement.
There can be the two scenario of inserting this new node ptr into the linked queue.
In the first scenario, we insert element into an empty queue. In this case, the condition front =
NULL becomes true. Now, the new element will be added as the only element of the queue
and the next pointer of front and rear pointer both, will point to NULL.
In the second case, the queue contains more than one element. The condition front = NULL
becomes false. In this scenario, we need to update the end pointer rear so that the next pointer
of rear will point to the new node ptr. Since, this is a linked queue, hence we also need to make
the rear pointer point to the newly added node ptr. We also need to make the next pointer of
rear point to NULL.
In this way, the element is inserted into the queue. The algorithm and the C implementation is
given as follows.
Algorithm
C Function
Deletion
Deletion operation removes the element that is first inserted among all the queue elements.
Firstly, we need to check either the list is empty or not. The condition front == NULL becomes
true if the list is empty, in this case , we simply write underflow on the console and make exit.
Otherwise, we will delete the element that is pointed by the pointer front. For this purpose,
copy the node pointed by the front pointer into the pointer ptr. Now, shift the front pointer,
point to its next node and free the node pointed by the node ptr. This is done by using the
following statements.
1. ptr = front;
2. front = front -> next;
3. free(ptr);
Algorithm
C Function