0% found this document useful (0 votes)
63 views47 pages

Unit 1 Linked List

This document introduces linked lists as a data structure to store dynamic lists of data. It discusses the limitations of using arrays to store dynamic lists, such as not being able to dynamically increase or decrease size. Linked lists address this by allocating nodes dynamically and linking them using pointers. Each node contains a data field and a pointer to the next node. This allows flexible insertion and removal while using memory efficiently. The document covers the basic concepts of linked lists and different types, such as singly and doubly linked lists, and linear vs circular lists.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views47 pages

Unit 1 Linked List

This document introduces linked lists as a data structure to store dynamic lists of data. It discusses the limitations of using arrays to store dynamic lists, such as not being able to dynamically increase or decrease size. Linked lists address this by allocating nodes dynamically and linking them using pointers. Each node contains a data field and a pointer to the next node. This allows flexible insertion and removal while using memory efficiently. The document covers the basic concepts of linked lists and different types, such as singly and doubly linked lists, and linear vs circular lists.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 47

LINKED LIST

INTRODUCTION
We use the concept of “list” very frequently in our day-to-day lives. We make a list of
tasks to be done in the day, a lady makes a list of shopping items, students make a list of
the topics to be studied and so on. However, a list once made, hardly remains the same. As
the day progresses, there are new tasks to be added, completed tasks to be removed, tasks
to be reordered and some tasks to be cancelled. Thus, there are constant modifications to
the list i.e. the list is “dynamic” in nature.

The term “list” refers to a linear collection of data items such that there is a first
element, second and . . . a last element. Data processing frequently involves storing and
processing data organized into lists.

The following shows a list containing some beautiful colors.

Violet
Blue
Green
Orange
Red

If we wanted to store this list in memory, we could use the sequential representation i.e.
store the colors in an array. Arrays use sequential mapping i.e. the data elements are stored
in memory, fixed distances apart. This makes it easy to compute the location of any element
in the array.

If the elements of the list are going to be fixed, then using an array will be a good
method of storing the elements of the list. But if we wished to insert the colors “Indigo”
and “Yellow” to complete the colors of the rainbow, it will mean that we would have to move
some colors to make place for the missing colors. The same would apply if we had to remove
certain colors from the list. Moreover, the use of arrays will impose an upper limit on the
maximum number of colors in the list.

1-1
1-2
Linked List
Thus, in general , the use of sequential representation for a list, which is dynamic in
nature , proves to be inadequate due to the following reasons.
Limitations of Sequential Representation ( Array )
1. An array is a static data structure i.e. the size of the array remains fixed.
Thus, even if the data structure actually uses less amount of storage to store
elements or possibly uses no storage at all, the unutilized memory cannot be used for
other purposes.
Moreover, if we require more space than allotted, it cannot be increased during run
time.
2. Most real-time applications process variable size data. The amount of data to be
manipulated and hence the storage requirements cannot be predicted in advance
during design time.
3. Often, we need to insert , delete , move and reorder data. For this, a lot of elements
will have to be moved , which will require a lot of processing time. If these operations
are to be carried out very frequently, the processing time will be enormous.

Since a list is basically a dynamic data structure, we have to find another method of
representing the elements of the list so that the operations can be performed in a
reasonable amount of time.

CONCEPT OF LINKED ORGANIZATION


One solution to the above problem is that instead of using sequential representation, a
“linked representation” or “linked organization” should be used, i.e. unlike an array,
where elements are stored sequentially in memory, items in a list may be located anywhere
in memory. To access elements in the correct order, we store the address or location of the
next element, with each element of the list.

Definition : Linked Organization


A Linked Organization is one in which the elements of the list are logically next to each
other, but physically, they may not be adjacent.

Definition : Linked List


A linked list is an ordered collection of data elements where the order is given by means
of links i.e. each item is connected or “linked” to another item.
Basically a linked list consists of “nodes”. Each node contains an item field and a link.
The item field may contain a data item or a link.
1-3
Linked List

LINKED LIST AS A PHYSICAL DATA STRUCTURE


In the previous section we have defined a linked list to be a linked collection of nodes,
each containing some information. In this section, we will think about how to implement
the linked list. The main issues to be considered are :
a) How to store the elements of the linked list in memory.
b) How to indicate their logical order.
c) How to perform various operations on the list like insertion, deletion etc.

The way in which we will perform operations on the list will depend upon the method
used to store the nodes of the linked list. We can use two methods to implement the
linked list :
1. Static Representation.
2. Dynamic Representation.

1. Static Representation
An array is used to store the elements of the list. The elements may not be stored in a
sequential order. The elements can be stored at any position in the array. The logical order
can be stored in another array called “Link”. The values in this array tell the logical order
of the elements in the array DATA. The corresponding “link” of a data item tells where the
next element is.
For example, let us consider our list of colors. The first color in the list is “Violet”
followed by “Blue”. These colors can be stored anywhere in the array but the position in the
Link field will tell where the next color in the sequence can be found. All we need to know is
the starting position of the list. In this case, it is 3.

Start = 3 DATA [3] = Violet


LINK[3] = 0 DATA [0] = Blue
1-4
Linked List
LINK[0] = 4 DATA [4] = Green
LINK[4] = 6 DATA [6] = Orange
LINK[6] = 1 DATA [1] = Red
LINK[1] = –1 ⇒ List ended

Advantages
1. The implementation is simple.
2. For performing operations like insert, delete etc, all we have to do is update the
links.

Disadvantages
1. We will have to use double the memory; one array to store data elements and one
array to store the links.
2. Since we are using an array –which is a static data structure, to implement the
linked list, there will be the limitation of having fixed memory.

A linked list is a dynamic data structure i.e. the size of the list grows and shrinks
depending upon the operations performed on it. This means that when we insert elements
in the list, its size should increase and when elements are deleted, its size should decrease.
This cannot be possible using an array which uses static memory allocation i.e. memory is
allocated during compile time. Hence, we have to use “dynamic memory allocation”
where memory can be allocated and de-allocated during run time.
2. Dynamic Representation
The Static representation uses arrays, which is a static data structure and has its own
limitations.
Another way of storing a list in memory is by dynamically allocating memory for each
node one by one and linking them. Since we will dynamically allocate memory using
functions like malloc and calloc, we will have to use pointers. Moreover, each node will at
random memory locations , so we have to store the address of the next node along-with the
data in the node. All we have to do is remember the address of the first node in an external
pointer .
The node structure will thus contain two fields :
a) data or info : which stores the information
b) link or next : which stores the address of the next node.
1-5
Linked List
Each node contains two parts, data and link. The data part may contain a single data
item or a composite one like an entire record or it may be a link. The link or next part
contains the address of the next node in the list. The last node contains a special value
called “NULL” which indicates end of the list.
The linked list for our set of colors can now be pictorially shown as below:

Advantages
1. Since memory is dynamically allocated during run-time, memory is efficiently
utilized.
2. There is no limitation on the number of nodes in the list; except for the available
memory.
3. Insertion, deletion and traversal can be easily done.
4. Memory can be freed when nodes have to be deleted.

TYPES OF LINKED LISTS


Types of Linked Lists
Linked lists are basically of two types.
1. Singly Linked List
Each node in this list contains only one pointer which points to the next node of the list.

2. Doubly Linked List


Each node in this list contains two pointers; one pointing to the previous node and the
other pointing to the next node. This list is used when traversing in both directions is
required

The Singly linked list and Doubly linked list can further be of two types :

1. Linear Linked List


In this list, the elements are organized in a linear fashion and the list terminates at
some point i.e. the last node contains a NULL pointer.
1-6
Linked List

Linear Singly Linked List

Linear Doubly Linked List

2. Circular List
In this list, the last node does not contain a NULL pointer at the end to signify the
end of the list, but the last node points back to the first node i.e. it contains the
address of the first node.

Circular Singly Linked List

Circular Doubly Linked List

Sometimes, an extra node is placed at the beginning of the list. Such a node is called
“Header Node”. This node does not store any data element but can be used to store some
control information like number of elements etc.

REPRESENTING LISTS IN C++


To create a linked list, we will create the nodes whenever required and attach the nodes
to the list. Whenever nodes are not required, they will be removed from the list. In order to
do this, we will be using dynamic memory allocation. For dynamic memory allocation and
de-allocation, we will be using the C++ free store operators new and delete which will
allow us to allocate and de-allocate nodes during run-time.
1-7
Linked List

1 Node structure
Each node of a linked list contains an info / data part and a link/next part which is a
pointer. The pointer stores the address of the next node.

The class definition for the above node can be written as follows. The class will have two
data members – data and the pointer pointing to the next node.

struct node
{
int data;
node * next;
};

For dynamic memory allocation, we will be using pointers and the new and delete
operators. The following example shows how to create a single node and storing the value
10 in it.

Example: To create a single node containing data 10:


node *newnode = new node;
newnode → data = 10;
newnode → next = NULL;

We can add a constructor to the node class which will initialize a node during creation.
class node
{
int data;
node * next;
public:
node(int n)
//constructor
{
data
= n;
next
= NULL;
1-8
Linked List
}
};
Here, the constructor is defined as a parameterized constructor which takes one
argument ; a data element. The pointer has been assigned a default value of NULL.

2 Creating the List class

A class in C++ is a user defined type which contains data members and related member
functions in a single unit. A class can then be used to create objects. The member functions
are the operations to be performed and form the class interface.
We can create a class for a linked list. The linked list can be considered as a class with
one data member i.e. a pointer to a node and a set of operations on the list. The user will
access the list as a whole using the pointer and perform operations using the functions
provided in the list interface.

The data members of the class list will be:


1. Pointer to a node

The operations carried out on a list of integers will be:

i) Initialize the list: This will be a constructor which is automatically called when a
list is defined.
ii) Freeing the list: This is a destructor which frees the nodes of the list. (
automatically invoked when a list is freed or the block in which the list was
created, ends.
iii) Checking whether the list is empty.
iv) Adding a node at a specific position
v) Deleting a node at a specific position
vi) Deleting a node with a specific value.
vii) Displaying all the elements of the list ( Traversing the list )

We can create the list class in two different ways.


Method 1: Using Composite classes

A list class can be created with one data member which will be a pointer to the first node
of the list. Since the pointer will point to a node,
the node class above will have to be declared as a friend class to the class list.

The class definitions can now be written as :

class List; // forward declaration


1-9
Linked List
class node
{
int data;
node * next;
public:
node(int n) //constructor
{
data = n;
next = NULL;
}
friend class List; // Methods of List can access node
};

class List
{
Node * Listptr; // data member
public :
List() ; //constructor
void create();
void display();
void reverse();
int length();
void insert(int num, int pos);
void deleteval(int val);
void deletepos(int pos);
};

Method 2 : Using Nested classes

Instead of creating two separate classes, we can create nested classes i.e. one class
defined within another class. Here, we will have to define the class Node within the
class List. When defined in this way, the class Node will not be accessible outside i.e. it
cannot be used independently. . It can only be used as a part of the class List.

class List
{
struct node
{
int data;
node * next;
public:
node(int n) //constructor
{
data=n;
next=NULL;
1 - 10
Linked List
}
}* Listptr; // data member

public :

// List Manipulation operations

};

Creating a Reusable List Class

In the above section, we have created a List class for a list which stores integers.
However, we may need to store data of different types in the nodes. In order to do this, we
will have to define new classes for nodes storing data of different types. Clearly, this is very
inefficient.
In order to have a generic class for a list which can be used for any data types, we can
make use of templates which is a very powerful feature of C++. The use of templates allows
us to make “container” classes and clearly, a linked list is a container class.

This can be done as follows.


template <class T> class List; // forward declaration

template <class T>


class node
{
T data;
node * next;
public:
node(T n)
{
data = n;
next = NULL;
}
friend class List<T>;
};

template <class T>


class List
{
node<T> * Listptr; // data member
public :
// List Manipulation operations

};
1 - 11
Linked List

Defining Member Functions outside the class


When the member functions are defined outside the class, the syntax will be as follows :
template <class T>
void class-name<T> :: method-name()
{
//function code
}

example:

template <class T>


void list<T> :: Create()
{
//function code
}

OPERATIONS ON A SINGLY LINKED LIST


The various operations that can be performed on a singly linked list are given below.
1. Creating the list: This operation creates a singly linked list.
2. Traversing the list: Visiting each node of the list is called traversal.
3. Computation of Length: Count the total number of nodes in the list.
4. Insertion: A node can be inserted at the beginning, end or in between two nodes
of the list.
5. Deletion: Deletion from a list may be done either position-wise or element-wise.
6. Searching: This process searches for a specific element in the list.
7. Reversing or Inversion: This process reverses the order of nodes in the list.
8. Concatenation : This process appends the nodes of the second list at the end of
the first list i.e. it joins two lists.

The class definition for a singly linked list with the above operations (only declarations)
is given below. We shall see how to perform these operations in the following sections.
For simplicity, we will not be using templates. We will create a singly linked list of
integer data.
The entire program using templates is given in Appendix A.

class list; // forward declaration

class node
1 - 12
Linked List
{
int data;
node * next;
public:
node(int &n) // constructor
{
data = n;
next = NULL;
}
friend class list;
};

class list
{
node* Listptr; // data member
public :

list() //constructor
{
Listptr = NULL;
}
~list(); // destructor
int Length() const;
void Create();
void Insert(int n, int pos); // insert node
void DeletePos (int pos); //
deletes node at position p
void DeleteVal ( int val); //
deletes node with ‘n’ void
Display() const; // displays the list
int isEmpty() const ; //checks if list is
empty
void Invert(); //Reverses a list
void Concatenate(list &l); //Concatenates two lists
};

1 Creation of a Singly Linked List


To create a linked list, we will create the nodes one by one and add them at the end of
the list. The list will be pointed to by an external pointer, which stores the address of the
first node of the list. In the example below, we are creating three nodes with values 10, 20
and 30 and making the linked list. The list is pointed to by a pointer called “slist” , which is
initially NULL.

1
slist = NULL
.
1 - 13
Linked List

2
.

4
.

The algorithm to create a linked list containing ‘n’ nodes can be written as follows:

Algorithm
1. Start
2. Accept number of nodes to be created in n.
4. Counter = 1
5. Accept num i.e. the data to be stored in the list
6. Create a new node using new and store num in it
6. If Listptr is NULL then ( i.e. the list is empty )
Store the address of the new node in Listptr and temp i.e. Listptr = temp=
newnode
else
Attach newnode to temp i.e. temp->next=newnode
Move temp to the last node
7. Increment Counter
8. If Counter < = n
goto 5
9. Stop

Function : Create a List


void list:: Create()
{
int i, n;
node * temp;
cout<<”How many nodes :”;
cin>>n;
for(int i=0; i<n; i++)
{
cout<<”Enter the data”<<endl;
cin>>num;
1 - 14
Linked List
node *newnode = new node(num);
if(Listptr == NULL)
Listptr = temp = newnode;
else
{
temp -> next = newnode;
temp = temp->next;
}
}
}

2 Checking if a List is empty


For many operations, we have to check if the list is empty or not. For this, we can write
a member function which will return TRUE if the list is empty and FALSE otherwise. If the
pointer Listptr contains NULL, it means that the list has no nodes i.e. it is empty. Hence,
we can check if a list is empty by examining the contents of the pointer Listptr.
int list:: isEmpty()
{
return (Listptr == NULL);
}

3 Traversing a List
In order to display the elements of a list we will have to move from the first node to the
last using the links till we reach NULL. This is called displaying the list. The address of
the starting node has to be known.

Algorithm
1. Start
2. Listptr is the pointer to the first node of the list.
3. if Listptr == NULL
Display “List is Empty”
Go to step 8.
4. temp is a temporary pointer for traversal.
5. Make temp point to the first node i.e. temp=Listptr.
6. If temp ≠ NULL
Display the data of temp i.e. display temp->data
Move temp to the next node i.e. temp=temp->next.
7. Repeat from 6 as long as temp ≠ NULL.
8. Stop
1 - 15
Linked List
Function : Display a List
void list:: Display()
{
node * temp = Listptr ; /* temp points to first node*/
if ( isEmpty() )
{
cout<<“List is empty”;
return;
}
while (temp != NULL)
{
cout << temp → data << “->”;
temp = temp → next; /* move temp to the next node
*/
}
cout<< ”NULL”;
}

Recursive Display method

The list traversal can also be done recursively. For this purpose, we will have to pass the
list pointer to the function recursively. Hence, we will have to define another private
member function which takes one parameter – a pointer to node. This is the working
function. The recursive calls will be given to the function as long as the pointer does not
become NULL.

Function : Recursive Display


void list:: Display() //public member function - driver
{
Display(ListPtr); //private member function - workhorse
}

void list::Display(node *temp)


{
if ( temp==NULL )
{
cout<<“NULL”;
return;
}
cout << temp → data << “->”;
Display(temp → next); // Recursive call

}
1 - 16
Linked List

4 Finding Length of a List


To find the length of a list, we have to traverse the list and count the number of nodes in
the list. This can be easily done using a temporary pointer which starts from the first node
and moves to the next nodes until it becomes NULL.

Algorithm
1. Start
2. Listptr is the pointer to the first node of the list.
3. if Listptr = = NULL
Display “ Empty List”
Go to 10
4. temp is a temporary pointer for traversal.
5. Initialize count to 0.
6. Make temp point to the first node i.e. temp=Listptr.
7. If temp ≠ NULL
Increment count.
Move temp to the next node i.e. temp=temp->next.
8. Repeat step 7 as long as temp ≠ NULL.
9. Return count.
10. Stop.

int list:: Length() const


{
node * temp = Listptr ; /* temp points to first node*/
int count =0;
while (temp)
{
temp = temp → next; /* move temp to the next
node */
count++;
}
return count;
}

This function can also be written recursively. We will have to write a private member
function (working function) which is called by the public function (driver function) of the
class.

int list:: Length() const


{
Length(ListPtr);
1 - 17
Linked List
}

int list:: Length(node *temp)


{
static int count=0;
if(temp==NULL)
return count;
count++;
Length(temp->next);
}

5 Inserting an element in the list


In many situations we may have to insert an element in the list. For this, we must
know the position where it has to be inserted. There are three possibilities that we can
consider:
a. Insert at the beginning
To insert a new node at the beginning of the list, the pointer pointing to the first node
will have to be changed such that it now points to the new node. The steps performed are
illustrated in the diagram below. The function returns the new address of the first node.

Function : Insert at Beginning


void List:: InsertBeg(int num)
{
node *newnode = new node(num);
if(isEmpty())
Listptr=newnode;
else
{
newnode->next=Listptr;
Listptr=newnode;
}
}
1 - 18
Linked List
b. Insert at the end
To insert a new node at the end of the list, we will have to move a temporary pointer to
the last node and then attach the new node after the last node.

Function : Insert at End

void List:: InsertEnd(int num)


{
node *newnode = new node(num);
if( isEmpty() )
Listptr=newnode;
else
{
// MOVE temp to the last node
for (node *temp=Listptr; temp→next!= NULL; temp = temp → next);

// Link newnode to temp


temp → next = newnode;
}
}

c. Insert in a intermediate position


To insert a node in between, we have to know the position of insertion and move temp to the
node before this position. The new node has to be linked between temp and the node after
temp.

Function : Insert at intermediate position


void List:: InsertMiddle(int num, int pos)
1 - 19
Linked List
{
node *newnode = new node(num);
node *temp = Listptr;

if( isEmpty())
Listptr=newnode;
else
{
// Move temp to node at pos –1
for (int i=1; i < pos–1 && temp→ next ! = NULL; i++)
temp = temp → next;
if(i<pos-1)
{
cout<<”Position is out of range”;
delete newnode;
return;
}
// Insert newnode between temp and the node after temp
newnode → next = temp → next;
temp → next = newnode;
}
}

All the above three functions can be combined into a single function as below.
Function : Insertion
void list:: Insert(int num, int pos)
{
node *newnode = new node(num);
node *temp=Listptr;
int i;
if( isEmpty() || pos == 1)
{
newnode->next=Listptr;
Listptr= newnode;
}
else
{
// Move temp to node at pos –1
for (i=1; i < pos–1 && temp→ next ! = NULL; i++)
temp = temp → next;

if(i<pos-1)
{
cout<< “Position out of range”;
delete newnode;
1 - 20
Linked List
return;
}
// Insert newnode between temp and its next node
newnode → next = temp → next;
temp → next = newnode;
}
}

6 Deleting an element from the list (Specific Position)


For deleting an element, we have to locate the node at the specified position and free the
node after linking the nodes before and after the node to be deleted.
As in the case for insertion, deletion of an element can be done at three positions.
a. Deletion from the beginning
After deleting the first node from the list, the next node will become the first node and
hence, we will have to change the pointer to the list.

b. Deleting the last element


To delete the last node, we have to move a temporary pointer to the second last node and
then free the last node. The second last node should now contain a NULL link.

c. Deleting an element in between


To delete a node in between, we have to move a temporary pointer to the node at position-1
so that the node at the specific position can be deleted by making appropriate links.
1 - 21
Linked List

Function : Delete at a specific position


void list:: DeletePos(int pos)
{
node *temp = Listptr, *temp1;
if(pos == 1)
{
Listptr = Listptr ->next;
delete temp;
}
else
{
// Move temp to node at pos –1
for (int i=1; i < pos–1 && temp→ next ! = NULL; i++)
temp = temp → next;
if(i<pos-1)
{
cout<<”Position out of range”;
return;
}
// Delete node next to temp
temp1=temp->next;
temp->next=temp1->next;
delete temp1;
}
}

7 Deleting an element from the list (Specific Value)


The above function deletes the element at a given position. We can also delete a specific
number from the list. This can be done by “searching” the number in the list and then
deleting that node which contains the number.
To search for the number in the list and then delete it, we will use a temporary pointer
which will be positioned one node before the node which contains the required number so
that it can be deleted.

void list:: DeleteVal(int val)


1 - 22
Linked List
{
node *temp = Listptr, *temp1;
if(temp->data == val) // val found in first node
{
Listptr = Listptr ->next;
delete temp;
}
else
while(temp) // search for the node
{
if(temp->next->data == val)
{
// Delete node next to temp
temp1=temp->next;
temp->next=temp1->next;
delete temp1;
return;
}
temp=temp->next;
}
cout<<”Number not found in the list”;
}

8 Searching an element in the list


To search an element in the list, we will have to traverse the entire list and compare the
data in each node. If found, we will return the position of the element in the list and
-1otherwise.

Algorithm
1. Start
2. listptr is the pointer to the first node of the list.
3. temp is a temporary pointer for traversal.
4. Accept d i.e. the data to be searched in the list.
5. Make temp point to the first node i.e. temp=listptr.
6. pos = 1
7. If temp->data == d then
Display “Element found in the list at position pos”
Go to step 11
8. Move temp to the next node i.e. temp=temp->next.
9. pos = pos + 1
10. If temp ≠ NULL
Go to step 7
1 - 23
Linked List
11. Return pos.
12. Stop

Function : Search a specific data in the list


int list:: Search(int val)
{
node *temp=Listptr;
for (int i=1; temp!=NULL && temp->data!= val; i++);
temp=temp->next;
if(temp==NULL)
return –1;
return i;
}
We shall now write a menu-driven program to implement the above operations on the
linked list.

9 Inversion / Reversing a Singly Linked List


Reversing a linked list reverses all the links of the list such that the first node goes to
the end and the last becomes the first.

Example

After reversing

To reverse a list, we need to use three pointers. We will cal them “back”, “curr” and
“forward”. Since three pointers are used, the algorithm is called, ‘‘The Three Pointer
Method’. The algorithm is as follows:
Algorithm
1. Start
2. forward points to the first node i.e. forward = Listptr.
3. curr = NULL
4. back = curr
5. curr = forward
6. Move forward to the next node i.e forward = forward -> next
7. Link back to curr i.e. curr → next = back
8. If forward is not NULL
go to 4
1 - 24
Linked List
9. list = curr ; i.e curr is the address of the first node of the reversed list.
10. Return list.
11. Stop

Function : Reverse a Linked List


void List:: Invert()
{
node * forward, *curr, *back;
forward = Listptr;
curr =NULL;
while ( forward != NULL )
{
back = curr;
curr = forward;
forward = forward → next;
curr → next = back;
}
list = curr;
return (*this);
}

10 Concatenation of two Singly Linked Lists


Concatenation of two lists means “joining” the two lists such that the second list is
appended to the first list. As a result, the first list contains all elements of the first followed
by elements of the second.
Example :
List 1 -> 10 20 30
40
List 2 -> 4 7 8
25
Resulting List1 -> 10 20 30 40
4 7 8 25

Algorithm
1. Start
2. list1 and list2 are the pointers to the two lists respectively.
3. temp = list2. (temp is a temporary pointer used for traversal.)
4. while ( temp != NULL)
{
Create a new node p
p->data = temp->data
1 - 25
Linked List
Append p to list1
Move temp to next node of list2
}
6. Stop.

Function : Concatenate two Lists


void list:: Concatenate(list &l)
{
// this = (a1,a2,…,an) and l = (b1,b2,…,bm) where m,n>=0
// creates list (a1,a2,…,an,b1,b2,…,bm) in this

node *t1=Listptr, *t2=l.Listptr, *newnode;


//Move t1 to the end of list1

while(t1->next !=NULL)
t1=t1->next;

while(t2!=NULL)
{
newnode=new node(t2->data); //Create a new node
if(t1==NULL)
Listptr=t1=newnode;
else
{
t1->next=newnode;
t1=t1->next;
}
t2=t2->next;
}
}

APPLICATIONS OF SINGLY LINKED LIST


A Linked List can be used as the data structure for a variety of applications because of
its dynamic nature. An application can make use of a singly linked list if it requires
variable sized data to be stored in a linear manner. In this chapter, we will study some
important applications of a linked list.

1 Representation and Manipulation of Polynomials


In the previous semester, you must have studied polynomial representation using an
array. However, since an array is a static data structure, this method of representation is
not very efficient. Instead, we can represent polynomials in one variable using a Singly
Linked List.
1 - 26
Linked List
To represent a polynomial in one variable using a Singly Linked List, each node of the
list will represent one term of the polynomial. The terms can be stored in descending order
or powers . For example, if we wanted to represent the polynomial
A(x) = anxn + ….. + amxm
Where ai are the non-zero coefficients of terms having exponents from ‘n’ to ‘m’ such that
n > m ≥ 0 , then each node of the list will be a term of the polynomial containing three
parts, the coefficient, the exponent and a pointer to the next node.

Example 5x3 + 6x + 10

Each node contains


∙ Coefficient
● Exponent
∙ Pointer to the next term

The structure of each node of the linked list will be as follows :

class PolyNode
{
float coef;
int exp;
PolyNode * next;
public:
PolyNode(double c, int e) // constructor
{
coef = c;
exp = e;
next=NULL;
}
};

The various operations that can be carried out on polynomials are Addition, Subtraction,
Multiplication and Evaluation of a polynomial.

1. Addition of Two Polynomials


Two terms of a polynomial can be added if their powers are the same.
1 - 27
Linked List

Example: The addition of 6x4 + 2x3+ 4x and 7x3 + 3x2+ 9 will result in
6x + 9x3+ 3x2+ 4 x + 9.
4

For adding two polynomials, the algorithm can be written as :

Algorithm
1. Accept Polynomial a ( Store it in a list pointed to by a )
2. Accept Polynomial b. ( Store it in a list pointed to by b )
3. t1, t2 and t3 are temporary pointers used for traversal.
4. Set t1=a , t2 = b and t3 = c. ( c is the resultant polynomial )
5. while t1 ≠ NULL and t2 ≠ NULL
create node t
if (t1->exp == t2 -> exp)
{
Add coefficients of t1 and t2 and store in t.
Store exponent of t1 in t.
Shift t1 and t2 to next node
}
else
if (t1->exp > t2 -> exp)
{
Store coefficients of t1 in t.
Store exponent of t1 in t.
Shift t1 to next node
}
else
{
Store coefficients of t2 in t.
Store exponent of t2 in t.
Shift t2 to next node
}
Attach node t to resultant polynomial.
Shift t3 to next node.
6. while t1 ≠ NULL
Copy remaining nodes from a to c
7. while t2 ≠ NULL
Copy remaining nodes from b to c
1 - 28
Linked List
8. Display polynomial c.
9. Stop.

The class for the above algorithm is as given below.


class list; // forward declaration

class PolyNode
{
float coef;
int exp;
PolyNode * next;
public:
PolyNode(double c, int e) // constructor
{
coef = c;
exp = e;
next=NULL; }
friend class list;
};

class list
{
PolyNode * Listptr; // data member
public :

list() { Listptr = NULL;} // constructor


~List(); // destructor
void CreatePoly();
void AddPoly(const list &l1, const list &l2);
void DisplayPoly() const; // displays
the polynomial
};

Evaluation of a polynomial
One of the operation which can be carried out on a polynomial is its evaluation. For
evaluation of a polynomial, we have to know the value of the variable.
For example, for the polynomial, 3x2 + 2x+ 7 , if the value of x is 2, the result is 23.
Since the polynomial is represented using a linked list, we will have to visit each node of
the list anf find the value of the term. This value can be then added to a variable sum.

double List :: EvaluatePoly( double x)


{
PolyNode *temp=ListPtr;
double sum=0.0;
1 - 29
Linked List
while(temp!=NULL)
sum = sum + temp->coef * pow(x, temp->exp);

return sum;
}

3 Linked Stack
A Stack is an ordered collection of data items organized in the LIFO manner. It has one
open end called “top” and the operations PUSH and POP are done from this end.
We have seen how a stack can be represented using sequential representation i.e. using
an array. However, in that method, there is a limitation on the size of the array. Moreover,
if less elements are stored, memory will be wasted.
Essentially a stack is a dynamic data structure i.e. its size grows and shrinks according
to the operations performed (PUSH and POP). Hence the implementation of stack using an
array is highly inefficient.
To overcome the above problems, the stack can be implemented using linked lists.
In the linked organization,
i. The stack can grow to any size,
ii. We need not have prior knowledge of the number of elements,
iii. When an element has to be Pushed, memory can allocated and the Stack size grows.
iv. When an element is popped, the memory can be freed. Thus the stack size shrinks

Each node of the linked list will store one element of the stack. However, in a linked list,
insertion and deletion can be done anywhere in the list. But for a stack, we have to impose
a restriction that elements should be added (Pushed) and deleted (Popped) from the same
end. This can be done from the front of the list. Hence we will call the pointer to the first
node of the list as “top”.
The node structure for the stack will be the same as that of a singly linked list.

class node
{
int data:
node *next ;
public:
node(int n) //constructor
{
data = n;
next=NULL;
}
};
1 - 30
Linked List
The stack will be a linked list which contains one pointer called “top” pointing to the first
node of the list. Thus, the class Stack will be as follows:

class stack
{
node *top ;
public:
stack(); //constructor
void push(int n);
int pop();
int isEmpty();
};

The various steps in the creation of a stack are as shown:


i. Initially, stack is empty
top = NULL

ii. Push 10

iii. Push 20

iv. Pop

Thus, every element pushed will be added to the beginning of the list and this node will
be the new “top”. When an element has to be popped, the first node of the list has to be
freed and its next node becomes the new “top”.
Stackempty: If there is no list i.e. top contains NULL, it indicates that the stack is
empty.
1 - 31
Linked List
Stackfull : Since we are using dynamic memory allocation, we can allocate memory
whenever we have to Push an element. Hence, there is no limitation on the stack size.
Thus, this condition does not have to be checked.

The stack functions can be written as follows:

1. Initializing the stack : Constructor


stack :: stack()
{
top=NULL ;
};

2. Push
void stack :: push(int n)
{
node *newnode=new node(n);
newnode->next=top;
top=newnode;
};

3. Checking for Stack Empty


int stack :: isEmpty()
{
return (top==NULL) ;
};

4. Pop
int stack :: pop()
{
int n=top->data;
node *temp=top;
top=top->next;
delete temp;
return n;
};
1 - 32
Linked List

4 Linked Queue
A Queue is an ordered collection of data items organized in the FIFO manner. It has
two ends called front and rear. Elements are added from the rear and elements are removed
from the front.
You have already studied the implementation of a queue using arrays. However, since
the number of elements in the queue can go on varying according to the operations
performed on the queue, using arrays is not very efficient.
A queue can be considered as a list in which all insertions are made at one end called the
rear and all deletions from the other end called front. A queue can be easily represented
using a singly linked list. “front” and “rear” will be two pointers pointing to the first and
last node respectively. The node structure will be the same as used for implementing the
stack.

The various operations to be carried out on a queue are :


1. Add : A newnode will be added at the rear of the list. Rear will now point to this new
node
2. Delete : The first node of the list will be have to be deleted and its next node will
become the front of the queue.
3. Queue-Empty : If the list is empty, it will indicate that the queue is empty.

The various operations are illustrated below.


i. front = rear = NULL

ii. Add 10

iii. Add 20

iv. Add 30
1 - 33
Linked List
v. Delete

Just like the stack, the node structure for the queue will be :
class queue; // forward declaration

class node
{
int data:
node *next ;
public:
node(int n) //constructor
{
data = n;
next=NULL;
}
friend class queue;
};
The class queue can now be defined as follows:

class queue
{
node *front, *rear ;
public:
queue(); //constructor
void add(int n);
int delete();
int isEmpty();
};

The functions for the queue can be written as follows:


1. Initializing the queue : Constructor

queue :: queue()
{
1 - 34
Linked List
front=rear=NULL ;
}

2. Checking if the queue is empty

int queue :: isEmpty()


{
return (front==NULL) ;
}

3. Adding an element to the queue

void queue :: add(int n)


{
node *newnode=new node(n);
if(isEmpty())
front=rear=newnode;
else
{
rear->next=newnode;
rear=newnode;
}
};

4. Deleting an element from the queue

int queue :: delete()


{
int n=front->data;
node *temp=front;
front=front->next;
delete temp;
if(front==NULL)
rear=NULL;
return n;
}

CIRCULAR LIST
A circular linked list is a linked list in which the last node points to the first node of the
list.
1 - 35
Linked List

In a circular list, there is no logical “first” element and no “last”. Any node can be
considered as the first node of the list. This makes traversal easier since we can reach any
node starting from any other.
Operations on Circular Linked List
The operations carried out on a circular list are similar to those carried out on a singly
linked list , namely Creation, Insertion, Deletion, Traversal. After performing any operation
on a circular list, we must ensure that the last node points to the first node.
The main application of a Circular list is in implementing a circular queue. The program
for this implementation is given in the Solved Programs Section at the end of this book. We
shall study operations like creation , insertion , deletion and traversal of a circular list in
this section.
The class definition will be the same as that for a Singly linked list.

Creation of a Circular Linked List


To create a circular list, we will create the nodes one by one and add them at the end of
the list. The last node will not contain a NULL pointer but will contain the address of the
first node of the list. The list will be pointed to by an external pointer, which stores the
address of the first node of the list.

In the example below, we are creating three nodes with values 10, 20 and 30 and making
the linked list. The list is pointed to by a pointer called “ListPtr” , which is initially NULL.

1
slist = NULL
.

2
.
1 - 36
Linked List

4
.

The function for creation can be written as follows.

void list:: Create_Circular()


{
int i, n;
node * temp;
cout<<”How many nodes :”;
cin>>n;
for(int i=0; i<n; i++)
{
cout<<”Enter the data”<<endl;
cin>>num;
node *newnode = new node(num);
if(Listptr == NULL)
{
Listptr = temp = newnode;
newnode->next=ListPtr; //last node points to
first
else
{
temp -> next = newnode;
newnode->next=ListPtr;
temp = temp->next;
}
}
}

Inserting into a Circular Linked List


In order to insert an element into a circular list, we can follow the same procedure used
for the linear list. However, the care that we have to take is that the last node should point
to the first node of the list.
Function : Insertion
void list:: Insert(int num, int pos)
1 - 37
Linked List
{
node *newnode = new node(num);
node *temp=Listptr;
int i;
if(pos == 1)
{
while(temp->next!=ListPtr) //move temp to last node
temp=temp->next;
newnode->next=Listptr;
Listptr= newnode;
temp->next=newnode; //link last to first
}
else
{
// Move temp to node at pos –1
for (i=1; i < pos–1 && temp→ next ! = ListPtr; i++)
temp = temp → next;

// Insert newnode between temp and its next node


newnode → next = temp → next;
temp → next = newnode;
}

Deleting from a Circular Linked List


In order to delete an element at a specific position, if the position is equal to 1, then the
first node has to be deleted and the last node should point to the new first node of the list.
For all other positions, we have to move temp to the node at position-1 and then delete the
next node.

Function : Delete at a specific position


void list:: DeletePos(int pos)
{
node *temp = Listptr, *temp1;
if(pos == 1)
{
while(temp1->next!=ListPtr) //move temp1 to last node
temp1=temp1->next;

Listptr = Listptr ->next;


delete temp;
temp1->next=ListPtr;
}
else
1 - 38
Linked List
{
// Move temp to node at pos –1
for (int i=1; i < pos–1 && temp→ next ! = ListPtr; i++)
temp = temp → next;
if(i<pos-1)
{
cout<<”Position out of range”;
return;
}
// Delete node next to temp
temp1=temp->next;
temp->next=temp1->next;
delete temp1;
}
}
}

Traversal of a Circular Linked List


The traversal will be done in the same way as a singly linked linear list. The only
difference is that the last node does not contain NULL. Hence, the termination condition
will be different.

Function : Display
void list:: Display()
{
node *temp = Listptr;
do
{
cout<< temp->data <<”->”;
temp1=temp1->next;
} while(temp!=Listptr;
cout<<”END”;
}

DOUBLY LINKED LIST


In a singly linked list, each node contains one pointer, which points to the next node.
Thus, traversal is possible only in one direction.

A doubly linked list is a linked list in which each node contains two links – one pointing
to the previous node and one pointing to the next node.
1 - 39
Linked List

The class for the node will be


class node
{
int data;
node *prev, *next;
public:
node(int n)
{
data=n;
prev = next = NULL;
}
};
Example

The class for the doubly linked list will contain only one data member. This data member
will be a pointer to the first node in the list.
class list
{
node *first;
public:
list();
create();
display();
// other member functions
};

Advantages
1. Traversal in both directions is possible.
2. Operations like insertion, deletion can be performed more efficiently.

Disadvantage
1. Extra storage is needed for the pointers.

1. Creating a doubly linked list


This is the same as creating a singly linked list except that we have to link the nodes
using both links, prev and next.
Function
1 - 40
Linked List
Function : Create a doubly linked List
void list:: Create()
{
int i, n;
node * temp;
cout<<”How many nodes :”;
cin>>n;
for(int i=0; i<n; i++)
{
cout<<”Enter the data”<<endl;
cin>>num;
node *newnode = new node(num);
if(first == NULL)
first = temp = newnode;
else
{
temp -> next = newnode;
newnode->prev=temp;
temp = temp->next;
}
}
}

2. Inserting node at the beginning

newnode →next = dlist;


dlist →prev = newnode;
dlist = newnode
3. Inserting a node at the end

temp → next = newnode;


newnode → prev = temp;
1 - 41
Linked List

4. Inserting a node in between

newnode → next = temp → next;


temp → next → prev = newnode;
temp → next = newnode;
newnode → prev = temp;
5. Deleting the first node

temp → prev → next = temp → next;


temp → next → prev = temp → prev;
free(temp);

Deleting an intermediate node can be done in the same way as for a singly linked list.

GENERALIZED LINKED LIST


A generalized linked list is a special type of linked list, which not only contains
individual data items but also pointers to other lists.
A linear list is defined to be a finite set of zero or more elements a1, a2,. . . ,an and
denoted as L = (a1,a2,….an). Each of these elements are called atoms and do not have any
structure of their own.
Definition
A generalized list G is a finite sequence of n> 0 elements a1….an where ai are either
atoms or lists. These lists are called the sublists of G. It is denoted as G = (a1,a2,. . . ,an)
Example G = (a,(b,c), d)
G is a generalized list of length three. Two of them are atoms (a and d) and one is a list
with two elements ( b is the head and c the tail of the sub list)

Examples
1 - 42
Linked List
1 L=() Empty or null list
.
2 L = (A, A( )) A list of length three – the first two are lists A and third in a null list.
.
3 L = (a,L) A recursive list of length two. L is infinite i.e. L = (a,(a,(a,. . . ). . .
.

Application of Generalized linked list


So far we have restricted ourselves to polynomials in a single variable. However,
polynomials in multiple variables also need to be represented and manipulated. These can
be represented as follows.
i. An array of structures
Each element contains the coefficient and the exponent of all the variables. For a
three variable polynomial, we can define the structure as:
struct poly
{
float coef;
int expx , expy, expz;
};

However, all the terms in the polynomial may not contain all the variables. Thus,
many exponents will be 0.
ii. Consider the polynomial as a polynomial in one variable whose coefficients are
polynomials in another variable. Thus, we can use a generalized linked list.
For example consider the polynomial,
P(x,y,z) = x10 y3 z2 + 2x8 y3 z2 + 3x8 y2 z2 + x4 y 4 z + 6 x3 y4 z + 2 yz.

This polynomial can be represented as a polynomial in one variable z by collecting


common terms.
i.e P = Az2 +Bz
where
A = x10 y3 + 2x8y3 + 3x8y2
B = x4y4 + 6x3y4 + 2y
A can be further represented as a polynomial in variable y
i.e. A = Cy3 + Dy2
where C = X + 2X8
10

D = 3x8
and B can be represented as
B = Ey4 + 2y
4 3
where E = x + 6x .
Thus each sub-list is polynomial in one variable. The representation of P is as follows.
1 - 43
Linked List

The node structure for any generalized linked list will be

Tag = False/True Data/link lin


k

If the TAG field is True, the next field will contain a pointer to a sub-list, otherwise it
will contain data. The link field points to the next node in the list. Using the above
structure, we can represent any generalized list G. Let us consider some examples :
1. A = ( a , ( b, c ) , d )
2. B = ( a , B )
3. C = ( B , B , c )

Exercises
1. Programming Exercises
1. Find the length of a linked list and also calculate sum of its elements.
2. Search for an element in a list. The function should return the address of the node if
found and NULL otherwise.
3. Merge two lists of numbers in the sorted order into a third list such that the third list
is also sorted.
4. Find the union and intersection of two lists of numbers.
5. Write a function to insert element n into a doubly linked list immediately before
element m. If m is not found in the list, the element n. should be appended to the list.
6. Write an algorithm to multiply two polynomials represented as linked lists.
7. Write a menu driven program to insert, delete and display elements from a doubly
linked list.
1 - 44
Linked List
8. Display the elements of a singly linked list in the reverse order. (Use a stack)
9. Reverse a Queue using a stack.
10. Represent long integers using linked lists. Write a program to perform addition of two
long integers.
11. Write a program to reverse a linked list.
12. Sort the numbers stored in a linked list in the descending order.
13. Write a recursive algorithm for erasing a linked list
14. Write a function to delete the ith node from a doubly linked list .
15. Count the number of nodes in a circular doubly linked list .
16. Write function for ADDQ and DELQ on a queue using dynamic memory allocation
method.
17. Write a menu driven program in C to implement Queue using a singly linked list
1. Add
2. Delete
3. Exit
18. Write a function to add a node at the beginning of a singly linked list.

2. Review Questions
1. Compare sequential representation with linked representation.
2. What are the drawbacks of sequential storage?
3. Define a linked list. Explain the node structure.
4. What are the four types of linked lists? Illustrate with diagrams.
5. What are the different operations that can be performed on linked lists ?
6. What are the differences between a singly linked list and doubly linked list?
7. How can a stack be represented using a linked list?
8. How can a queue be represented using a linked list?
9. What are the differences between an array and a linked list?
10. What the Generalized linked lists?
11. What are the advantages of using a circular list for a queue?
12. Represent the polynomial as a Generalized linked list.
M(p,q,r) = 25p3q2r4 + 8p2q2r4 +9p3qr +2p2qr + 14pqr
13. Represent (A, B(C,D,E),G,(H,(I,J,(K,L))),M)
Generalized linked list) diagrammatically

Frequently Asked Questions ( Univ )


1 - 45
Linked List
1. What is a generalized linked list? Write a node structure in C for a generalized
linked list. Give the diagrammatic representation for the following polynomial using
generalized linked list:
((x7+x5)y3 + 3x5y2 ) z2 + ((x3+6x2)y4 + 2y ) z ( Dec
03 Dec 00, 10 marks )
GP(a,b,c) = a10b3c2+2a8b3c2 + 3a8b2c2+ a4b4c + 6a3b4c + 2bc ( Dec 01 , 8
marks )
L(M,(N,(O,P)) , (Q,(R,(S,T)),A,(B,C))) (
May 00 May 97 , 4 marks )
−x3 y2 z4 + 8x3 y z2 − x y z + y3 z
( May 99 , 4 marks )
x3 (y2 (3z4 − 7z3 + z) − y (z2 + z)) − xyz
( Dec 98 , 8 marks )
8x3 y3 z2 + 3x3 y2 z3 +y2 z2 + x y2 z2 + 8x + 9y
( Dec 97 , 8 marks )
2. Write a pseudo C function to add an element at any position and delete from any
position in a doubly linked list.
(Dec 03 , 6 marks )
3. Write a pseudo C function to traverse a singly linked list without using any
additional data structure.
( Dec 03 , 6 marks )
4. Differentiate between static and dynamic implementation of a singly linked list.

( May
02 , 4 marks )
5. Explain how a circular list can be erased in a fixed amount of time.

( May 02 , 4 marks )
6. Write a pseudo C algorithm that traverses a singly linked list and deletes all nodes
whose keys are negative. Specify the time complexity of your algorithm.
( May 02 , 6 marks
)
7. Explain ADT of linked list
( Dec 01 , 5 marks )
8. Differentiate between singly and doubly linked list. Write a function to insert a node
before and after any node in a singly linked list.
( Dec 01 , 10 marks )
9. Write a recursive pseudo C algorithm for merging the contents of two singly linked
lists.
( May 01 , 6
marks )
1 - 46
Linked List
Write a pseudo C algorithm to reverse a singly linked list a) Without using a new list b)
Using a new list.
( May 99 Dec 98, 8 marks )


1 - 47
Linked List

1.1 Introduction 1
1.2 CONCEPT OF Linked ORGANIZATION 2
1.3 Linked List as a Physical Data Structure 2
1.4 TYPES OF Linked ListS 5
1.5 representing lists in c++ 6
1.6 Operations on a SINGLY Linked List 11
1.6 APPLICATIONS OF SINGLY LINKED LIST 24
1.7 Circular List 44
1.8 Doubly Linked List 46
1.9 APPLICATION of DOUBLY Linked List 49
4.9 Generalized – Linked list 57

You might also like