0% found this document useful (0 votes)
5 views53 pages

Unit 3

The document provides an overview of singly linked lists (SLL) and dynamic memory allocation in C, detailing operations such as insertion, deletion, and searching within the list. It explains memory management functions like malloc(), calloc(), realloc(), and free(), along with examples. Additionally, it outlines the structure of a linked list, including node creation and various methods for manipulating the list's contents.
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)
5 views53 pages

Unit 3

The document provides an overview of singly linked lists (SLL) and dynamic memory allocation in C, detailing operations such as insertion, deletion, and searching within the list. It explains memory management functions like malloc(), calloc(), realloc(), and free(), along with examples. Additionally, it outlines the structure of a linked list, including node creation and various methods for manipulating the list's contents.
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/ 53

UNIT-3

LILIST: Introduction, Dynamic memory allocation, Single Linked list, Advantages and disadvantages of
Si Single linked list, single linked list vs Array, Representation of a linked list in memory,
O Operations: insertion, deletion, search Implementation of stack, Queue using linked list, Circular
L linked list, Double linked list.

Dynamic Memory Allocation:


About malloc( ) and calloc( ) dynamic memory management functions with an example.
The function malloc( ) allocates a block of size bytes from the free memory pool (heap).
It allows a program to allocate an exact amount of memory explicitly, as and when needed.
Ptr=(cast_type *)malloc (byte_ size);

Ptr is a pointer of type cast_type.The malloc returns a pointer to an area of memory with size
byte_size.The parameter passed to malloc() is of the type byte_size. This type is declared in the
header file alloc.h. byte_size is equivalent to the unsigned int data type. Thus, in compilers where
an int is 16 bits in size, malloc() can allocate a maximum of 64KB at a time, since the maximum
value of an unsigned int is 65535.

Return value:

On success, i.e., if free memory is available, malloc() returns a pointer to the newly allocated
memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type
before using it to access the memory allocate.
.
Ex: 1) malloc(30); allocates 30 bytes of memory and returns the address of byte0.
2) malloc(sizeof(float)); allocates 4 bytes of memory and returns the address of byte0.

2) calloc( ) — allocates multiple blocks of memory(for arrays)


The function calloc( ) has the following prototype:
Ptr= (cast_type *)calloc(n,ele_ size);

calloc( ) provides access to the C memory heap, which is available for dynamic allocation of
variable-sized blocks of memory.
Unlike malloc(), the function calloc( ) accepts two arguments: n and ele_size. The parameter n
specifies the number of items to allocate and ele_size specifies the size of each item.

Return value:

✔ On success, i.e., if free memory is available, calloc( ) returns a pointer to the newly
allocated memory. Usually, it is generic pointer. Hence, it should be typecast to
appropriate data type before using it to access the memory allocated.
✔ On failure, i.e., if enough free memory does not exist for block, calloc( ) returns NULL.
Ex: 1) calloc(3,5); allocates 15 bytes of memory and returns the address of byte0.
2) calloc(6,sizeof(float)); allocates 24 bytes of memory and returns the address of byte0.

About free( ) and realloc( ) allocation functions with an example?


realloc( ) — grows or shrinks allocated memory
The function realloc( ) has the following prototype:
Ptr= realloc(ptr, newsize);

The function realloc() allocates new memory space of size newsize to the pointer variable ptr and
returns a pointer to the first byte of the new memory block.
ptr is the pointer to the memory block that is previously obtained by calling malloc(), calloc() or
realloc(). If ptr is NULL pointer, realloc() works just like malloc().

Return value:

✔ On success, this function returns the address of the reallocated block, which might be
different from the address of the original block.
✔ On failure, i.e., if the block can’t be reallocated or if the size passed is 0, the function
returns NULL.
The function realloc() is more useful when the maximum size of allocated block cann’t be
decided in advance.

Ex: int *a;


a=(int *) malloc(30); //first 30 bytes of memory is allocated.
a=(int *) realloc(a,15); //later the allocated memory is shrink to 15 bytes.
free( ) — de-allocates memory

The function free( ) has the following prototype:


free (ptr);

The function free( ) de-allocates a memory block pointed by ptr.


ptr is the pointer that is points to allocated memory by malloc( ), calloc( ) or realloc(). Passing an
uninitialized pointer, or a pointer to a variable not allocated by malloc( ), calloc() or realloc()
could be dangerous and disastrous.

Ex: int *a;


a=(int *) malloc(30); //first 30 bytes of memory is allocated.
free(a); //de-allocates 30 bytes of memory.

Single Linked List (SLL):

A singly linked list, or simply a linked list, is a linear collection of data items. The linear order is
given by means of POINTERS. These types of lists are often referred to as linear linked list.
* Each item in the list is called a node.
* Each node of the list has two fields:
1. Data - contains the element being stored in the list.
2. Next address- contains the address of the next node in the list.
* The last node in the list contains NULL pointer to indicate that it is the end of the list.

Conceptual view of Singly Linked List

Operations on single linked list


The operations on the list are as follows:
1. Creating the linked list
2. Displaying or Traversing the linked list
3. Inserting a node in linked list
a). Inserting a node at the beginning
b). Inserting a node at the end
c). Inserting a node after a given node
d). Inserting a node before a given node
4. Deleting a node from linked list
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after a given node
d). Deleting the node before a given node
5. Searching for a node in the linked list

1.Creating the linked list:


Linked list allows us to insert or delete nodes whenever necessary. First we have to create the
node.This is possible by using self referential structure, pointers and dynamic memory allocation
functions like malloc.
First we have to declare a structure and create memory by using malloc function.
struct node
{
int data;
struct node *next;
};
struct node *newnode,*start=NULL;
newnode=(struct node *) malloc(sizeof(struct node));
The above statement will allocate a block of memory whose size is equal to size of node of type
structure and its address is assigned to pointer variable new node. This pointer indicates the
beginning of linked list.

Creation of a linked list involves the following steps:


1. Allocate memory for new node
2. Assign data part of new node to element and next field to NULL
3. Assign START pointer to new node
4. Take pointer variable ptr which points to START
5. Move ptr to which points to the next field of ptr =NULL
6. Set next field of ptr points to new node
7. Repeat the above steps for the required number of node in the list

/* Function for Creating a linked list */


void create()
{
struct node *ptr,*newnode;
int ele;
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
while(ele!=-1)
{ newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
newnode->next=NULL;
if(start==NULL)
start=newnode;
else
{
ptr=start;
while(ptr->next!=NULL)
ptr=ptr->next;
ptr->next=newnode;
}
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
}
}

2.Displaying the linked list

We can display all the elements in a linked list.

Displaying the linked list involves the following steps:

1. Take pointer ptr which points to START


2. Move ptr which points to NULL
3. Print data part of ptr.

/*Function for Displaying the element of linked list*/


void display()
{
struct node *ptr;
ptr=start;
if(ptr==NULL)
printf("\n list is empty");
else
{
while(ptr!=NULL)
{
printf("%d ",ptr->data);
ptr=ptr->next;
}
}
}

3.Inserting a node in Linked list:

A new node can be inserted into linked list which requires resetting of pointers.
Inserting a new node into the list has 4 situations

a). Inserting a node at the beginning


b). Inserting a node at the end
c). Inserting a node after a given node
d). Inserting a node before a given node
The process of insertion involves search for the place of insertion .The search involves in locating
a node after which the new node is to be inserted.
a). Inserting a node at the beginning of a linked list involves the following steps:

1.Allocate memory for new node


2. Assign data part of newnode to element
3. Set next field of new node to START
4. Change START pointer point to the new node

/*Function for Inserting a node at beginning */


void insert_beg()
{
struct node *newnode;
int ele;
printf("Enter element");
scanf("%d",&ele);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
newnode->next=start;
start=newnode;
}

b). Inserting a node at the end of a linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element and next field to NULL
3. Take pointer variable ptr which points to START
4. Move ptr which points to last node
5. Set next part of ptr to address of newnode

/*
Function for inserting a node at end*/
void insert_end()
{
struct node *ptr,*new_node;
int ele;
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=ele;
new_node->next=NULL;
ptr=start;
while(ptr->next!=NULL)
ptr=ptr->next;
ptr->next=new_node;
}
c).Inserting a node after a given node involves following steps:

1. Allocate memory for new node


2. Assign data part of new node to element
3. Search for the given key element by using search function and assign key element address
to keyptr
4. Set next field of new node point to next field of keyptr
5. Set next field of keyptr node point to newnode

/*Function for Inserting a node after a given node*/


void insert_after()
{
struct node *keyptr,*newnode;
int ele,key;
printf("\nEnter nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
newnode->next=keyptr->next;
keyptr->next=newnode;
}}
d). Inserting a node before a given node involves following steps:
1. Allocate memory for new node
2. Assign data part of newnode to element
3. Search for the given key element by using search function and assign key element address
to keyptr
4. Take pointer variable ptr which points to START
5. Move ptr which points to before node of keyptr
6. Set next field of ptr point to newnode
7. Set next field of newnode point to keyptr

/*Function for Inserting a node before a given node*/


void insert_before()
{
struct node *keyptr,*newnode,*ptr;
int ele,key;
printf("\nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
ptr=start;
while(ptr->next!=keyptr)
ptr=ptr->next;
ptr->next=newnode;
newnode->next=keyptr;
}
}

4.Deleting a node from linked list


Deleting a node from the list is easier than insertion as only one pointer needs to be changed.
Here again we have four different situations
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after a given node
d). Deleting the node before a given node
The memory space of deleted node may be released for reuse .The process of deletion also
involves search for the item to be deleted.

a). Deleting the first node involves the following steps


1. Take pointer variable ptr which points to START
2. START pointer is altered to point to the next field of START node in the list
3. Deallocate memory for first node from list.
/*Function for Delete first node*/
void delete_first()
{
struct node *ptr;
ptr=start;
start=start->next;
free(ptr);
}

b). Deleting the last node involves the following steps


1. Take pointer variables preptr and ptr which points to START
2. Move ptr such that next field of ptr = NULL and preptr points to ptr(address of before
node of ptr)
3. Set next field of preptr points to NULL
4. Deallocate memory for ptr node from list.

/*Function for Deleting last node*/


void delete_last()
{
struct node *ptr,*preptr;
ptr=start;
while(ptr->next!=NULL)
{
preptr=ptr;
ptr=ptr->next;
}
preptr->next=NULL;
free(ptr);
}

c). Deleting the node after the given node involves the following steps
1. Search for the given key element by using search function and assign key element address to
keyptr
2. Take pointer variable Aptr which points to next field of keyptr
3. Set next field of keyptr to next field of Aptr
4. Deallocate memory for Aptr node from list

/*Function for deleting a node after given node*/


void delete_after()
{
struct node *keyptr,*Aptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
Aptr=keyptr->next;
keyptr->next=Aptr->next;
free(Aptr);
}
}
d). Deleting the node before the given node involves the following steps
1. Search for the given key element by using search function and assign key element address
to keyptr
2. Take pointer variable ptr which points to START
3. Move ptr such that next field of ptr = keyptr and preptr points to ptr(address of before
node of ptr)
4. Set next field of keyptr to next field of ptr
5. Deallocate memory for ptr node from list

/*Function for deleting a node before given node*/


void delete_before()
{
struct node *ptr,*keyptr,*preptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{ ptr=start;
while(ptr->next!=keyptr)
{ preptr=ptr;
ptr=ptr->next;
}
preptr->next=ptr->next;
free(ptr);
}
}
}

5.Searching a node in linked list:-


The search function attempts to locate the requested element in the linear list. If the node in the
list matches with key, the search returns true if no key matches, it returns false.
The function given below searches through the linked list and returns a pointer the first
occurrence of the search key or returns NULL pointer if the search key is not in the list

Searching a node in linked list involves the following steps

1. Take pointer variable ptr which points to START


2. Move ptr which points to NULL
3. If data part of ptr =key then return ptr otherwise return NULL

/* Function for Search of a element in linked list*/


struct node* search(int key)
{
struct node *ptr;
ptr=start;
while(ptr!=NULL)
{
if(ptr->data==key)
return ptr;
ptr=ptr->next;
}
return NULL;
}
Program for SLL:
#include <stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert();
void del();
void display();
void search();
void reverse();
void count();
struct node* create(int data);
int c=0,b=0;
void main()
{
int a,ch;
head=NULL;
while(1)
{
scanf("%d",&ch);
switch(ch)
{
case 1:insert();
break;
case 2:del();
break;
case 3:display();
break;
case 4:search();
break;
case 5:count();
break;
case 6:reverse();
break;
case 7:exit(0);
default: printf("Invalid Choice");
}
}
}
void insert()
{
int p,i,n;
struct node *temp=(struct node *)malloc(sizeof(struct node));
struct node *temp2;
scanf("%d%d",&p,&n);
if(p<=0||p>c+1)
printf("\nPosition does not exist - Cannot insert into SLL");
else
{
c++;
temp->data=n;
temp->next=NULL;
if(p==1)
{
temp->next=head;
head=temp;
}
else
{
temp2=head;
for(i=0;i<p-2;i++)
temp2=temp2->next;
temp->next=temp2->next;
temp2->next=temp;
}
}
}
void del()
{
int p,i;
struct node *temp1=head,*temp2;
scanf("%d",&p);
if(p<=0||p>c)
printf("\nPosition does not exist - Cannot delete from SLL");
else
{
c--;
if(p==1)
{
head=temp1->next;
printf("\nDeleted element from SLL is %d",temp1->data);
free(temp1);
}
else
{
for(i=0;i<p-2;i++)
temp1=temp1->next;
temp2=temp1->next;
temp1->next=temp2->next;
printf("\nDeleted element from SLL is %d",temp2->data);
free(temp2);
}
}
//printf("\nDeleted element from SLL is %d",temp2->data);
}
void search()
{
int n,p=0,b=0;
struct node *x;
//printf("Enter the element to be searched");
scanf("%d",&n);
x=head;
while(x!=NULL)
{
p++;
if(x->data==n)
{
b=1;
break;
}
x=x->next;
}
if(b==1)
printf("\n%d is found in SLL",n);
else
printf("\n%d is not found in SLL",n);
}
void display()
{
struct node *x;
x=head;
printf("\n");
while(x!=NULL)
{
printf("%d ->",x->data);
x=x->next;
}
if(head==NULL)
printf("Empty SLL - Cannot display");
}
void count()
{
struct node *x;
int n=0;
x=head;
while(x!=NULL)
{
n++;
x=x->next;
}
printf("\nNo of nodes in SLL = %d",n);
}
void reverse()
{
struct node *x,*p=NULL;
x=head;
if(head==NULL)
return;
while(x!=NULL)
{
struct node *y=create(x->data);
y->next=p;
p=y;
x=x->next;
}
head=p;
display();
}
struct node* create(int data)
{
struct node* new_node = (struct node*) malloc (sizeof(struct node));
new_node -> data = data;
new_node -> next = NULL;
return new_node;
}

ADVANTAGES OF SINGLE LINKED LIST:

1. Linked list is Dynamic data structure- It is not necessary to know in advance the number
of elements to be stored in the list . At run time we can allocate as much memory as we
can. Though we can allocate any number of nodes in linked list.
2. Linked list can grow and shrink during run time.
3. Insertion and deletion operations are easier.-We can insert any node at any place easily
and similarly we can remove it easily. In insertion operation we have to just update next
link of node.
4. Efficient memory utilization i.e; no need to pre allocate memory.-Memory is allocated at
run time as per requirement, so that linked list data structure provides us strong command
on memory utilization
5. Faster access time, can be expanded in constant time without memory over head.
6. Linear data structures such as stack, queue can be easily implemented using linked list.

DISADVANTAGES OF LINKED LIST

1. Wastage of memory- Pointer requires extra memory for storage


2. No Random Access- In array we can access nth element easily just by using a[n].
3. In linked list no random access is given to user, we have to access each node sequentially.
4. Time Complexity-Individual nodes are not stored in the contiguous memory locations.
Access time for individual element is O(n) where as array O(1).
5. Reverse Traversing is difficult- It is very difficult to traverse linked list from end.Heap
space restriction- If there is insufficient space in heap then it won’t create any memory.
Linked List vs. Array

ARRAY LINKED LIST

Linked List is an ordered collection of elements of same type,


Array is a collection of elements of similar data type.
which are connected to each other using pointers.

Array supports Random Access, which means elements can


Linked List supports Sequential Access, which means to access any
be accessed directly using their index, like arr[0] for 1st
element/node in a linked list, we have to sequentially traverse the
element, arr[6] for 7th element etc.
complete linked list, upto that element.
Hence, accessing elements in an array is fast with a constant
To access nth element of a linked list, time complexity is O(n).
time complexity of O(1).
In a linked list, new elements can be stored anywhere in the memory.

In an array, elements are stored in contiguous memory Address of the memory location allocated to the new element is stored
location or consecutive manner in the memory. in the previous node of linked list, hence formaing a link between the

two nodes/elements.
In case of linked list, a new element is stored at the first free and

available memory location, with only a single overhead step of


In array, Insertion and Deletion operation takes more
time, as the memory locations are consecutive and fixed.storing the address of memory location in the previous node of linked
list.

Insertion and Deletion operations are fast in linked list.


Memory is allocated as soon as the array is declared,
Memory is allocated at runtime, as and when a new node is added. It's
at compile time. It's also known as Static Memory
also known as Dynamic Memory Allocation.
Allocation.
In array, each element is independent and can be In case of a linked list, each node/element points to the next, previous,
accessed using it's index value. or maybe both nodes.
Array can be single dimensional, two Linked list can be Linear (Singly) linked list, Doubly linked list or
dimensional or multidimensional Circular linked list linked list.
Size of the array must be specified at time of array Size of a Linked list is variable. It grows at runtime, as more
decalaration. nodes are added to it.
Array gets memory allocated in the Stack section. Whereas, linked list gets memory allocated in Heap section.

STACK USING LINKED LIST

To implement a stack using linked list we need to define a node which in turn consists of data and
a pointer to the next node. The advantage of representing stacks using linked lists is that we can
decide which end should be the top of the stack.
In our example we will select front end as the top of the stack in which we can add and remove
data.
The working principle of stack is LIFO. Using a linked list is one way to implement a stack so
that it can handle essentially any number of elements. The operations performed on a stack are
push ( ) and pop ( ).When implementing a stack using linked lists, pushing elements on to the
stack and popping elements from the stack is performed at the same end i.e. TOP.

Pushing elements to the stack:


1. Allocate memory for the new node.
2. Assign the value to the data field of the new node.
3. If stack is empty then Set next field of the new node to NULL and set TOP pointer points to
the new node .
5. Otherwise Set the next field of the newnode pointsto TOP and set TOP pointer points to the
new node

Popping elements from the stack:


1. If stack is empty, then display message “stack is empty – no deletion possible” and exit.
2.Otherwise, Take pointer variable ptr which points toTOP
3. set TOP points to the next field of TOP
4. Deallocate memory for ptr node from list

/*Program for stack using linked list */


#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void push(int);
void pop();
void display();
void main()
{
int n,a,p,ch;
head=NULL;
while(1)
{
scanf("%d",&ch);
switch(ch)
{
case 1:scanf("%d",&n);
push(n);
break;
case 2:pop();
break;
case 3:display();
break;
case 4:exit(0);
default:printf("\nInvalid option");
}
}
}
void push(int n)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data=n;
temp->next=head;
head=temp;
}
void pop()
{
int i;
struct node *temp1=head;
if(head==NULL)
{
printf("\nSTACK UNDERFLOW - CANNOT POP");
exit(0);
}
else
{
i=temp1->data;
head=temp1->next;
}
printf("\nPopped element from stack is %d",i);
free(temp1);
}
void display()
{
struct node *x;
x=head;
printf("\n");
if(head==NULL)
printf("\nEMPTY STACK - NOTHING TO DISPLAY");
else
{
printf("\nTHE ELEMENTS OF STACK ARE -");
while(x!=NULL)
{
printf("%d ->",x->data);
x=x->next;
}
}
}

QUEUE USING LINKED LIST

Like stacks when implementing a queue using linked list a node must be defined .Front end of
Queue is used to remove data and rear end is used to add data. The advantage of representing a
queue using linked list is that it allows us to select any end to add and remove data items. So, we
can select the end of the linked list as rear and beginning of the list as front.

The working principle of queue is FIFO. Using a linked list is one way to implement a queue so
that it can handle essentially any number of elements. The operations performed on a queue are
enqueue ( ) and dequeue ( ).When implementing a queue using linked lists, inserting elements to
the queue is done at one end and deletion of elements from the queue is done at the other end.
Inserting a node at the Rear end:

1. Allocate memory for the new node.


2. Assign the value to the data field of the new node.
3. Set the next field of the new node to NULL.
4. If the queue is empty, then set FRONT and REAR pointer points to the new node.
5. Otherwise, Set the next field of REAR points to new node.
6. Set REAR pointer points to the new node.

Deleting a node at the Front end:

1. If queue is empty, then display message “ Queue is empty – no deletion is possible” and
exit.
2. Otherwise, Take pointer variable ptr which points toFRONT.
3. Set FRONT points to the next field of FRONT.
4. Deallocate memory for ptr node from list.

/*Program for queue using Linked List*/


#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
int c=0;
struct node *head;
void enqueue(int);
void dequeue();
void display();
void main()
{
int n,a,p,ch;
head=NULL;
while(1)
{
scanf("%d",&ch);
switch(ch)
{
case 1:scanf("%d",&n);
enqueue(n);
break;
case 2:dequeue();
break;
case 3:display();
break;
case 4:exit(0);
default:printf("\nInvalid Choice");
}
}
}
void enqueue(int n)
{
int i;
struct node *temp=(struct node *)malloc(sizeof(struct node));
struct node *x;
c++;
temp->data=n;
temp->next=NULL;
if(head==NULL)
head=temp;
else
{
x=head;
for(i=0;i<c-2;i++)
x=x->next;
x->next=temp;
}
}
void dequeue()
{
int i;
struct node *temp1=head;
if(head==NULL)
printf("\nQUEUE UNDERFLOW - No nodes to delete");
else
{
c--;
i=temp1->data;
head=temp1->next;
printf("\nThe DEQUEUED Node VAL = %d",i);
free(temp1);
}
}
void display()
{
struct node *x;
x=head;
printf("\n");
if(head==NULL)
printf("Empty QUEUE - NOTHING TO DISPLAY");
else
{
printf("\nTHE ELEMENTS OF QUEUE ARE -");
while(x!=NULL)
{
printf("%d ->",x->data);
x=x->next;
}
}
}
CIRCULAR LINKED LIST

A circularly linked list, or simply circular list, is a linked list in which the last node always points
to the first node. This type of list can be build just by replacing the NULL pointer at the end of the
list with a pointer which points to the first node. There is no first or last node in the circular list.

Advantages:
● Any node can be traversed starting from any other node in the list.

● There is no need of NULL pointer to signal the end of the list and hence, all pointers
contain valid addresses.
● In contrast to singly linked list, deletion operation in circular list is simplified as the search
for the previous node of an element to be deleted can be started from that item itself.
Conceptual view of circular linkedlist

OPERATIONS ON CIRCULAR LINKED LIST

The operations on a circular linked list are as follows:


1. Creating the circular linked list
2. Displaying or traversing the linked list
3. Inserting a node in circular linked list
a). Inserting a node at the beginning
b). Inserting a node at the end
c). Inserting a node after a given node
d). Inserting a node before a given node
4. Deleting a node from circular linked list
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after a given node
d). Deleting the node before a given node
5. Searching for a node in circular linked list

1. Creating the circular linked list:

Linked list provides to insert or delete nodes whenever necessary. First we have to create the
nodes. This is possible by using self referential structure, pointers and dynamic memory
allocation functions like malloc.First we have to declare structure and create memory by using
malloc function.
struct node
{
int data;
struct node *next;
};
struct node *newnode,*start=NULL;
newnode=(struct node *) malloc(sizeof(struct node));
The above statement will allocate a block of memory whose size is equal to size of node of type
structure and its address is assigned to pointer variable newnode. This pointer indicates the
beginning of linked list

Creation of a circular linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element
3. Assign START point to newnode and next field of newnode to START
4. Take pointer variable ptr which points to START
5. Move ptr to which points to the next field of ptr! =START
6. Set next field of ptr points to newnode and next field of newnode to START
7. Repeat the above steps for the required number of nodes in the list

/* Function for Creating a circular linked list */


void create()
{
struct node *ptr,*newnode;
int ele;
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
while(ele!=-1)
{
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
if(start==NULL)
{
start=newnode;
newnode->next=start;
}
else
{
ptr=start;
while(ptr->next!=start)
ptr=ptr->next;
ptr->next=newnode;
newnode->next=start;
}
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);

}
}

2. Displaying the circular linked list


We can display the all the elements in a linked list.

Displaying the circular linked list involves the following steps

4. Take pointer ptr which points to START


5. Move ptr to which points to the next field of ptr! =START
6. Print data part of ptr.

/*Function for Displaying the element of circular linked list*/


void display()
{
struct node *ptr;
ptr=start;
if(ptr==NULL)
printf("\n list is empty");
else
{
while(ptr->next!=start)
{
printf("%5d->",ptr->data);
ptr=ptr->next;
}
printf("%5d",ptr->data);
}
}

3. Inserting a node in circular Linked list:


A new node can be inserted into linked list which requires resetting of pointers.
Inserting a new node into the list has 4 situations
a). Inserting a node at beginning
b). Inserting a node at end
c). Inserting a node after a given node
d). Inserting a node before a given node
The process of insertion involves search for the place of insertion .The search involves in locating
a node after which the new node is to be inserted.

a). Inserting a node at the beginning of a circular linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element
3. Set next field of new node to START
4. Take pointer ptr which points to START
5. Move ptr to which points to the next field of ptr! =START
6. Change START pointer point to the new node
7. Set next field of ptr to START

/*Function for Inserting a node at beginning */


void insert_beg()
{
struct node *newnode,*ptr;
int ele;
printf("Enter element");
scanf("%d",&ele);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
newnode->next=start;
ptr=start;
while(ptr->next!=start)
ptr=ptr->next;
start=newnode;
ptr->next= start;
}

b). Inserting a node at the end of a circular linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element
3. Take pointer variable ptr which points to START
4. Move ptr to which points to next field of ptr!=START
5. Set next field of ptr to newnode
6. Set next field of newnode to START

/* Function for inserting a node at end*/


void insert_end()
{
struct node *ptr,*newnode;
int ele;
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
ptr=start;
while(ptr->next!=start)
ptr=ptr->next;
ptr->next=newnode;
newnode->next=start;
}

c).Inserting a node after a given node involves following steps:


1. Allocate memory for new node
2. Assign data part of new node to element
3. Search for given key element by using search function and assign key ele address to
keyptr
4. Set next field of new node points to next field of Keyptr
5. Set next field of keyptr node points to newnode
/*Function for Inserting a node after a given node*/
void insert_after()
{
struct node *keyptr,*newnode;
int ele,key;
printf("\nEnter nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
newnode->next=keyptr->next;
keyptr->next=newnode;
}
}

d). Inserting a node before a given node involves following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element
3. Search for given key element by using search function and assign key ele address to
keyptr
4. Take pointer variable ptr which points to START
5. Move ptr which points to before node of keyptr
6. Set next field of ptr point to newnode
7. Set next field of newnode point to keyptr
/*Function for Inserting a node before a given node*/
void insert_before()
{
struct node *keyptr,*newnode,*ptr;
int ele,key;
printf("\nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
ptr=start;
while(ptr->next!=keyptr)
ptr=ptr->next;
ptr->next=newnode;
newnode->next=keyptr;
}
}

4.Deleting a node from circular linked list


Deletion of a node into the list has 4 situations
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after the given node
d). Deleting the node before the given node

The memory space of deleted node may be released for reuse .The process of deletion also
involves search for the item to be deleted.

a). Deleting the first node involves the following steps

1 Take pointer variable ptr which points to START


2 Move ptr to which points to next field of ptr!=START
3 Set next field of ptr points to the next field of START
4 Deallocate memory for first node from list.
5 Set START which points to the next field of ptr

/*Function for Delete first node*/


void delete_first()
{
struct node *ptr,*temp;
ptr=start;
while(ptr->next!=start)
ptr=ptr->next;
ptr->next=start->next;
free(start);
start=ptr->next;
}

b). Deleting the last node involves the following steps

1. Take pointer variables preptr and ptr which points to START


2. Move ptr such that next field of ptr !=START and preptr points to ptr(address of before
node of ptr)
3. Set next field of preptr points to START
4. Deallocate memory for ptr node from list.
/*Function for Deleting last node*/
void delete_last()
{
struct node *ptr,*preptr;
ptr=start;
while(ptr->next!=start)
{
preptr=ptr;
ptr=ptr->next;
}
preptr->next=start;
free(ptr);
}

c). Deleting the node after the given node involves the following steps

1. Search for the given key element by using search function and assign key element address to
keyptr
2. Take pointer variable Aptr which points to next field of keyptr
3. Set next field of keyptr to next field of Aptr
4. Deallocate memory for Aptr node from list
/*Function for deleting a node after given node*/
void delete_after()
{
struct node *keyptr,*Aptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
Aptr=keyptr->next;
keyptr->next=Aptr->next;
free(Aptr);
}
}

d). Deleting the node before the given node involves the following steps

1. Search for the given key element by using search function and assign key element address
to keyptr
2. Take pointer variable ptr which points to START
3. Move ptr such that next field of ptr = keyptr and preptr points to ptr(address of before
node of ptr)
4. Set next field of keyptr to next field of ptr
5. Deallocate memory for ptr node from list

/*Function for deleting a node before given node*/


void delete_before()
{
struct node *ptr,*keyptr,*preptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{ ptr=start;
while(ptr->next!=keyptr)
{ preptr=ptr;
ptr=ptr->next;
}
preptr->next=ptr->next;
free(ptr);
}
}
}

5.Searching a node in circular linked list:-


The search function attempts to locate the requested element in the linear list. If the node in the
list matches with key, the search returns true if no key matches, it returns false.
The function given below searches through the linked list and returns a pointer the first
occurrence of the search key or returns NULL pointer if the search key is not in the list

Searching a node in circular linked list involves the following steps

1. Take pointer variable ptr which points to START


2. If data part of ptr=key then return ptr and ptr points to next filed of ptr
3. Move ptr which is not equals to START
4. If data part of ptr =key then return ptr otherwise return NULL

/* Function for Search of a element in linked list*/


struct node* search(int key)
{
struct node *ptr;
ptr=start;
if(ptr->data==key)
return ptr;
ptr=ptr->next;
while(ptr!=start)
{
if(ptr->data==key)
return ptr;
ptr=ptr->next;
}
return NULL;
}

Program for circular linked list


#include <stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head=NULL;
void insert();
void del();
void display();
void search();
int c=0,b=0;
void main()
{
int ch;
head=NULL;
while(1)
{
scanf("%d",&ch);
switch(ch)
{
case 1:insert();
break;
case 2:del();
break;
case 3: display();
break;
case 4: search();
break;
case 5:exit(0);
default: printf("Invalid Choice");
}
}
}
void insert()
{
int p,i,n;
struct node *temp=(struct node *)malloc(sizeof(struct node));
struct node *temp2,*x;
scanf("%d%d",&p,&n);
if(p<=0||p>c+1)
printf("\nPosition does not exist - Cannot insert into CLL");
else
{
c++;
temp->data=n;
temp->next=NULL;
if(p==1)
{
temp->next=head;
head=temp;
x=head;
for(i=0;i<c-1;i++)
x=x->next;
x->next=temp;
}
else
{
temp2=head;
for(i=0;i<p-2;i++)
temp2=temp2->next;
temp->next=temp2->next;
temp2->next=temp;
}
}
}
void del()
{
int p,i;
struct node *temp1=head,*temp2,*x;
scanf("%d",&p);
if(p<=0||p>c)
printf("\nPosition does not exist - Cannot delete from CLL");
else
{
c--;
if(p==1)
{
head=temp1->next;
printf("\nDeleted element from CLL is %d",temp1->data);
free(temp1);
x=head;
for(i=0;i<c-1;i++)
x=x->next;
x->next=head;
}
else
{
for(i=0;i<p-2;i++)
temp1=temp1->next;
temp2=temp1->next;
temp1->next=temp2->next;
printf("\nDeleted element from CLL is %d",temp2->data);
free(temp2);
}
}
}
void search()
{
int n,b=0,m=0;
struct node *x;
scanf("%d",&n);
x=head;
while(m<c)
{
if(x->data==n)
{
b=1;
break;
}
x=x->next;
m++;
}
if(b==1)
printf("\n%d is found in CLL",n);
else
printf("\n%d is not found in CLL",n);
}
void display()
{
int m=0;
struct node *x;
x=head;
if(head==NULL)
printf("Empty CLL - Cannot display");
//printf("\n");
while(m<c)
{
printf("%d ->",x->data);
x=x->next;
m++;
}

DOUBLE LINKED LIST

In a singly linked list, each element contains a pointer to the next element. We have seen this
before. In single linked list, traversing is possible only in one direction. Sometimes, we have to
traverse the list in both directions to improve performance of algorithms. To enable this, we
require links in both the directions, that is, the element should have pointers to the right element
as well as to its left element. This type of list is called doubly linked list.

Conceptual view of doubly linked list

Doubly linked list is defined as a collection of elements, each element consisting of three fields:
• Pointer to left element,
• Data field, and
• Pointer to right element.
Left link of the leftmost element is set to NULL which means that there is no left element to that.
And right link of the rightmost element is set to NULL which means that there is no right element
to that.

OPERATIONS ON DOUBLE LINKED LIST

The operations on double linked list are as follows:


1. Creating the doubly linked list
2. Displaying or traversing the doubly linked list
3. Inserting a node in doubly linked list
a). Inserting a node at beginning
b). Inserting a node at end
c). Inserting a node after a given node
d). Inserting a node before a given node
4. Deleting a node from doubly linked list
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after the given node
d). Deleting the node before the given node
5. Searching for a node in doubly linked list

1.Creating the double linked list:


Double Linked list provides to insert or delete nodes whenever necessary. First we have to create
the nodes. This is possible by using self referential structure, pointers and dynamic memory
allocation functions like malloc.First we have to declare structure and create memory by using
malloc function.

struct node
{
struct node *prev;
int data;
struct node *next;
};
struct node *newnode,*start=NULL;
newnode=(struct node *) malloc(sizeof(struct node));
The above statement will allocate a block of memory whose size is equal to size of node of type
structure and its address is assigned to pointer variable newnode. This pointer indicates the
beginning of linked list

Creation of a linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element, prev and next field to NULL
3. Assign START point to newnode
4. Take pointer variable ptr which points to START
5. Move ptr to which points to the next field of ptr =NULL
6. Set next field of ptr points to newnode
7. Set prev field of newnode to ptr
8. Repeat the above steps for the required number of nodes in the list
/* Function for Creating a double linked list */
void create()
{
struct node *ptr,*newnode;
int ele;
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);
while(ele!=-1)
{ newnode=(struct node *)malloc(sizeof(struct node));
newnode->prev=NULL;
newnode->data=ele;
newnode->next=NULL;
if(start==NULL)
start=newnode;
else
{
ptr=start;

while(ptr->next!=NULL)
ptr=ptr->next;
ptr->next=newnode;
newnode->prev=ptr;
}
printf("Enter -1 to end the list \nEnter element");
scanf("%d",&ele);

}
}

2.Displaying the elements of doubly linked list


We can display the all the elements in a doubly linked list.

Displaying the double linked list involves the following steps


1. Take pointer ptr which points to START
2. Move ptr which points to NULL
3. Print data part of ptr.

/*Function for Displaying the element of double linked list*/


void display()
{
struct node *ptr;
ptr=start;
if(ptr==NULL)
printf("\n list is empty");
else
{
while(ptr!=NULL)
{
printf("%5d->",ptr->data);
ptr=ptr->next;
}
}
}

3. Inserting a node in Doubly Linked list:


A new node can be inserted into doubly linked list which requires resetting of pointers.
Inserting a new node into the list has 4 situations
a). Inserting a node at beginning
b). Inserting a node at end
c). Inserting a node after a given node
d). Inserting a node before a given node
The process of insertion involves search for the place of insertion .The search involves in locating
a node after which the new node is to be inserted.

a). Inserting a node at the beginning of a doubly linked list involves the following steps:

1.Allocate memory for new node


2. Assign data part of newnode to element
3. Set prev field of newnode to NULL
4. Set next field of new node to START
5. Set prev field of START to newnode
6. Change START pointer point to the new node
/*Function for Inserting a node at beginning */
void insert_beg()
{
struct node *newnode;
int ele;
printf("Enter element");
scanf("%d",&ele);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
newnode->prev=NULL;
newnode->next=start;
start->prev=newnode;
start=newnode;
}

b). Inserting a node at the end of a linked list involves the following steps:

1. Allocate memory for new node


2. Assign data part of newnode to element and next field to NULL
3. Take pointer variable ptr which points to START
4. Move ptr which points to last node
5. Set next field of ptr to address of newnode
6. Set prev field of newnode to ptr
/* Function for inserting a node at end*/
void insert_end()
{
struct node *ptr,*new_node;
int ele;
printf("Enter the element");
scanf("%d",&ele);
new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=ele;
new_node->next=NULL;
ptr=start;
while(ptr->next!=NULL)
ptr=ptr->next;
ptr->next=new_node;
newnode->prev=ptr;
}

c).Inserting a node after a given node involves following steps:

1. Allocate memory for new node


2. Assign data part of new node to element
3. Search for the given key element by using search function and assign key element address
to keyptr
4. Set prev field of new node points to keyptr
5. Set next field of new node points to next field of Keyptr
6. Set next field of keyptr of prev field to newnode
7. Set next field of keyptr node points to newnode
/*Function for Inserting a node after a given node*/
void insert_after()
{
struct node *keyptr,*newnode;
int ele,key;
printf("\nEnter nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
newnode->prev=keyptr;
newnode->next=keyptr->next;
keyptr->next->prev=newnode;
keyptr->next=newnode;
}
}

d). Inserting a node before a given node involves following steps:


1. Allocate memory for new node
2. Assign data part of newnode to element
3. Search for the given key element by using search function and assign key element address to
keyptr
4. Set prev field of newnode to prev field of keyptr
5. Set next field of newnode points to keyptr
6. Set next field of keyptr of prev field points to newnode
7. Set prev field of keyptr to newnode

/*Function for Inserting a node before a given node*/


void insert_before()
{
struct node *keyptr,*newnode;
int ele,key;
printf("\nEnter element");
scanf("%d",&ele);
printf("\nEnter the key element");
scanf("%d",&key);
newnode=(struct node *)malloc(sizeof(struct node));
newnode->data=ele;
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");

else
{
newnode->prev=keyptr->prev;
newnode->next=keyptr;
keyptr->prev->next=newnode;
keyptr->prev=newnode;
}
}
2.Deleting a node from double linked list
Deleting a node from the list is easier than insertion as only one pointer needs to be changed.
Here again we have four different situations
a). Deleting the first node
b). Deleting the last node
c). Deleting the node after the given node
d). Deleting the node before the given node
The memory space of deleted node may be released for reuse .The process of deletion also
involves search for the item to be deleted.

a). Deleting the first node involves the following steps

1. Take pointer variable ptr which points to START


2. START pointer is altered to point to the next field of START node in the list
3. Set prev field of start to NULL
4. Deallocate memory for first node from list.

/*Function for Delete first node*/


void delete_first()
{
struct node *ptr;
ptr=start;
start=start->next;
start->prev=NULL;
free(ptr);
}
b). Deleting the last node involves the following steps
1. Take pointer variables ptr which points to START
2. Move ptr such that next field of ptr = NULL
3. Set previous field of ptr of next field points to NULL
4. Deallocate memory for ptr node from list.

/*Function for Deleting last node*/


void delete_last()
{
struct node *ptr;
ptr=start;
while(ptr->next!=NULL)
ptr=ptr->next;
ptr->prev->next=NULL;
free(ptr);
}
c). Deleting the node after the given node involves the following steps

1. Search for the given key element by using search function and assign key element address
to keyptr
2. Take pointer variable Aptr which points to next field of keyptr
3. Set next field of keyptr to next field of Aptr
4. Set next field of Aptr of prev field points to keyptr
5. Deallocate memory for Aptr node from list
/*Function for deleting a node after given node*/
void delete_after()
{
struct node *keyptr,*Aptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
Aptr=keyptr->next;
keyptr->next=Aptr->next;
Aptr->next->prev=keyptr;
free(Aptr);
}
}
d). Deleting the node before the given node involves the following steps

1. Search for the given key element by using search function and assign key element address to
keyptr
2. Take pointer variable preptr which points to prev field of keyptr
3. Set prev field of keyptr to prev field of preptr
4. Set prev field of preptr of next field to keyptr
5. Deallocate memory for ptr node from list
/*Function for deleting a node before given node*/
void delete_before()
{
struct node *preptr,*keyptr;
int key;
printf("\nEnter the key element");
scanf("%d",&key);
keyptr= search(key);
if(keyptr==NULL)
printf("\nKey is not found");
else
{
preptr=keyptr->prev;
keyptr->prev=preptr->prev;
preptr->prev->next=keyptr;
free(preptr);
}
}

5. Searching a node in double linked list:-


The search function attempts to locate the requested element in the list. If the node in the list
matches with key, the search returns true if no key matches, it returns false.
The function given below searches through the linked list and returns a pointer the first
occurrence of the search key or returns NULL pointer if the search key is not in the list
Searching a node in double linked list involves the following steps

1. Take pointer variable ptr which points to START


2. Move ptr which points to NULL
3. If data part of ptr =key then return ptr otherwise return NULL

/* Function for Searching of a element in double linked list*/


struct node* search(int key)
{
struct node *ptr;
ptr=start;
while(ptr!=NULL)
{
if(ptr->data==key)
return ptr;
ptr=ptr->next;
}
return NULL;
}
Program for Double linked list
#include <stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
struct node *pre;
};
struct node *head;
void insert();
void del();
void display();
void search();
void reverse();
int c=0,b=0;
void main()
{
int a,ch;
head=NULL;
while(1)
{
scanf("%d",&ch);
switch(ch)
{
case 1:insert();
break;
case 2:del();
break;
case 3:display();
break;
case 4:search();
break;
case 5:reverse();
break;
case 6:exit(0);
default: printf("Invalid Option");
}
}
}
void insert()
{
int p,i,n;
struct node *temp=(struct node *)malloc(sizeof(struct node));
struct node *temp2,*x;
scanf("%d%d",&p,&n);
if(p<=0||p>c+1)
printf("Position does not exist - Cannot insert into DLL");
else
{
c++;
temp->data=n;
temp->next=NULL;
temp->pre=NULL;
if(head==NULL)
head=temp;
else if(p==1)
{
x=head;
x->pre=temp;
temp->next=x;
head=temp;
}
else
{
temp2=head;
for(i=0;i<p-2;i++)
temp2=temp2->next;
temp->next=temp2->next;
temp2->next=temp;
temp->pre=temp2;
if(p!=c)
{
temp2=temp->next;
temp2->pre=temp;
}
}
}
}
void del()
{
int p,i;
struct node *temp1=head,*temp2;
scanf("%d",&p);
if(p<=0||p>c)
printf("\nPosition does not exist - Cannot delete from DLL");
else
{
c--;
if(p==1)
{
head=temp1->next;
if(c!=0)
{
temp2=temp1->next;
temp2->pre=temp1->pre;
}
printf("\nDeleted element from DLL is %d",temp1->data);
free(temp1);
}
else
{
for(i=0;i<p-2;i++)
temp1=temp1->next;
temp2=temp1->next;
temp1->next=temp2->next;
if(p!=c+1)
{
temp1=temp1->next;
temp1->pre=temp2->pre;
}
printf("\nDeleted element from DLL is %d",temp2->data);
free(temp2);
}
}
}
void search()
{
int n,p=0,b=0;
struct node *x;
scanf("%d",&n);
x=head;
while(x!=NULL)
{
p++;
if(x->data==n)
{
b=1;
break;
}
x=x->next;
}
if(b==1)
printf("\n%d is found in DLL",n);
else
printf("\n%d is not found in DLL",n);
}
void display()
{
struct node *x;
int i;
x=head;
printf("\n");
while(x!=NULL)
{
printf("%d ->",x->data);
x=x->next;
}
if(head==NULL)
printf("\nEmpty DLL - Cannot display");
}
void reverse()
{
struct node *y;
int i;
y=head;
printf("\n");
for(i=0;i<c-1;i++)
y=y->next;
while(y!=NULL)
{
printf("%d->",y->data);
y=y->pre;
}
if(head==NULL)
printf("\nEmpty DLL - Cannot display");
}

You might also like