Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 79

Linked List

Array Limitations

1. Fixed array size


2. Contiguous memory location
3. Expensive insertion/deletion operation
Linked List

● A linked list is a basic data structure where each item contains the information that
we need to get to the next item.
● In a linked list the elements are not stored at contiguous memory locations. The
elements in a linked list are linked using pointers
● A linked list consists of items called “Nodes” which contain two parts. The first part
stores the actual data and the second part has a pointer that points to the next node.

NOD
E
Representation of Linked Lists:

● A linked list is represented by a pointer to the first node of the linked list. The first
node is called the head of the linked list. If the linked list is empty, then the value of
the head points to NULL.
● The last node next part does not refer to any other node hence it contains null
● Here, each node stores the data and the address of the next node.
Representation of Linked Lists:

● Suppose we want to store a list of numbers: 23, 54, 78, 90

23 54 78 90

1000 2000 3000 4000


Representation of Linked Lists:

● Suppose we want to store a list of numbers: 23, 54, 78, 90

23 2000 54 3000 78 4000 90 NULL

1000 2000 3000 4000


Accessing First Element of Linked List

● Suppose we want to store a list of numbers: 23, 54, 78, 90

23 2000 54 3000 78 4000 90 NULL

1000 2000 3000 4000

1000

HEAD
Linked List

● Suppose we want to store a list of numbers: 23, 54, 78, 90

23 2000 54 3000 78 4000 90 NULL

1000 2000 3000 4000

1000

HEAD
Node

● In C, we can represent a node using structures. In Java or C++, LinkedList Node can
be represented as a class.

class Node {
public:
int data;
Node* next;
};
Storing data in Node
#include <iostream> //assign data to node
using namespace std; first->data=1;
class Node{ //assign link of next node
public:
first->next=NULL;
int data;
Node* next;
//assign first node to head node
};
int main(){
head=first;
Node* head; }
// create a node
Node* first=NULL;
//assign memory to node
first=new Node();
Linked List in C++
#include <iostream> second=new Node();
using namespace std; third=new Node();
class Node{ // Assign data values
public: first->data=23;
int data; second->data=54;
Node* next;
third->data=78;
};
// Connect nodes
int main(){
first->next=second;
Node* head;
second->next=third;
Node* first=NULL;
Node* second=NULL; third->next=NULL;
Node* third=NULL;
// allocate 3 nodes in the heap head=first;
first=new Node(); }
Traversal Operation

C++:
Algorithm:
void traverse(Node* n){
while(n!=NULL){
Given a node n
cout<<n->data<<" ";
Loop till n is not equal to null
n=n->next;
Display data in n
}
Point n to next node
}
Time Complexity: O(n)
Linked List

● A node can be added in three ways:

1. At the front of the linked list


2. After a given node.
3. At the end of the linked list.
Insertion Operation - at head

● The new node is always added before the head of the given Linked List. And newly
added node becomes the new head of the Linked List.
● For example, if the given Linked List is 10->15->20->25 and we add an item 5 at the
front, then the Linked List becomes 5->10->15->20->25.
● Let us call the function that adds at the front of the list is push(). The push() must
receive a pointer to the head pointer because the push must change the head pointer
to point to the new node
Insertion Operation - at head
Insertion Operation - at head

C++:
Algorithm:
void push(Node** head_ref, int new_data)
1. Given a pointer to head pointer and
{
data
Node* new_node = new Node();
2. Create a new node
new_node->data = new_data;
3. Save the data in data part of new
new_node->next = *head_ref;
node
*head_ref = new_node;
4. Make new node point to the location
}
stored in head pointer
5. Make head pointer point to new node.

Time Complexity: O(1)


Insertion Operation - at tail

● The new node is always added after the last node of the given Linked List.
● For example if the given Linked List is 5->10->15->20->25 and we add an item 30 at
the end, then the Linked List becomes 5->10->15->20->25->30.
● Since a Linked List is typically represented by the head of it, we have to traverse the
list till the end and then change the next to last node to a new node.
Insertion Operation - at tail
Insertion Operation - at tail

Algorithm: Create a temporary reference to address in


head pointer
Given a pointer to head pointer and data Iterate till temporary is pointing to NULL
Create a new node Make temp point to new node
Save the data in data part of new node
Make new node point to NULL
Check if pointer to head pointer is referring Time Complexity: O(n)
to NULL
Assign pointer to head pointer
new node and return
Insertion Operation - at tail

C++:
Node *temp = *head_ref;
void append(Node** head_ref, int new_data) while (temp->next != NULL)
{ {
Node* new_node = new Node(); temp= temp->next;
new_node->data = new_data; }
new_node->next = NULL; temp->next = new_node;
if (*head_ref == NULL) return;
{ }
*head_ref = new_node;
return;
}
Insertion Operation - at middle

● The new node is added somewhere in between head and tail.


● For example if the given Linked List is 5->10->15->20->25 and we add an item 30 at
third node, then the Linked List becomes 5->10->30->15->20->25.
● We have to update two links to insert in middle of linked list.
Insertion Operation - at middle
Insertion Operation - at middle

C++:
Algorithm: void insertAfter(Node* prev_node, int
1. Given a specific node and new data new_data)
2. Check if the given previous node is {
NULL or not. if (prev_node == NULL) {
3. Then, allocate a new node and cout << "The given previous node cannot
4. Assign the data to the new node be NULL";
5. And then make the next of new node return;
as the next of previous node. }
6. Finally, move the next of the previous Node* new_node = new Node();
node as a new node. new_node->data = new_data;
new_node->next = prev_node->next;
Time Complexity: O(1) prev_node->next = new_node;
}
Complete Insertion Program

void insertAfter(Node* prev_node, int


#include <iostream>
new_data)
using namespace std;
{
class Node{
if (prev_node == NULL)
public:
{
int data;
cout<<"The given previous node cannot
Node *next;
be NULL";
};
return;
void push(Node** head_ref, int new_data)
}
{
Node* new_node = new Node();
Node* new_node = new Node();
new_node->data = new_data;
new_node->data = new_data;
new_node->next = prev_node->next;
new_node->next = *head_ref;
prev_node->next = new_node;
*head_ref = new_node;
}
}
Complete Insertion Program

void append(Node** head_ref, int new_data)


last = last->next;
{ }
Node* new_node = new Node(); last->next = new_node;
new_node->data = new_data; return;
new_node->next = NULL; }
if (*head_ref == NULL) void traverse(Node *node)
{ {
*head_ref = new_node;
return; while (node != NULL)
} {
Node *last = *head_ref; cout<<" "<<node->data;
while (last->next != NULL) node = node->next;
{ }
}
Complete Insertion Program

int main()
{
Node* head = NULL;
append(&head, 6);
push(&head, 7);
push(&head, 1);
append(&head, 4);
insertAfter(head->next, 8);
cout<<"Created Linked list is: ";
traverse(head);
return 0;
}
Understanding Insertion
Program
Node* head = NULL;

head NULL

1430
append(&head, 6);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL)
{ 1430 head NULL
*head_ref = new_node;
return; head_ref 1430
}
Node *last = *head_ref;
while (last->next != NULL) 6
{ last = last->next;
} new_data
last->next = new_node;
return;
}
append(&head, 6);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) 1430 head NULL
{
*head_ref = new_node; head_ref 1430
return;
}
Node *last = *head_ref;
while (last->next != NULL)
{ last = last->next; new_node 6 NULL 6
}
last->next = new_node; 1630 new_data
return;
}
append(&head, 6);
void append(Node** head_ref, int new_data)
{ 1430 head NULL
Node* new_node = new Node();
new_node->data = new_data; head_ref
new_node->next = NULL; 1430
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
1430 head 1630
}
Node *last = *head_ref; head_ref 1430
while (last->next != NULL)
{ last = last->next;
}
last->next = new_node;
return; new_node 6 NULL 6
}
1630 new_data
Linked List

head 1630 6 NULL

1430 1630
push(&head, 7);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 1630 7
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}
push(&head, 7);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 1630 7
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 7

2452
push(&head, 7);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 1630 7
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 7 1630

2452
push(&head, 7);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 2452 7
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 7 1630

2452
Linked List

head 2452 7 1630 6 NULL

1430 2452 1630


push(&head, 1);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 2452 1
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}
push(&head, 1);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 2452 1
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 1

4378
push(&head, 1);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 2452 1
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 1 2452

4378
push(&head, 1);
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 4378 1
new_node->data = new_data;
new_node->next = *head_ref; head_ref 1430 new_data
*head_ref = new_node;
}

new_node 1 2452

4378
Linked List

head 4378 1 2452 7 1630 6 NULL

1430 4378 2452 1630


append(&head, 4);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 4378 4
new_node->data = new_data;
new_node->next = NULL; head_ref 1430 new_data
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
Node *last = *head_ref;
while (last->next != NULL)
{ last = last->next;
}
last->next = new_node;
return;
}
append(&head, 4);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 4378 4
new_node->data = new_data;
new_node->next = NULL; head_ref 1430 new_data
if (*head_ref == NULL)
{
*head_ref = new_node;
return; new_node 4 NULL
}
Node *last = *head_ref; 8971
while (last->next != NULL)
{ last = last->next;
}
last->next = new_node;
return;
}
append(&head, 4);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 4378 4
new_node->data = new_data;
new_node->next = NULL; head_ref 1430 new_data
if (*head_ref == NULL)
{
*head_ref = new_node;
return; last 4378
}
Node *last = *head_ref; 3321
while (last->next != NULL)
{ last = last->next;
} new_node 4 NULL
last->next = new_node;
return; 8971
}
Loop Iteration

head 4378 1 2452 7 1630 6 NULL

1430 4378 2452 1630

last 4378

3321
Loop Iteration

head 4378 1 2452 7 1630 6 NULL

1430 4378 2452 1630

last 2452

3321
Loop Iteration

head 4378 1 2452 7 1630 6 NULL

1430 4378 2452 1630

last 1630

3321
append(&head, 4);
void append(Node** head_ref, int new_data)
{
Node* new_node = new Node(); 1430 head 4378 4
new_node->data = new_data;
new_node->next = NULL; head_ref 1430 new_data
if (*head_ref == NULL)
{
*head_ref = new_node;
return; 6 8971
}
Node *last = *head_ref; 1630
while (last->next != NULL)
{ last = last->next;
}
last->next = new_node; last 1630
return; new_node 4 NULL
} 3321
8971
Linked List
head

4378

1430

1 2452 7 1630 6 8971 4 NULL

4378 2452 1630 8971


insertAfter(head->next, 8);
void insertAfter(Node* prev_node, int new_data)
{
if (prev_node == NULL) 2452 7 1630 8
{
cout<<"The given previous node cannot be NULL"; prev_node 2452 new_data
return;
}
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
}
insertAfter(head->next, 8);
void insertAfter(Node* prev_node, int new_data)
{
if (prev_node == NULL) 2452 7 1630 8
{
cout<<"The given previous node cannot be NULL"; prev_node 2452 new_data
return;
}
Node* new_node = new Node(); new_node 8 NULL
new_node->data = new_data;
new_node->next = prev_node->next;
1690
prev_node->next = new_node;
}
insertAfter(head->next, 8);
void insertAfter(Node* prev_node, int new_data)
{
if (prev_node == NULL) 2452 7 1630 8
{
cout<<"The given previous node cannot be NULL"; prev_node 2452 new_data
return;
}
Node* new_node = new Node(); new_node 8 1630
new_node->data = new_data;
new_node->next = prev_node->next;
1690
prev_node->next = new_node;
}
insertAfter(head->next, 8);
void insertAfter(Node* prev_node, int new_data)
{
if (prev_node == NULL) 2452 7 1690 8
{
cout<<"The given previous node cannot be NULL"; prev_node 2452 new_data
return;
}
Node* new_node = new Node(); new_node 8 1630
new_node->data = new_data;
new_node->next = prev_node->next;
1690
prev_node->next = new_node;
}
Linked List
head

4378

1430

1 2452 7 1690 8 1630 6 8971 4 NULL

4378 2452 1690 1630 8971


Searching Operation

C++:
Algorithm:
1. Initialize a node pointer, temp= head.
bool search(Node* head, int x)
2. Do following while tempis not NULL
{
3. If the tempvalue (i.e., temp->data) is
Node* temp= head;
equal to the key being searched
while (temp != NULL) {
return true.
if (temp->data == x)
4. Otherwise, move to the next node
return true;
(temp = temp->next).
temp= temp->next;
5. If the key is not found, return false
}
return false;
Time Complexity: O(n)
}
Types of Linked List

There are three common types of Linked List.

1. Singly Linked List


2. Doubly Linked List
3. Circular Linked List
4. Doubly Circular linked list
Singly Linked List

● It is the most common. Each node has data and a pointer to the next node.
Singly Linked List

● Node is represented as:

class Node {
public:
int data;
Node* next;
};
Doubly Linked List

● A doubly linked list or a two-way linked list is a more complex type of linked list
that contains a pointer to the next as well as the previous node in sequence.
● Therefore, it contains three parts of data, a pointer to the next node, and a pointer to
the previous node. This would enable us to traverse the list in the backward direction
as well. Below is the image for the same:
Doubly Linked List

● Node is represented as:

class Node {
public:
int data;
Node* next;
Node* prev;
};
Traversal Operation

C++:
last = last->prev;
void traverse(Node* n){ }
Node* last; }
cout << "Traversal in forward direction \n"; }
while (n != NULL) {
cout << " " << n->data << " ";
last = n;
n= n->next;
}
cout << "\nTraversal in reverse direction \n";
while (last != NULL) {
cout << " " << last->data << " ";
Insertion in DLL

● A node can be added in four ways:

1. At the front of the DLL


2. After a given node.
3. At the end of the DLL
Insertion Operation-at head

● The new node is always added before the head of the given Linked List. And newly
added node becomes the new head of DLL.
● For example, if the given Linked List is 1->0->1->5 and we add an item 5 at the
front, then the Linked List becomes 5->1->0->1->5.
● Let us call the function that adds at the front of the list push(). The push() must
receive a pointer to the head pointer because the push must change the head pointer
to point to the new node
Insertion Operation-at head
Insertion Operation - at head

C++:

void push(Node** head_ref, int new_data)


{
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = (*head_ref);
new_node->prev = NULL;
if ((*head_ref) != NULL)
(*head_ref)->prev = new_node;
(*head_ref) = new_node;
}
Insertion Operation-at tail

● The new node is always added after the last node of the given Linked List.
● For example, if the given DLL is 5->1->0->1->5->2 and we add item 30 at the end,
then the DLL becomes 5->1->0->1->5->2->30.
● Since a Linked List is typically represented by its head of it, we have to traverse the
list till the end and then change the next of last node to the new node.
Insertion Operation-at tail
Insertion Operation - at tail

C++: last->next = new_node;


void append(Node** head_ref, int new_data) new_node->prev = last;
{ return;
Node* new_node = new Node(); }
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) {
new_node->prev = NULL;
*head_ref = new_node;
return;
}
Node* last = *head_ref;
while (last->next != NULL)
last = last->next;
Insertion Operation-after given node
Insertion Operation - after given node

C++: new_node->next->prev = new_node;


void insertAfter(Node* prev_node, int }
new_data)
{
if (prev_node == NULL) {
cout << "the given previous node
cannot be NULL";
return;
}
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
new_node->prev = prev_node;
Insertion Operation-before given node
Insertion Operation - after given node

C++: new_node->next->prev = new_node;


void insertAfter(Node* prev_node, int }
new_data)
{
if (prev_node == NULL) {
cout << "the given previous node
cannot be NULL";
return;
}
Node* new_node = new Node();
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
new_node->prev = prev_node;
Assignment -

Q No 1: Implement the insert by key, and insert by index method of linked list
Q No 2: You can delete an element in a Linked List from:

1. Beginning
2. End
3. Middle
4. Middle given index
5. Middle given key

Write algorithm and code in C++ for all five ways for both Simple Linked List and
Doubly Linked List.

SUBMISSION DEADLINE: 7th November,2022 (11:00 PM)


Circular Linked List

● A circular linked list is that in which the last node contains the pointer to the first
node of the list.
● While traversing a circular linked list, we can begin at any node and traverse the list
in any direction forward and backward until we reach the same node we started.
Thus, a circular linked list has no beginning and no end.
Circular Linked List

● Node is represented as:

class Node {
public:
int data;
Node* next;
};
Traversal Operation

C++:

void traverse(Node* n){


Node* temp = head;
if (head != NULL) {
do {
cout << temp->data << " ";
temp = temp->next;
} while (temp != head);
}
}
Doubly Circular Linked List

● A Doubly Circular linked list or a circular two-way linked list is a more complex
type of linked list that contains a pointer to the next as well as the previous node in
the sequence.
● The difference between the doubly linked and circular doubly list is the same as that
between a singly linked list and a circular linked list. The circular doubly linked list
does not contain null in the previous field of the first node. Below is the image for
the same:
Doubly Circular Linked List

● Node is represented as:

class Node {
int data;
Node* next;
Node* prev;
};

You might also like