Linked List
Linked List
Linked List
Module 4
Linked List
Other list structures
Hashing
Syllabus
Module 1 Data Structure operations
Sorting algorithms
Dynamic memory allocation
Module 2 Stacks
Representation of Stacks in C
Applications
Module 3 Queues
Module 4 Linked List
Other list structures
Hashing
Other list structures - Circular lists and it’s primitive operations, Doubly linked
lists and it’s primitive operations, Applications of linked lists: Addition of long
positive integers, addition of Polynomials.
Special name is given to the address of first node as Head and last
node in the linked list can be identified because its next portion
points to Null
Linked list Data Structure
• A node contains two fields i.e. data stored at that particular
address and the pointer which contains the address of the next
node in the memory.
• The last node of the list contains pointer to the null.
Uses of Linked List
✓The list is not required to be contiguously present in the memory.
The node can reside any where in the memory and linked together
to make a list. This achieves optimized utilization of space.
✓list size is limited to the memory size and doesn't need to be
declared in advance.
✓Empty node can not be present in the linked list.
✓We can store values of primitive types or objects in the singly
linked list.
Why use linked list over array?
Array contains following limitations:
1.The size of array must be known in advance before using it in the program.
2.Increasing size of the array is a time taking process. It is almost impossible
to expand the size of the array at run time.
3.All the elements in the array need to be contiguously stored in the memory.
Inserting any element in the array needs shifting of all its predecessors.
Linked list is the data structure which can overcome all the limitations
of an array. Using linked list is useful because,
1.It allocates the memory dynamically. All the nodes of linked list are non-
contiguously stored in the memory and linked together with the help of
pointers.
2.Sizing is no longer a problem since we do not need to define its size at the
time of declaration. List grows as per the program's demand and limited to
the available memory space.
Singly Linked List
Arrange the name of the students
according to the 1st letter of their names
Michael
Rock
John
Smith
Tony
Alpha
Mark
23 54 78 90
1000 2000 3000 4000
1000
Head
Self Referential Structure: It is a structure which contains
a pointer to a structure of the same type.
struct abc {
int a;
char b;
struct abc *self;
};
We use self referential structure for creating a node of the
single linked list
Node representation in C
struct node {
Node
int data;
struct node *link;
};
Creating a node in C
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *link;
Node
};
void main() Null
{
struct node *head = Null; head
1000
head=(struct node *)malloc(sizeof(struct node ));
head->data = 45; head
head->link=Null;
45 Null
printf(“%d”, head->data); 1000
} 1000
head
Traversal if(head==0)
#include <stdio.h> {
#include <stdlib.h> head=temp=newnode;
struct node { }
int data; else
{
struct node* next;
temp->next=newnode;
};
temp=newnode;
struct node *head, *newnode, *temp;
}
head=0;
printf(“Do you want to continue (0, 1)\n”);
int choice; scanf(“%d”, & choice);
while(choice) } TraversingCode
{ temp=head;
newnode = (struct node*)malloc(sizeof(struct node)); while(temp!=0)
printf(“Enter the data\n”); {
scanf(“%d”, &newnode->data); printf("%d", temp->data);
newnode->next=0; temp=temp->next;
}
Operations on Singly Linked List
• Insertion
The insertion into a singly linked list can be performed at different positions.
Based on the position of the new node being inserted, the insertion is categorized
into the following categories.
Sl. No Operation Description
1. Insertion at It involves inserting any element at the front of the list. We just
beginning need to a few link adjustments to make the new node as the
head of the list.
2. Insertion at end It involves insertion at the last of the linked list. The new node
of the list can be inserted as the only node in the list or it can be inserted
as the last one.
3. Insertion after It involves insertion after the specified node of the linked list. We
specified node need to skip the desired number of nodes in order to reach the
node after which the new node will be inserted
head
500
Insertion at 100
printf("\nEnter value\n");
scanf("%d",&newnode->data);
newnode->next = head;
head = newnode;
printf("\nNode inserted");
}
head
500
Insertion at end 100
printf("\nEnter value\n");
scanf("%d",&newnode->data);
newnode->next = 0
temp=head;
while(temp->next!=0)
{
temp=temp->next;
}
temp->next=newnode;
newnode
Insertion at specified location 100 400 5 400
400
int pos, i=1;
struct node { 7 200 1 400 9 0
int data;
struct node *next; 100 200 300
100
};
struct node *head, temp
3 pos
*newnode, *temp;
newnode =
(struct node *) malloc(sizeof( 21 i
struct node));
printf("\nEnter the
position");
scanf("%d",&pos);
if(pos>count)
{
printf(“Invalid position”);
} printf("Enter the data");
else scanf("%d", &newdata->data);
{ newnode->next=temp->next;
temp=head; temp->next=newnode;
while(i<pos)
{
Deletion
The Deletion of a node from a singly linked list can be performed at
different positions. Based on the position of the node being deleted,
the operation is categorized into the following categories.
void display()
{ 8 200
void peek()
struct node *temp; 300
{
temp=top;
if(top==0) 5 100
if(top==0)
{
{ 200
printf("stack is empty\n");
printf("stack is empty\n");
} 2 0
}
else 100
else
{
{
printf("Top element us %d", top->data);
while(temp!=0)
}
{
}
printf("%d", temp->data);
temp=temp->link;
}}}
Implementation of stack using linked list
head
top
200
300
7 400 8 100 1 0 2 0
8 200 5 100 2 0 200 400 100 200
300 200 100
void pop()
{ 8 200
struct node *temp;
300
temp=top;
if(top==0) 5 100
{
200
printf("No elements");
} 2 0
else 100
{
printf("%d", top->data);
top=top->link;
free(temp)
}
}
Implementation of Queue using Linked List
Front rear
100 100 200 300
struct node
5 0 200 0 300 -3 0
{
int data; 100 200 300
void main()
struct node *next; if(front==0&&rear==0) {
}; { front=rear=newnode;
} enqueue(5);
struct node *front=0;
else enqueue(0);
{
struct node *rear=0; rear->next=newnode;
enqueue(-3);
void enqueue(int x) rear=newnode; } } display();
{ dequeue();
struct node *newnode; peek();
newnode=(struct node *) malloc(sizeof(struct node));
newnode->data=x;
}
newnode->next=0;
}
Implementation of Queue using Linked List
Front rear
100 100 200 300
struct node {
5 0 200 0 300 -3 0
int data;
struct node *next; 100 200 300
void main()
}; else {
{
struct node *front=0; temp=front; enqueue(5);
struct node *rear=0;
while(temp!=0) { enqueue(0);
printf(“%d”, temp->data);
void display() { temp=temp->next;
enqueue(-3);
struct node *temp; } display();
if(front==0 && rear ==0) dequeue();
{ peek();
printf(“Queue is empty);
}
}
Implementation of Queue using Linked List
Front rear
struct node
{ The prev part of the first node and
struct node *prev; the next part of the last node will
always contain null indicating end in
int data; each direction.
struct node *next;
}
Doubly Linked List
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, we can easily manipulate the elements of the list since the
list maintains pointers in both the directions (forward and
backward).
• In the following image, the first
element of the list that is i.e. 13
stored at address 1. The head
pointer points to the starting
address 1. Since this is the first
element being added to the list
therefore the prev of the
list contains null. The next node
of the list resides at address 4
therefore the first node contains 4
in its next pointer.
• We can traverse the list in this
way until we find any node
containing null or -1 in its next
part.
Operations on doubly linked list
• Node Creation
struct node
{
struct node *prev;
int data;
struct node *next;
};
struct node *head;
Operations
Sl. No Operations Descriptions
1 Insertion at beginning Adding the node into the linked list at beginning.
2 Insertion at end Adding the node into the linked list to the end.
3 Insertion at specified Adding the node into the linked list at the specified node.
node
4 Deletion at beginning Removing the node from beginning of the list
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 node
having given data containing the given data.
7 Searching Comparing each node data with the item to be searched and
return the location of the item in the list if the item found
else return null.
8 Traversing Visiting each node of the list at least once in order to
perform some specific operation like searching, sorting,
display, etc.
Insertion Operation
head
100
struct node{
int data; 0 5 200 100 4 250 200 2 0
struct node *prev; 250
head 100 200
struct node *next; tail
}; 0 100 0 100 200 250
struct node *head, *tail; tail
0 5 0 200 0 100 6 0
void createdll(){
struct node *newnode; 100 200
while(choice) {
newnode=(struct node*)malloc(size of(struct node) if(head==0){
head=0; head=tail=newnode;
printf(“Enter the data”); }
scanf(“%d”, &newnode->data); else{
newnode->prev=0; tail->next=newnode;
newnode->prev=tail;
newnode->next=0;
tail=newnode;
printf(“Do you want to continue(1,0)”);
scanf(“%d”, &choice);
Insertion Operation:
head
Insert at the beginning
150 500
struct node{
int data; 0 500 5 100 150 4 200 100 1 0
struct node *prev; 200
150 100
struct node *next;
}; 200
0 6 0 150 500
struct node *head, *tail; tail
newnode
void insertatbeg(){ 500
struct node *newnode;
newnode=(struct
node*)malloc(size of(struct head->prev=newnode;
node); newnode->next=head;
head=0; head=newnode;
printf(“Enter the data”); }
scanf(“%d”, &newnode->data);
newnode->prev=0;
newnode->next=0;
Insertion Operation:
head
Insert at the end
tail
500
200
struct node{
int data; 500 5 100 150 4 200 100 1 0 400
struct node *prev; 200
150 100
struct node *next;
};
0 6 150
struct node *head, *tail; 0 200 7 0
void insertatend(){ 500
400
struct node *newnode;
newnode=(struct node*)malloc(size of(struct node); 400
head=0; tail->next=newnode; newnode
printf(“Enter the data”); newnode->prev=tail;
scanf(“%d”, &newnode->data); tail=newnode;
newnode->prev=0; }
newnode->next=0;
Insertion Operation:
head
Insert
temp
at the pos
tail
150 150 100
200
500 500
struct node{
int data; 500 5 100 150 4 200 100 1 0
struct node *prev; 200
150 100
struct node *next;
0 100 7 0 200
};
struct node *head, *tail; struct node *newnode, *temp; 500 newnode
void insertatpos() { temp=head;
int pos, i=1; newnode=(struct node*)malloc(size of(struct node);
printf(“Enter the position”); head=0;
scanf(“%d”, &pos); printf(“Enter the data”);
if(pos<=0 && pos>count){ scanf(“%d”, &newnode->data);
printf(“Invalid position”); newnode->prev=0;
newnode->prev=temp;
} newnode->next=0;
newnode->next=temp->next;
else if(pos==1){ while(i<pos-1) {
temp->next=newnode;
insertatbeg(); temp=temp->next;
newnode->next->prev=newnode;
} i++;
}
else{ }
deletefromBeg()
Deletion Operation:
head
Delete
temp
from Beg deletefromEnd()
deletefromPos()
200 400 200
struct node {
int data;
struct node *next;
};
struct node *head;
void display()
{
struct node *temp;
if(head==0) {
printf(“List is empty”);
}
else
{
temp=head;
while(temp->next!=head){
printf(“%d”, temp->data);
temp=temp->next;
}
printf(“%d”, temp->data);
}}
head tail
struct node
200 200 100 Create using head and tail
{
int data;
struct node *next; 7 100 1 200
}; 200 100
struct node *head, *tail;
void createCLL(){
int choice=1;
struct node *newnode;
else
head=0; {
while(choice){ tail->next=newnode;
newnode=(struct node *)malloc(sizeof(struct node)); tail=newnode;
printf(“Enter the data\n”); }
scanf(“%d”, &newnode->data); tail->next=head;
newnode->next=0; printf(“Enter your choice\n”);
if(head==0) scanf(“%d”, &choice);
}
{
printf(“%d”, tail->next->data);
head=tail=newnode;
}
}
Creation tail
100 500
struct node { 150
int data;
7 100 6 0 100 1 0 100
struct node *next;
100 500 150
};
struct node *tail;
void createCLL(){
int choice=1;
struct node *newnode; else {
tail=0; newnode->next=tail->next;
while(choice){ tail->next=newnode;
newnode=(struct node *)malloc(sizeof(struct node)); tail=newnode;
}
printf(“Enter the data\n”);
printf(“Enter your choice\n”);
scanf(“%d”, &newnode->data);
scanf(“%d”, &choice);
newnode->next=0; }
if(tail==0) printf(“%d”, tail->next->data);
{ }
tail=newnode;
tail->next=newnode; }
struct node { temp tail
500 200
struct node{
int data;
5 600 4 100 1 200 7 500
struct node *next;
}; 500 600 100 200
struct node *tail;
void deletefromBeg(){
struct node *temp;
temp=tail->next; temp tail
if(tail==0) 600 600
{
tail->next=temp->next;
printf(“List is empty”);
free(temp); 5 600
}
else{ 600
if(tail==temp)
{
tail=0;
free(temp);
}
else{
Deletion from Circular Linked List:
Deletion from End temp
tail
500 200
struct node{
int data;
5 600 4 100 1 200 7 500
struct node *next;
}; 500 600 100 200
struct node *tail;
void deletefromEnd(){
struct node *temp, *prev;
temp=tail->next; temp tail
if(tail==0) 600 600
{
while(temp->next!=tail->next){
printf(“List is empty”);
prev=temp; 5 600
}
temp=temp->next;
else if(tail==temp) 600
}
{
prev->next=tail->next;
tail=0;
tail=prev;
free(temp);
free(temp);
}
}
else{
Deletion from Circular Linked List:
Deletion from Pos temp prev
tail
67 mod 10 = 7 Storing
Retrieving / Searching
5
6
67 7
48 8
9
Collision in Hashing
0
1 91
2 52 Suppose if we want to add 62 then how to store 62?
3 83 This process is called collision
4 24
0
5 Collision Resolution Techniques
1 91
6
2 52 62
7 67
8 48
3 83 Chaining Open addressing
4 24 (Open hashing) (Closed hashing)
9 • Linear Probing
5 • Quadratic Probing
6 • Double Probing
7 67
8 48
9
Chaining (Open hashing) 0 10
1
2 42
Keys: 42, 19, 10, 12 3
Hash Function: k mod 5 4 19
Advantages: Deletion is easy
Insertion is easy O(1)
0 10
1
Disadvantages: Searching is O(n) 2 12 42
Extra space 3
Load factor = Total number of elements/slots 4 19
= 4/5
Linear Probing 0 19
1
2 72
• Keys: 43, 135, 72, 23, 99, 19, 82 3 43
• Hash Function h(k): k mod 10 4 23
20 6 70
70 7
20 mod 11 = 9 70 mod 11=4
h2(k)=8-(70 mod 8) 8
=8-6 9 20
34 =2
h2(k)=8-(45 mod 8) 10
34 mod 11=1 =8-5
4+1(2) mod 11
4+2 mod 11
=3 6 mod 11
45 h1(k)+i h2(k)mod 11 6
1+ 1(3) mod 11
45 mod 11=1 1+3 mod 11
4 mod 11= 4