0% found this document useful (0 votes)
6 views28 pages

Linked List DSA

A doubly linked list is a type of linked list where each node contains pointers to both the next and previous nodes, allowing traversal in both directions. It supports various operations such as insertion, deletion, and searching, with advantages including bidirectional traversal and more efficient deletions compared to singly linked lists. However, it requires extra memory for the previous pointers and more complex operations due to the need to maintain both next and previous pointers.

Uploaded by

jakeklent262
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views28 pages

Linked List DSA

A doubly linked list is a type of linked list where each node contains pointers to both the next and previous nodes, allowing traversal in both directions. It supports various operations such as insertion, deletion, and searching, with advantages including bidirectional traversal and more efficient deletions compared to singly linked lists. However, it requires extra memory for the previous pointers and more complex operations due to the need to maintain both next and previous pointers.

Uploaded by

jakeklent262
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 28

Doubly linked list

Doubly linked list is a complex type of linked list in which a


node contains a pointer to the previous as well as the next
node in the sequence. Therefore, in a doubly linked list, a node
consists of three parts: node data, pointer to the next node in
sequence (next pointer) , pointer to the previous node
(previous pointer). A sample node in a doubly linked list is
shown in the figure.

A doubly linked list containing three nodes having numbers


from 1 to 3 in their data part, is shown in the following image.

In C, structure of a node in doubly linked list can be given as :

1. struct node
2. {
3. struct node *prev;
4. int data;
5. struct node *next;
6. } ;

The prev part of the first node and the next part of the last
node will always contain null indicating end in each direction.

In a singly linked list, we could traverse only in one direction,


because each node contains address of the next node and it
doesn't have any record of its previous nodes. However, doubly
linked list overcome this limitation of singly linked list.

Due to the fact that, each node of the list contains the address
of its previous node, we can find all the details about the
previous node as well by using the previous address stored
inside the previous part of each node.

Operations on doubly linked list

Node Creation

1. struct node
2. {
3. struct node *prev;
4. int data;
5. struct node *next;
6. };
7. struct node *head, *last;
head=last=NULL;

All the remaining operations regarding doubly linked list are


described in the following table.

S Operation Description
N

1 Insertion at Adding the node into the linked list at beginning.


beginning

2 Insertion at end Adding the node into the linked list to the end.
3 Insertion after Adding the node into the linked list after the specifi
specified node node.

4 Deletion at Removing the node from beginning of the list


beginning

5 Deletion at the end Removing the node from end of the list.

6 Deletion of the node Removing the node which is present just after the n
having given data containing the given data.

7 Searching Comparing each node data with the item to be sear


and return the location of the item in the list if the i
found else return null.

8 Traversing Visiting each node of the list at least once in order t


perform some specific operation like searching, sor
display, etc.
Following are advantages/disadvantages of doubly linked list
over singly linked list.
Advantages over singly linked list
1) A DLL can be traversed in both forward and backward
direction.
2) The delete operation in DLL is more efficient if pointer to the
node to be deleted is given.
3) We can quickly insert a new node before a given node.
In singly linked list, to delete a node, pointer to the previous
node is needed. To get this previous node, sometimes the list is
traversed. In DLL, we can get the previous node using previous
pointer.

Disadvantages over singly linked list


1) Every node of DLL Require extra space for an previous
pointer.

2) All operations require an extra pointer previous to be


maintained. For example, in insertion, we need to modify
previous pointers together with next pointers. For example in
following functions for insertions at different positions, we need
1 or 2 extra steps to set previous pointer.
Doubly Linked List : Traverse Bi-directional

1. In Doubly Linked List , each node contain two address


fields .
2. One address field for storing address of next node to be
followed and second address field contain address
of previous node linked to it.
3. So Two way access is possible i.e We can start
accessing nodes from start as well as from last .
4. Like Singly Linked List also only Linear but
Bidirectional Sequential movement is possible.
5. Elements are accessed sequentially , no direct access is
allowed.

Explanation :

1. Doubly Linked List is most useful type of Linked List.


2. In DLL we have facility to access both next as well as
previous data using “next link” and “previous link“.
3. In the above diagram , suppose we are currently on 2nd
node i.e at 4 then we can access next and previous data
using –
To Access Next Data : curr_node->next->data
To Access Previous Data : curr_node->previous->data

4. We have to always maintain start node , because it is the


only node that is used to keep track of complete linked
list.

Insertion in doubly linked list at beginning

As in doubly linked list, each node of the list contain double


pointers therefore we have to maintain more number of
pointers in doubly linked list as compare to singly linked list.

There are two scenarios of inserting any element into doubly


linked list. Either the list is empty or it contains at least one
element. Perform the following steps to insert a node in doubly
linked list at beginning.

o Allocate the space for the new node in the memory. This
will be done by using the following statement.

1. ptr = (struct node *)malloc(sizeof(struct node));


o Check whether the list is empty or not. The list is empty if
the condition head == NULL holds. In that case, the node
will be inserted as the only node of the list and therefore
the prev and the next pointer of the node will point to
NULL and the head pointer will point to this node.

1. ptr->next = NULL;
2. ptr->prev=NULL;
3. ptr->data=item;
4. head=ptr;
o In the second scenario, the condition head ==
NULL become false and the node will be inserted in
beginning. The next pointer of the node will point to the
existing head pointer of the node. The prev pointer of the
existing head will point to the new node being inserted.
o This will be done by using the following statements.

1. ptr->next = head;
2. head→prev=ptr;

Since, the node being inserted is the first node of the list and
therefore it must contain NULL in its prev pointer. Hence assign
null to its previous part and make the head point to this node.

1. ptr→prev =NULL
2. head = ptr
3. tail = ptr

Algorithm :

o Step 1: IF ptr = NULL

Write OVERFLOW
Go to Step 9
[END OF IF]

o Step 2: SET NEW_NODE = ptr


o Step 3: SET ptr = ptr -> NEXT
o Step 4: SET NEW_NODE -> DATA = VAL
o Step 5: SET NEW_NODE -> PREV = NULL
o Step 6: SET NEW_NODE -> NEXT = START
o Step 7: SET head -> PREV = NEW_NODE
o Step 8: SET head = NEW_NODE
o Step 10: EXIT
C Function

1. struct node
2. {
3. int data;
4. struct node *next;
5. struct node *prev;
6. };
7. struct node *head, *tail;
8. head=NULL;
9. tail=NULL;
10. void insertbeginning(int item)
11. {
12.
13. struct node *ptr = (struct node *)malloc(sizeof(struct n
ode));
14. if(ptr == NULL)
15. {
16. printf("\nOVERFLOW");
17. }
18. else
19. {
20.
21.
22. if(head==NULL)
23. {
24. ptr->next = NULL;
25. ptr->prev=NULL;
26. ptr->data=item;
27. head=ptr;
28. tail=ptr;
29. }
30. else
31. {
32. ptr->data=item;
33. ptr->prev=NULL;
34. ptr->next = head;
35. head->prev=ptr;
36. head=ptr;
37.
38. }
39. }
40.
41. }

Insertion in doubly linked list at the end


In order to insert a node in doubly linked list at the end, we must make sure whether
the list is empty or it contains any element. Use the following steps in order to insert
the node in doubly linked list at the end.

o Allocate the memory for the new node. Make the pointer ptr point to the new
node being inserted.

1. ptr = (struct node *) malloc(sizeof(struct node));

o Check whether the list is empty or not. The list is empty if the condition head
== NULL holds. In that case, the node will be inserted as the only node of the
list and therefore the prev and the next pointer of the node will point to NULL
and the head pointer will point to this node.

1. ptr->next = NULL;
2. ptr->prev=NULL;
3. ptr->data=item;
4. head=ptr;
5. tail=ptr;

o In the second scenario, the condition head == NULL become false. The new
node will be inserted as the last node of the list..
o tail->next=ptr;
o ptr->next=NULL;
o ptr->prev=tail;

o tail=ptr;

1. struct node
2. {
3. int data;
4. struct node *next;
5. struct node *prev;
6. };
7. struct node *head,*tail;
8. void insertlast(int item)
9. {
10.
11. struct node *ptr = (struct node *) malloc(sizeof(struct node));
12. struct node *temp;
13. if(ptr == NULL)
14. {
15. printf("\nOVERFLOW");
16.
17. }
18. else
19. {
20.
21. ptr->data=item;
22. if(head == NULL)
23. {
24. ptr->next = NULL;
25. ptr->prev = NULL;
26. head = ptr;
 tail = ptr;
27. }
28. else
29. { tail->next=ptr;
30. ptr->next=NULL;
31. ptr->prev=tail;
32.
33. tail=ptr;
34.
35. }
36.
37. printf("\nNode Inserted\n");
38.
39. }
40. }

41. Traverse to N-1 node in the list. Where N is the position to insert.
Say temp now points to N-1 node.
th
42. Create a newNode that is to be inserted and assign some data to its data field.

43. Connect the next address field of newNode with the node pointed by next
address field of temp node.

44. Connect the previous address field of newNode with the temp node.
45. Check if temp->next is not NULL then, connect the previous address field of
node pointed by temp.next to newNode.

46. Connect the next address field of temp node to newNode i.e. temp->next will
now point to newNode.

47. Final list


Program to insert a new node at the middle of doubly
linked list.

struct node
{
struct node *prev;
int data;
struct node *next;
};
struct node *head, *last;
head=last=NULL;

void insertion_specified()
{
struct node *ptr,*temp;
int item,loc,i;
ptr = (struct node *)malloc(sizeof(struct node));
if(ptr == NULL)
{
printf("\n OVERFLOW");
}
else
{
temp=head;
printf("Enter the location");
scanf("%d",&loc);
if (head==NULL )
printf("create the list first");

for(i=1;i<=loc;i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("\n There are less than %d elements", loc);
return;
}
}
printf("Enter value");
scanf("%d",&item);
ptr->data = item;
ptr->next = temp->next;
ptr -> prev = temp;
temp->next->prev=ptr;

temp->next = ptr;
printf("\nnode inserted\n");
}
}

Deletion at beginning
Deletion in doubly linked list at the beginning is the simplest operation. We just need
to copy the head pointer to pointer ptr and shift the head pointer to its next.

1. Ptr = head;
2. head = head → next;

now make the prev of this new head node point to NULL. This will be done by using
the following statements.

1. head → prev = NULL

Now free the pointer ptr by using the free function.

1. free(ptr)
Algorithm
o STEP 1: IF HEAD = NULL

WRITE UNDERFLOW
GOTO STEP 6

o STEP 2: SET PTR = HEAD

o STEP 3: SET HEAD = HEAD → NEXT

o STEP 4: SET HEAD → PREV = NULL

o STEP 5: FREE PTR

o STEP 6: EXIT

1. struct node
2. {
3. int data;
4. struct node *next;
5. struct node *prev;
6. };
7. struct node *head, *tail;
8.
9.
10. void beginning_delete()
11. {
12. struct node *ptr;
13. if(head == NULL)
14. {
15. printf("\n UNDERFLOW\n");
16. }
17. else if(head->next == NULL)
18. {
19.
20. free(head);
21. head = NULL;
22. tail=NULL;
23.
24. printf("\nNode Deleted\n");
25. }
26. else
27. {
28. ptr = head; head=head->next;
29. head = head -> next; free(head->prev);
30. head -> prev = NULL; head->prev=NULL;
31. free(ptr);
32. printf("\nNode Deleted\n");
33. }
34. }
Deletion in doubly linked list at the end

1. struct node
2. {
3. int data;
4. struct node *next;
5. struct node *prev;
6. };
7. struct node *head,*tail,*temp;
8. void last_delete()
9. {
10. struct node *ptr;
11. if(head == NULL)
12. {
13. printf("\n UNDERFLOW\n");
14. }
15. else if(head->next == NULL)
16. { free(head);
17. head = NULL;
18. tail=NULL;
19.
20. printf("\nNode Deleted\n");
21. }
22. else
23. {
24. ptr=tail; tail=tail->prev;
25. tail=tail->prev; free(tail->next);
26. tail->next=NULL; tail->next=NULL;
27. free(ptr);
28.
29. printf("\nNode Deleted\n");
30. }
31. }

Deletion at the middle (steps)

Deletion at middle

Steps

 Traverse till the target node

 create a node called the previous storing previous node of the target node

 Assign previous node’s next pointer to the next node of the target node

 For the next node of the target node, its previous pointer is assigned to the targets

node’s previous node’s address

 Free memory of target node


1. void deletion_specified()
2. {
3. struct node *ptr, *temp;
4. int val;
5. printf("\n Enter the data after which the node is to be deleted
: ");
6. scanf("%d", &val);
7. ptr = head;
8. while(ptr -> data != val)
9. ptr = ptr -> next;
10. if(ptr == NULL)
11. {
12. printf("\nCan't delete last node\n");
13. }
14. else
15. {
16. ptr->next->prev=ptr->prev;
17. ptr->prev->next=ptr->next;
18. free(ptr);
19. printf("\nnode deleted\n");
20. }
21. }

Display contents of the doubly linked list

22. void display() [ forward]


23. {
24. struct node *ptr;
25. if (head==NULL)
26. printf(" list is empty");
27. printf("\n printing values...\n");
28. ptr = head;
29. while(ptr != NULL)
30. {
31. printf("%d\n",ptr->data);
32. ptr=ptr->next;
33. }
34. }
35. void display()
36. {
37. struct node *ptr;
38. if (head==NULL)
39. printf(" list is empty");
40. printf("\n printing values...\n");
41. ptr=tail;
42. while(ptr != NULL)
43. {
44. printf("%d\n",ptr->data);
45. ptr=ptr->prev;
46. }
47. }

STACK USING LINKED LIST

The major problem with the stack implemented using an array is, it works only for a

fixed number of data values. That means the amount of data must be specified at

the beginning of the implementation itself. Stack implemented using an array is not

suitable, when we don't know the size of data which we are going to use. A stack

data structure can be implemented by using a linked list data structure. The stack

implemented using linked list can work for an unlimited number of values. That

means, stack implemented using linked list works for the variable size of data. So,

there is no need to fix the size at the beginning of the implementation. The Stack

implemented using linked list can organize as many data values as we want.

In linked list implementation of a stack, every new element is inserted as 'top'

element. That means every newly inserted element is pointed by 'top'. Whenever we

want to remove an element from the stack, simply remove the node which is pointed

by 'top' by moving 'top' to its previous node in the list. The next field of the first

element must be always NULL.


Example

In the above example, the last inserted node is 99 and the first inserted node is 25.

The order of elements inserted is 25, 32,50 and 99.

Stack Operations using Linked List

To implement a stack using a linked list, we need to set the following things before

implementing actual operations.

 Step 1 - Include all the header files which are used in the program. And

declare all the user defined functions.

 Step 2 - Define a 'Node' structure with two members data and next.

 Step 3 - Define a Node pointer 'top' and set it to NULL.

 Step 4 - Implement the main method by displaying Menu with list of

operations and make suitable function calls in the main method.

push(value) - Inserting an element into the Stack

We can use the following steps to insert a new node into the stack...

 Step 1 - Create a newNode with given value.


 Step 2 - Check whether stack is Empty (top == NULL)

 Step 3 - If it is Empty, then set newNode → next = NULL.

 Step 4 - If it is Not Empty, then set newNode → next = top.

 Step 5 - Finally, set top = newNode.

pop() - Deleting an Element from a Stack

We can use the following steps to delete a node from the stack...

 Step 1 - Check whether stack is Empty (top == NULL).

 Step 2 - If it is Empty, then display "Stack is Empty!!! Deletion is not

possible!!!" and terminate the function

 Step 3 - If it is Not Empty, then define a Node pointer 'temp' and set it to

'top'.

 Step 4 - Then set 'top = top → next'.

 Step 5 - Finally, delete 'temp'. (free(temp)).

display() - Displaying stack of elements

We can use the following steps to display the elements (nodes) of a stack...

 Step 1 - Check whether stack is Empty (top == NULL).

 Step 2 - If it is Empty, then display 'Stack is Empty!!!' and terminate the

function.

 Step 3 - If it is Not Empty, then define a Node pointer 'temp' and initialize

with top.

 Step 4 - Display 'temp → data --->' and move it to the next node. Repeat the

same until temp reaches to the first node in the stack. (temp → next !

= NULL).

 Step 5 - Finally! Display 'temp → data ---> NULL'.


 struct Node
 {
 int data;
 struct Node *next;
 }*top = NULL;
 void push(int value)
 {
 struct Node *newNode;
 newNode = (struct Node*)malloc(sizeof(struct Node));
 newNode->data = value;
 if(top == NULL)
 newNode->next = NULL;

 else
 newNode->next = top;
 top = newNode;
 printf("\nInsertion is Success!!!\n");
 }
 void pop()
 {
 if(top == NULL)
 printf("\nStack is Empty!!!\n");
 else{
 struct Node *temp = top;
 printf("\nDeleted element: %d", temp->data);
 top = top->next;
 free(temp);
 }
 }
 void display()
 {
 if(top == NULL)
 printf("\nStack is Empty!!!\n");
 else{
 struct Node *temp = top;
 while(temp != NULL){
 printf("%d--->",temp->data);
 temp = temp -> next;
 } }

Linked List implementation of Queue


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.

The linked representation of queue is shown in the following figure.

1.

struct node
2. {
3. int data;
4. struct node *next;
5. };
6. struct node *front;
7. struct node *rear;
front=rear=NULL
Operation on Linked Queue
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.

1. Ptr = (struct node *) malloc (sizeof(struct node));

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.

1. ptr -> data = item;


2. if(front == NULL)
3. {
4. front = ptr;
5. rear = ptr;
6. front -> next = NULL;
7. rear -> next = NULL;
8. }

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.

1. rear -> next = ptr;


2. rear = ptr;
3. rear->next = NULL;

In this way, the element is inserted into the queue.

Step 1: Allocate the space for the new node PTR

o Step 2: SET PTR -> DATA = VAL


o Step 3: IF FRONT = NULL
SET FRONT = REAR = PTR
SET FRONT -> NEXT = REAR -> NEXT = NULL
ELSE
SET REAR -> NEXT = PTR
SET REAR = PTR
SET REAR -> NEXT = NULL
[END OF IF]

o Step 4: END

Algorithm

1. void insert( int item )


2. {
3. struct node *ptr;
4.
5. ptr = (struct node *) malloc (sizeof(struct node));
6. if(ptr == NULL)
7. {
8. printf("\nOVERFLOW\n");
9. return;
10. }
11. else
12. {
13. ptr -> data = item;
14. if(front == NULL)
15. {
16. front = ptr;
17. rear = ptr;
18.
19. rear -> next = NULL;
20. }
21. else
22. {
23. rear -> next = ptr;
24. rear = ptr;
25. rear->next = NULL;
26. }
27. }
28. }

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);

o Step 1: IF FRONT = NULL


Write " Underflow "
Go to Step 5
[END OF IF]

o Step 2: SET PTR = FRONT

o Step 3: SET FRONT = FRONT -> NEXT

o Step 4: FREE PTR

o Step 5: END

Algorithm

1. void delete ()
2. { struct node *ptr;
3. if(front == NULL)
4. {
5. printf("\nUNDERFLOW\n");
6. return;
7. }
8. else
9. {
10. ptr = front;
11. printf( " the deleted data is %d", front->data);
12. front = front -> next;
13. free(ptr);
14. }
15. }
Algorithm
8. void display()
9. {
10. struct node *ptr;
11. ptr = front;
12. if(front == NULL)
13. {
14. printf("\nEmpty queue\n");
15. }
16. else
17. { printf("\nprinting values .....\n");
18. while(ptr != NULL)
19. {
20. printf("\n%d\n",ptr -> data);
21. ptr = ptr -> next;
22. }
23. }
24. }

You might also like