You are on page 1of 66

LINKED LIST

Abstract
Data Types

Doubly
Single
Linked
Linked List
List
LISTS

Circular
Polynomial
Linked
ADT
List

2
INTRODUCTION

 An array is a data structure where elements are stored in


consecutive memory locations.

 Memory required for the array is allocated in advance.

 Hence, an array is also called as static data structure.

 If some data has to be inserted or removed from the array in the


middle, some amount of data movement occurs. This consumes
computer time and decreases program efficiency.

 Dynamic data structure where the memory space can be extended.


Ex : linked – lists.
3
ARRAY LIMITATIONS
• arrays - advantages
• simple,
• fast
disadvantages:
• must specify size at construction time

more flexible data structure – linked list.


 A linked list is an ordered collection of data elements called nodes.

 Each node consists of two fields : data field and pointer field.

 Data field has the actual data. next


 Pointer field has the address of the
next element.

elem node
 An abstract data type (ADT) is a
set of operations.

 Objects such as lists, sets, and graphs, along with their operations, can
be viewed as abstract data types, just as integers, reals, and Booleans
are data types.
5
LIST ADT :

•First() : Returns the address of the first node in the linked list so the
other nodes to the right of it can be accessed.

•Last() : Returns the address of the last node in the linked list so the
other nodes to the right of it can be accessed.

•Insertfirst() : Inserts a node at the front of the linked list.

•Insertlast() : Inserts a node at the last of the linked list.

•Insertbefore() : Inserts a node before the specified node’s position.

•Insertafter() : Inserts a node after the specified node’s position.


6
•Remove() : removes a node at the specified position.
• Replace() : replaces a value stored at a position with some other value.

• Swap() : swap the values of the nodes specified by two positions.

Benefits of linked lists :

• As the linked lists are dynamic, memory is utilized optimally.


• List manipulations (adding new elements, removing elements etc)
are very simple pointer manipulations.
• Linked lists can be used to implement several other complex data
structures.
7
Singly Linked List
• A singly linked list is a
concrete data structure next
consisting of a sequence of
nodes
• Each node stores
1. data data node
2. link to the next node

(NULL)

A B C D 8
Singly Linked List (contd..)


(NULL)

Head B C D

• The very first node of the linked list is called Header node where no
data is stored, but holds the address of the very first data element.
• The elements can be traversed from left to right. Hence, it is also
called as one-way list.
9
Singly Linked List Operations

1) Insertion of a node into a singly linked list

2) Traversing the singly linked list

3) Deletion of a node from a singly linked list

4) Copying a linked list to make a duplicate

5) Merging two linked lists into a larger list

6) Searching for an element in a singly linked list


10
1.Insertion of a Node
A node can be inserted into a singly linked list in any of the
following three positions.
a) Insertion of a node at the front.
b) Insertion at the end.
c) Insertion at any position.

11
a) Insertion of a Node at the Front

ALGORITHM
1. Get a memory block of type NODE and store the starting address
of NODE in a pointer variable NEW.
i.e. NEW=GETNODE(NODE)
2. a) NEW.LINK = HEADER.LINK
b) NEW.DATA = X
c) HEADER.LINK = NEW
3. stop

12
b) Insertion of a Node at the End
ALGORITHM
1. Get a memory block of type NODE and store the starting
address
of this NODE in a pointer variable NEW.
i.e. NEW=GETNODE(NODE)
2. If NEW = NULL then print “Memory is Insufficient”
exit
Else
a) ptr = HEADER
b) ptr = ptr.LINK
13
3) When prt.LINK becomes NULL, ptr is the last node of the singly
linked list.
i. ptr.LINK = new
ii. new.data = X
iii. Make the LINK field of the new node to be NULL
i.e., make this new node as the last node.
NULL=new.LINK

14
c) Insertion of a Node at any position
ALGORITHM
1. Get a memory block of type NODE and store the address of it in a
pointer variable NEW.
i.e. NEW=GETNODE(NODE)
2. If NEW = NULL then print “Memory is Insufficient”
exit
Else
a) ptr = HEADER
b) Get the data item of the Node key after which the new node has
to be placed.
c) Now traverse the singly linked list from the HEADER node
i.e., ptr = ptr.LINK

15
3. If ( ptr.LINK = NULL)
print “ key is not available in the list”
exit.
Else
a) Make the LINK field of the new node to point the node
pointed out by ptr.
i.e., NEW.LINK = ptr.LINK
b) Place the data X in the DATA field of the NEW node.
i.e., NEW.DATA = X
c) Now make the LINK field of the ptr node to point the
NEW node. ptr.LINK=NEW

4. EXIT
16
2. Traversing through Singly Linked list
• Visiting each node in the singly linked list starting from the first
node to the last node.

ALGORITHM
1. Get the first node address from the pointer field of the HEADER
node. i.e., ptr = HEADER.LINK
2. Now traverse the singly linked list as long as ptr is not NULL.
i.e. while (ptr is not NULL) do steps (a) and (b).
a) Print the data in the ptr node.
i.e. print ptr.DATA.
b) Go to the next node of ptr.
i.e. ptr = ptr.LINK.
3. Stop. 17
3. Deletion of a Node

A node can be deleted from a singly linked list in any of the


following three positions.

a) Deletion of a node at the front.


b) Deletion of a node at the end.
c) Deletion of a node at any position.

18
a) Deletion of a Node at the Front
ALGORITHM
1. Get the address of the first node from the link field of the HEADER node.
i.e. ptr = HEADER.LINK
2. If ( ptr is NULL )
print “ The singly linked list is empty”
EXIT.
3. Otherwise do the following:
a) Get the address of the node which is pointed out by the first node.
i.e., ptr = ptr.LINK
b) Now the HEADER node should be made to point to the second node.
i.e. , HEADER.LINK = ptr.LINK.
c) Deallocate or free the space allocated for the ptr node.
i.e., return (ptr) to the free store.
4. stop
19
b) Deletion of a Node at the End

ALGORITHM
1. Start from the HEADER node. i.e., ptr = HEADER.
2. If the LINK field of HEADER node is NULL
print “ the list is empty; no deletion”.
3. Otherwise do the following :
a) Traverse the singly linked list from the first node to the last
node
to find the last but one node.
i.e., while (ptr.LINK is not NULL)
i. ptr1 = ptr.
ii. Ptr = ptr.LINK
b) ptr1.LINK = NULL
c) ptr is the last node of the singly linked list. 20
4. Stop.
c) Deletion of a Node at any position
ALGORITHM

1. Start from the HEADER node. i.e., ptr1 = HEADER


2. Get the LINK field of the HEADER node. i.e., ptr = ptr1.LINK
3. Accept the data X of the node which has to be deleted.
4. Check whether the LINK field of the HEADER node is NULL
a) If so,
print “ linked list is empty”
exit.
5. Otherwise do the following :
a) Traverse the singly linked list from the first node to the last node
to find the node with the value X.
i.e., while (ptr is not NULL) do step i. 21
i. If the data field of ptr is not X
• Go to the next node
• Store the previous node in ptr1
i.e., ptr1 = ptr
ptr = ptr.LINK
Otherwise make the previous node’s LINK field to point to the
next node.
i.e., ptr1.LINK = ptr.LINK
• Now return ptr to the free store.
• Exit.

22
Copy A Linked List To Make A Duplicate
• The entire singly linked list is copied into another by allocating
new memory
space.

ALGORITHM:

1. Start from the HEADER node. i.e., ptr = HEADER.


2. Allocate memory space for the single node in a singly linked list and
store it in HEADER1.
3. a) Assume that ptr1 is the pointer variable which points or holds the
HEADER node of duplicate linked list.
i.e., ptr1 = HEADER1
b) Make the data field of ptr1 to be NULL
23
i.e., ptr1.DATA = NULL
Copy A Linked List To Make A Duplicate
(contd..)
4. Now traverse the singly linked list from the first node to the last node
and do the following
i.e., while (ptr is not NULL) do the following

a) Allocate memory space for a node and store the starting address of it in NEW
i.e., NEW = GETNODE(NODE)
b) Move the DATA field of ptr node to the NEW node
i.e., NEW.DATA = ptr.DATA
c) Make the LINK field of ptr1 node to point to the NEW node
i.e., ptr1.LINK = NEW
d) Make the LINK field of the NEW node to be NULL
i.e., NEW.LINK = NULL
e) Make the NEW node to be the current node of the duplicate linked list.
i.e., ptr1 = NEW
f) Go to the next node of the original linked list
i.e., ptr = ptr.LINK 24
5. Stop.
Merging of two singly linked list into one list
• Two singly linked lists are combined to form a
singly linked list.

ALGORITHM:
1. Start from the HEADER node of the first singly linked list
i.e., ptr = HEADER1
2. Traverse the first singly linked list until the last node of this is
reached.
a) Go to the next node.
i.e., ptr = ptr.LINK
3. Once the last node is reached (ptr), make the LINK field of this last node to point
to the HEADER2 node’s LINK content
i.e., ptr.LINK = HEADER2.LINK
4. Now return the HEADER2 node to the free store.
5. Now HEADER1 is the HEADER node of the merged singly linked list.
i.e., HEADER = HEADER1. 25
6. Stop.
Search for an element in a singly linked list
• The nodes in a singly linked list are traversed to find a node
with the data X
ALGORITHM:
1. a) Start from the HEADER node. i.e., ptr = HEADER
b) Go to the first node in the singly linked list. i.e., ptr = ptr.LINK
2. Assume loc = NULL. Get the data to be searched – X
3. Now traverse the singly linked list from the first node to the last node.
a) If the DATA field of ptr node is X.
i. Loc = ptr
ii. Return loc
iii. Go to step 5
otherwise
i. Go to the next node of the singly linked list
4. If there is no match. Print “ Search is not successful”
5. Stop.
26
Doubly linked list
• Also called as two-way lists or two-way chains where it is
possible to traverse either from left to right or from right to left.
• Each node can have any number of data fields and two link fields
which are used to point to the previous node and next node.
• There are two NULL: at the first and last nodes in the list.
• Advantages:
• Given a node, it is easy to visit its predecessor.
• Convenient to traverse lists backwards


 A B C 

27
Head
• It is convenient to traverse lists backwards. Add an extra field
to the data structure, containing a pointer to the previous cell.
The cost of this is an extra link, adds to the space requirement
and also doubles the cost of insertions and deletions because
there are more pointers to fix.
• On the other hand, it simplifies deletion, because you no
longer have to refer to a key by using a pointer to the previous
cell; this information is now at hand.
Operations in a Doubly linked list
Insertion

Traversing the Doubly linked list

Deletion

Copying a doubly linked list to make a duplicate copy

Merging two linked lists into a larger list

Searching for an element in a doubly linked list

29
Function to check whether the list is empty or Function to check whether the element is in the last position
not int is_last (List L, position P)
int is_empty(list L) {
{ return(PtrRlink==NULL);
return(HeaderRlink==NULL); }
error(“List is empty”);
}

Function to Find the position of the element


position find(element type x, list L)
{
Position Ptr;
Ptr=HeaderRlink;
while (Ptr!=NULL && Ptrelement!=X)
Ptr=PtrRlink;
return Ptr;
}
Function to Insert an element Function to Delete an element
void insert(element X, list L, position Ptr) The position of the previous element is obtained by calling
{ the findLlink() function.
void delete(element X, list L)
Position new;
{
new=malloc(sizeof(struct node)); Position Ptr, toDel;
if(new==NULL) Ptr=Find Llink(X,L);
error(“new node is empty”); if(!islast(Ptr,L))
Newelement=X; {
NewRlink=PtrRlink; toDel =PtrRlink;
PtrRlink=new; PtrRlink=toDelRlink;
NewLlink=Ptr; Free(Todel);
} }
Circular linked lists
• A Circular Linked List is a special type of Linked List.

• It supports traversing from the end of the


list to the beginning by making the last
node point back to the head of the list.

•A Rear pointer is often used instead of a Head pointer

10 20 40 55 70

REAR 32
Circular linked lists (contd..)
• Circular linked lists are usually sorted.

Applications:
• Circular linked lists are useful for playing video and sound files

in “looping” mode.
• They are also a stepping stone to implementing graphs.

Advantages:
• Any node can be accessible from any other node by chaining

through the list.


• To delete a particular node, it is not necessary to start from the
very first node of the linked list. 33
• Operations like concatenation and splitting are more efficient.
Types of Circular linked lists
• Singly Linked Circular List : The last node points to the first node
and there is only link between the nodes
of the linked list.

10 20 40 55 70
• Doubly Linked Circular List : The last node points to the first node
and there are two links between the
nodes of the linked list.

 A B C

Head 34
Operations on a Circular linked list

 Insertion
 Traversing
 Deletion
 Copying
 Merging
 Searching

35
Function to Insert an element Function to Delete an element
The position of the previous element is obtained by
void insert(Element X,List L,position Ptr) calling the find Llink() function.
{ void delete(Element X, List L)
position Ptr, new; {
New =malloc(sizeof(struct node)); Position Ptr, toDel;
if(New=NULL) Ptr=findLlink(X,L);
Error(“Out of space”); toDel=PtrRlink;
NewElement=x; PtrRlink=toDelRlink;
If(ptrRlink=F) free(toDel);
NewRlink=PtrRlink; }
PtrRlink=New;
}
LINKED STACK
• In the linked list implementation, we would:
• Maintain the stack as a linked list.
• A pointer variable top points to the start of the list.
• The first element of the linked list is considered as the
stack top.
STACK: LINKED LIST STRUCTURE
PUSH OPERATION

top
STACK: LINKED LIST STRUCTURE
POP OPERATION

top
DECLARATION STACK CREATION

STRUCT LIFO
VOID CREATE (STACK **TOP)
{ {
INT VALUE; *TOP = NULL;
STRUCT LIFO *NEXT;
}; /* TOP POINTS TO NULL,
TYPEDEF STRUCT LIFO INDICATING EMPTY
STACK; STACK */
}
STACK *TOP;
PUSHING AN ELEMENT POPPING AN ELEMENT FROM THE
INTO THE STACK STACK
INT POP (STACK *TOP)
VOID PUSH (STACK *TOP, INT ELEMENT) {
{ INT T;
STACK *NEW; STACK *P;
NEW = MALLOC(SIZEOF(STACK)); IF (*TOP == NULL)
IF (TOP == MAX) {
{ PRINTF (“\N STACK IS EMPTY”);
PRINTF (“\N STACK IS FULL”);
EXIT(-1);
}
EXIT(-1); ELSE
} {
NEW->VALUE = ELEMENT; T = (*TOP)->VALUE;
NEW->NEXT = *TOP; P = *TOP;
*TOP = NEW; *TOP = (*TOP)->NEXT;
} FREE (P);
RETURN T;
}
}
LINKED QUEUE
• Create a linked list to which items would be added to one
end and deleted from the other end.
• Two pointers will be maintained:
• One pointing to the beginning of the list (point from
where elements will be deleted).
• Another pointing to the end of the list (point where new
elements will be inserted).
Rear

Front DELETION INSERTION


QUEUE: LINKED LIST STRUCTURE
ENQUEUE

front rear
QUEUE: LINKED LIST STRUCTURE
DEQUEUE

front rear
DECLARATION QUEUE CREATION

STRUCT NODE{ VOID INIT_QUEUE(_QUEUE *Q)


VALUE; {
STRUCT NODE *NEXT; Q->QUEUE_FRONT= Q-
}; >QUEUE_REAR=NULL;
}
TYPEDEF STRUCT {
_QNODE *QUEUE_FRONT, INT ISEMPTY(_QUEUE *Q)
*QUEUE_REAR; {
} _QUEUE; IF(Q==NULL) RETURN 1;
ELSE RETURN 0;
}
ENQUEUE DEQUEUE

_QNODE *ENQUEUE (_QUEUE *Q, ELEMENT X)


CHAR *DEQUEUE(_QUEUE *Q, ELEMENT X)
{
_QNODE *NEW; {
NEW= MALLOC (SIZEOF(_QNODE)); _QNODE *TODEL;
IF (NEW==NULL)
{
PRINTF(“BAD ALLOCATION \N"); IF(QUEUEFRONT==-1)
RETURN NULL;
PRINTF("QUEUE IS EMPTY \N");
}
WHILE(PTRLINK!=NULL) TODEL= FRONT;
PTR=PTRLINK PTRFRONT=FRONT;
IF(PTRLINK=NULL)
{ RETURN(TODEL)
NEWVALUE=X }
PTRLINK=NEW
NEWLINK=NULL;
REAR=NEW;
}
APPLICATIONS OF LINKED LIST
• APPLICATIONS OF LINKED LIST IN COMPUTER SCIENCE –

• Implementation of stacks and queues
• Implementation of graphs : adjacency list representation of graphs is most
popular which is uses linked list to store adjacent vertices.
• Dynamic memory allocation : we use linked list of free blocks.
• Maintaining directory of names
• Performing arithmetic operations on long integers
• Representing sparse matrices
• Manipulation of polynomials by storing constants in the node of linked list
• APPLICATIONS OF LINKED LIST IN REAL WORLD-
• Image viewer – previous and next images are linked, hence can be
accessed by next and previous button.
• Previous and next page in web browser – we can access previous and
next url searched in web browser by pressing back and next button
since, they are linked as linked list.
• Music player – songs in music player are linked to previous and next
song. You can play songs either from starting or ending of the list.
• APPLICATIONS OF CIRCULAR LINKED LISTS:

• Useful for implementation of queue. Unlike this implementation, we don’t need to


maintain two pointers for front and rear if we use circular linked list. We can maintain
a pointer to the last inserted node and front can always be obtained as next of last.
EXAMPLE: THE POLYNOMIAL ADT

N
• AN ADT FOR SINGLE-VARIABLE POLYNOMIALS f ( x)   ai x i
i 0

• ARRAY IMPLEMENTATION
THE POLYNOMIAL ADT…
• Acceptable if most of the coefficients aj are nonzero, undesirable if this is not the case
• E.G. Multiply
P1 ( x)  10 x1000  5 x14  1
P2 ( x)  3x1990  2 x1492  11 x  5

• Most of the time is spent multiplying zeros and stepping through nonexistent
parts of the input polynomials
• Implementation using a singly linked list
• Each term is contained in one cell, and the cells are sorted in decreasing order of
exponents
Void mult_polynomial( POLYNOMIAL poly1, POLYNOMIAL poly2, POLYNOMIAL
Poly_prod )
{
Unsigned int i, j;
Zero_polynomial( poly_prod );
Poly_prodhigh_power = poly1high_power + poly2high_power;
If( poly_prodhigh_power > MAX_DEGREE )
Error("exceeded array size");
Else
For( i=0; i<=poly1high_power; i++ )
For( j=0; j<=poly2high_power; j++ )
Poly_prodcoeff_array[i+j] += poly1coeff_array[i] * poly2coeff_array[j];
Poly_prodpower[i+j] = poly1power[i] + poly2power[j];
}
DYNAMIC MEMORY MANAGEMENT
• Any processing requires memory to be allocated for their storage. New strings may be Input or
created, old strings discarded, and strings in general may expand or contract during this
Processing. This requires some means of allocating storage in segments of variable size, and
"Recycling" unused space for new data.
There are four design criteria for a memory allocator.
a) Efficiency of representation
b) speed of allocation
c) speed of "recycling“
d) utilization of memory.
THE BOUNDARY TAG REPRESENTATION
• Even though there is a large contiguous chunk of free space, the memory
manager perceives it as two smaller segments and so may falsely conclude that it
has insufficient free space to satisfy a large request.
• The task of identifying and Merging adjacent free segments should be done when
a segment is released.
• IDENTIFICATION: The simplest identification method would be to have the
neighbors' "used/free" flags kept in these locations. This means that each
segment needs "used/ free" flags at both ends. There are advantages to Storing a
length value rather than a pointer.
• COALESCENCE:To merge two or three adjacent blocks, it is necessary to change
all of their bookkeeping information. It is straightforward to find the beginning
of the following segment. To find the beginning of the preceding segment, either
a pointer to the beginning of the segment, or an offset
BOUNDARY TAG METHOD
ALLOCATING MEMORY
• Free list- a data structure to keep track of the “holes” between the allocated memory.

1. To satisfy an allocate request

2. To satisfy a deallocate request


3. If the new hole is immediately preceded or followed by a hole, the holes can be coalesced into a bigger
hole
• Free list implementations
• – Singly linked list

• – Doubly linked list


• – Buddy systems
• Memory manager must keep track of which parts of the heap are free, and which are allocated.
• It supports the following operations:

1. Acquire: allocates memory needed by programs


2. Release: deallocates memory no longer needed by programsed list
Singly-linked list implementation of free-list
• Acquire( )
- A node is searched following one of the allocation policy. If the block is bigger than
requested, it is divided into two. One part is allocated and one remains in the list.
• Release( )
– A new node must be inserted (if the adjacent block is not on the free list)
– Or a node, which contains the adjacent free block, must be modified.
– Searching for the place of the new or existing node has complexity o(n).
DOUBLY-LINKED LIST IMPLEMENTATION OF FREE-LIST
• Each node in the doubly linked list represents a free block. It keeps size & start address of the
free block and start addresses & sizes of the previous and next memory blocks. The adjacent
blocks may be or may not be free
• • The release operation does not combine adjacent free blocks. It simply prepends a node
corresponding to a released block at the front of the free list. This operation is thus O(1).
Adjacent free blocks are combined by acquire().
• • The acquire operation traverses the free list in order to find a free area of a suitable size. As it
does so it also combines adjacent free blocks.
• How does the memory manager choose a hole to respond to an allocate
request?
• Best fit-choose the smallest hole that is big enough to satisfy the request
• Problems: it leads to lots of little holes that are not big enough to satisfy any
requests called fragmentation
• One way to avoid making little holes is to give the client a bigger block than it
asked for.
• First fit-simply scans the free list until a large enough hole is found.
• Problems: leads to less fragmentation. There is still one problem: small holes
tend to accumulate near the beginning of the free list, making the memory
allocator search farther and farther each time.
• Next fit-starts each search where the last one left off, wrapping around to the
beginning when the end of the list is reached
• List- maintain separate lists, each containing holes of a different size. It can also
be used in a more general setting by rounding all requests up to one of a few pre-
determined choices.
• Problems: internal fragmentation occurs. Another problem with this approach is
how to coalesce neighbouring holes.
BUDDY SYSTEM
• Trick for coalescing holes with multiple free lists
• All blocks and holes have sizes which are powers of two and starts at an Address
that is an exact multiple of its size.
• Then each block has a “buddy” of the same size adjacent to it, such that
combining a block of size 2^n with its buddy creates a properly aligned block of
size 2^n+1
• To allocate a block of a given size, first round the size up to the next power of
two and look on the list of blocks of that size. If that list is empty, split a block
from the next higher list
• When deallocating a block, first check to see whether the block's buddy is free.
If so, combine the block with its buddy and add the resulting block to the next
higher free list.
Advantage:
• Both acquire( ) and release( ) operations are fast.
Disadvantages:
• Only memory of size that is a power of 2 can be allocated .Internal fragmentation
if Memory request is not a power of 2.
• When a block is released, its buddy may not be free, resulting in external
Fragmentation.
GENERALIZED LISTS
• A generalized list, A, is a finite sequence of n ≥ 0 elements, a0, a1, a2,
…, an-1, where i, is either an atom or a list. The elements i,0 ≤ i ≤ n –
1, that are not atoms are said to be the sublists of A.
• A list a is written as a = (a0, …, an-1 ), and the length of the list is n.
• A list name is represented by a capital letter and an atom is represented
by a lowercase letter.
• A0 is the head of list a and the rest (a1, …,
an-1) is the tail of list a.

4-65
EXAMPLES OF GENERALIZED LISTS
• A = ( ): the null, or empty, list; its length is zero.
• B = (a, (b, c)): a list of length two; its first element is the
atom a, and its second element is the linear list (b, c).
• C = (b, b, ( )): a list of length three whose first two
elements are the list b, and the third element is the null list.
• D = (a, d): is a recursive list of length two; d corresponds
to the infinite list d = (a, (a, (a, …))).
• Lists may be shared by other lists.
• Lists may be recursive.

4-66

You might also like