VIDHYA SAGAR WOMENS COLLEGE, CHENGALPATTU
DEPT OF COMPUTER SCIENCE
ONLINE CASS
DATA STRUCTUREUSING
C++
Staff Incharge: D.Preethi M.Sc.,M.Phil.,NET
Asst.Professor
Dept of Computer Science
UNIT-3
Objectives
To Understand the concept of
Linked List in Data Structures
Singly Linked List - Operations, Application
Representation of a Polynomial,
Polynomial Addition;
Doubly Linked List – Operations
LINKED LIST
A linked list is a linear data structure,
A linked list does not store its elements in
consecutive memory locations and the user
can add any number of elements to it.
The elements in a linked list are linked using
pointers
The logical ordering is represented by having
each element pointing to the next element.
Each element is called a node, which has two
parts. INFO part which stores the information
and POINTER which points to the next
element.
WHY LINKED LIST?
Arrays can be used to store linear data of
similar types, but arrays have the following
limitations.
1) The size of the arrays is fixed:
2) Inserting a new element in an array of
elements is expensive.
ADVANTAGES OF LINKED LIST
Linked lists are dynamic data structures: .
Efficient memory utilization:
Insertion and deletions are easier and
efficient: .
Elements of linked list are flexible:
Disadvantages of Linked List
Random access is not allowed.
It cannot be easily sorted.
We must traverse 1/2 the list on average
to access any element.
More complex to create than an array.
Extra memory space for a pointer is
required with each element of the list.
OPERATIONS ON LINKED LIST
The basic operations to be performed on the
linked list as follows :
Creation
Insertion
Deletion
Traversing
Searching
Concatenation
TYPES OF LINKED LIST
Singly linked list..
Doubly linked list..
Circular linked list..
SINGLY LINKED LIST
A singly linked list is the simplest type of linked list that
is unidirectional
It can be traversed in only one direction from head to the
last node (tail).
Each element in a linked list is called a node.
Each node in a list consists of at least two parts:
1) data- contain information about item
2) Pointer (Or Reference) to the next node- contain address
of the next node
Info field Next field
REPRESENTATION
A linked list is represented by a pointer to the
first node of the linked list.
The first node is called the head.
itpoints to the first node of the list and helps us
access every other element in the list.
The last node, also sometimes called the tail,
points to NULL which helps us in determining when
the list ends.
If the linked list is empty, then the value of the
head is NULL.
OPERATION ON SINGLY LINKED LIST
Creating a Linked list
Traversing a Linked list
Inserting an element into Linked list
Deleting an element from linked list
Creating a Linked list
Definition is used to create every node in the
list.
The data field stores the element
The next is a pointer to store the address of
the next node.
class Node {
public:
int data;
Node* next;
};
CREATE A SIMPLE LINKED LIST WITH 3 NODES.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
};
// Program to create a simple linked list with 3 nodes
int main()
{
Node* head = NULL;
Node* second = NULL;
Node* third = NULL;
// allocate 3 nodes in the heap
head = new Node();
second = new Node();
third = new Node();
head->data = 1; // assign data in first node
head->next = second; // Link first node with the
second node
second->data = 2; // assign data to second
node
second->next = third; // Link second node with
the third node
third->data = 3; // assign data to third node
third->next = NULL;
return 0;
}
TRAVERSING A LINKED LIST
Traversing a linked list means accessing the nodes of
the list in order to perform some processing on them.
The linked list can be traversed in a while loop by using
the head node as a starting reference:
#include<iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
};
//This function prints contents of linked list starting from the
given node
void printList(Node* n)
{
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}
}
// Driver code
int main()
{
Node* head = NULL;
Node* second = NULL;
Node* third = NULL;
// allocate 3 nodes in the heap
head = new Node();
second = new Node();
third = new Node();
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(head);
return 0;
}
Output: 1 2 3
INSERTING A NEW NODE IN A LINKED LIST
The new node is inserted at the beginning.
The new node is inserted at the end.
The new node is inserted at a specific
position
INSERTING AT THE START
Inserting a new node at the start of the list
means that the new node will serve as the new
head.
It also fills the data within the node. Moreover, it
adjusts the pointer to start from the new head.
It will push the former head aside, the process
uses the push() function.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node * next;
};
void printlist(Node * n) {
cout << "\nPrinting new list..." << endl;
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}}
void push(struct Node ** head_ref, int
new_data) { struct Node * new_node =
(struct Node * ) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = ( * head_ref);
( * head_ref) = new_node;
}
int main() {
Node * head = NULL;
Node * second = NULL;
Node * third = NULL;
head = new Node();
second = new Node();
third = new Node();
head->data = 1;
head->next = second;
second->data = 2;
second->next = third; Output
third->data = 3; Printing new
list...
third->next = NULL; 5123
print_list(head);
push(&head, 5);
print_list(head);
}
INSERTING AT THE END
If you add a new node at the end of the list,
it'll become the end of the traversal within
the list. In other words, you should set the
new node to point at NULL.
#include <iostream>
using namespace std;
class Node {
public:
int data; Node * next;
};
void print_list(Node * n) {
cout << "\nPrinting new list..." << endl;
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}}
void append(struct Node ** head_ref, int new_data) {
struct Node * new_node = (struct Node * )
malloc(sizeof(struct Node
struct Node * last = * head_ref;
new_node->data = new_data;
new_node->next = NULL;
while (last->next != NULL)
last = last->next;
last->next = new_node;
}
int main() {
Node * head = NULL;
Node * second = NULL;
Node * third = NULL;
head = new Node();
second = new Node();
third = new Node();
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
Output
third->data = 3; Printing new
third->next = NULL; list...
123 6
print_list(head);
append(&head, 6);
print_list(head);
}
INSERTING AT A SPECIFIC POSITION
The purpose of this method is to put a new
node between the head and the tail.
we have to fill the data and adjust the
pointer of the new node with its previous
node.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node * next;
};
void print_list(Node * n) {
cout << "\nPrinting new list..." << endl;
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}}
void insertAfter(struct Node * prev_node, int new_data) {
if(prev_node == NULL) {
printf("the given previous node cannot be NULL");
return;
}
struct Node * new_node = (struct Node * )
malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
}
int main() {
Node * head = NULL;
Node * second = NULL;
Node * third = NULL;
head = new Node();
second = new Node();
third = new Node();
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
Output
third->data = 3; Printing new
third->next = NULL; list...
1253
print_list(head);
insertAfter(second, 5);
print_list(head);
}
DELETING A NODE FROM A LINKED
LIST
The first node is deleted.
The last node is deleted.
The node at specific position is deleted .
DELETING FROM BEGINNING OF THE
LIST
We can use the following steps to delete a node from
beginning of the single linked list...
Step 1 - Check whether list
is Empty (head == NULL)
Step 2 - If it is Empty then, display 'List is Empty!!!
Deletion is not possible' and terminate the
function.
Step 3 - If it is Not Empty then, define a Node
pointer 'temp' and initialize with head.
Step 4 - Check whether list is having only one node
(temp → next == NULL)
Step 5 - If it is TRUE then set head = NULL and
delete temp (Setting Empty list conditions)
Step 6 - If it is FALSE then set head = temp → next,
and delete temp.
Void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
DELETING FROM END OF THE LIST
Step 1 - Check whether list is Empty (head == NULL)
Step 2 - If it is Empty then, display 'List is Empty!!!
Deletion is not possible' and terminate the function.
Step 3 - If it is Not Empty then, define two Node
pointers 'temp1' and 'temp2' and initialize 'temp1'
with head.
Step 4 - Check whether list has only one Node (temp1
→ next == NULL)
Step 5 - If it is TRUE. Then, set head = NULL and
delete temp1. And terminate the function.
(Setting Empty list condition)
Step 6 - If it is FALSE. Then, set 'temp2 = temp1 '
and move temp1 to its next node. Repeat the same
until it reaches to the last node in the list. (until temp1
→ next == NULL)
Step 7 - Finally, Set temp2 → next = NULL and
delete temp1.
voiddelete_last()
{
node *current=new node;
node *previous=new node;
current=head;
while(current->next!=NULL)
{
previous=current;
current=current->next;
}
tail=previous;
previous->next=NULL;
delete current;
}
DELETING A SPECIFIC NODE FROM THE LIST
Step 1 - Check whether list is Empty (head == NULL)
Step 2 - If it is Empty then, display 'List is Empty!!! Deletion is not
possible' and terminate the function.
Step 3 - If it is Not Empty then, define two Node pointers 'temp1' and
'temp2' and initialize 'temp1' with head.
Step 4 - Keep moving the temp1 until it reaches to the exact node to be
deleted or to the last node. And every time set 'temp2 = temp1' before
moving the 'temp1' to its next node.
Step 5 - If it is reached to the last node then display 'Given node not
found in the list! Deletion not possible!!!'. And terminate the function.
Step 6 - If it is reached to the exact node which we want to delete, then
check whether list is having only one node or not
Step 7 - If list has only one node and that is the node to be deleted, then
set head = NULL and delete temp1 (free(temp1)).
Step 8 - If list contains multiple nodes, then check whether temp1 is the
first node in the list (temp1 == head).
Step 9 - If temp1 is the first node then move the head to the next node
(head = head → next) and delete temp1.
Step 10 - If temp1 is not first node then check whether it is last node in the
list (temp1 → next == NULL).
Step 11 - If temp1 is last node then set temp2 → next = NULL and
delete temp1 (free(temp1)).
Step 12 - If temp1 is not first node and not last node then set temp2 →
next = temp1 → next and delete temp1 (free(temp1)).
Void delete_position(intpos)
{
node *current=new node;
node *previous=new node;
current=head;
for(inti=1;i<pos;i++)
{
previous=current;
current=current->next;
}
previous->next=current->next;
}
POLYNOMIAL
Polynomial is a mathematical expression
that consists of variables and coefficients.
for example x^2 - 4x + 7
An essential characteristic of the polynomial
is that each term in the polynomial
expression consists of two parts:
one is the coefficient
other is the exponent
Example:
10x2 + 26x, here 10 and 26 are coefficients
and 2, 1 is its exponential value.
REPRESENTATION OF
POLYNOMIAL
Polynomial can be represented in the various
ways. These are:
By the use of arrays
By the use of Linked List
In the Polynomial linked list, the
coefficients and exponents of the polynomial
are defined as the data node of the list.
POINTS TO KEEP IN MIND WHILE
WORKING WITH POLYNOMIALS:
The sign of each coefficient and exponent is
stored within the coefficient and the
exponent itself
Additional terms having equal exponent is
possible one
The storage allocation for each term in the
polynomial must be done in ascending and
descending order of their exponent
ADDING TWO POLYNOMIALS USING
LINKED LIST
Adding two polynomials that are represented
by a linked list.
We check values at the exponent value of the
node. For the same values of exponent, we
will add the coefficients
Example,
Input :
p1= 13x8 + 7x5 + 32x2 + 54
p2= 3x12 + 17x5 + 3x3 + 98
Output : 3x12 + 13x8 + 24x5 + 3x3 + 32x2 + 152
ALGORITHM
Input − polynomial p1 and p2 represented as a linked
list.
Step 1: loop around all values of linked list and follow
step 2& 3.
Step 2: if the value of p1 node exponent is greater
than the exponent value of p2 node.
Then the node of p1 is store to resultant node of polynomial.
Step 3: : if the value of p1 node exponent is lesser
than the exponent value of p2 node.
Then the node of p2 is store to resultant node of polynomial.
Step 4:if the values of both p1 and p2 node’s exponent
is same
Then add the coefficients value and store it to resultant
node of polynomial.
Step 5: Print the resultant node.
void polyadd(struct Node *p1, struct Node *p2, struct Node *result)
{
while(p1->next && p2->next){
if(p1->pow > p2->pow){
result->pow = p1->pow;
result->coeff = p1->coeff;
p1 = p1->next;
}
else if(p1->pow < p2->pow){
result->pow = p2->pow;
result->coeff = p2->coeff;
p2 = p2->next;
}
else {
result->pow = p1->pow;
result->coeff = p1->coeff+p2->coeff;
p1 = p1->next;
p2 = p2->next;
}
result->next = (struct Node *)malloc(sizeof(struct Node));
result = result->next;
result->next = NULL;
}
while(p1->next || p2->next){
if(p1->next){
result->pow = p1->pow;
result->coeff = p1->coeff;
p1 = p1->next;
}
if(p2->next){
result->pow = p2->pow;
result->coeff = p2->coeff;
p2 = p2->next;
}
result->next = (struct Node *)malloc(sizeof(struct Node));
result = result->next;
result->next = NULL;
}}
DOUBLY LINKED LIST IN DATA
STRUCTURES
A doubly linked list is also called a two-way
linked list
It is a more complex type of linked list which
contains a pointer to the next as well as the
previous node in the sequence.
Each node in doubly linked list has two link
fields. These are used to point to the successor
node and predecessor nodes.
It provides bi-directional traversing
REPRESENTATION
A doubly linked list is one in which all nodes
are linked together by multiple number of
links which help in accessing both the
successor node and predecessor node from
the given node position
It consists of three parts—data, a pointer to
the next node, and a pointer to the previous
node.
Prev pointer Data Next Pointer
The first link points to the previous node in the
list and the second link points to the next node
in the list. The first node of the list has its
previous link pointing to NULL similarly the last
node of the list has its next node pointing to .
Advantages
Insertions and deletion are simple as
compared to other linked list.
Efficient utilization of memory.
Bi-directional traversal helps in efficient and
easy accessibility of nodes.
Disadvantages
Uses two pointers, which results in more
memory space requirement.
OPERATIONS ON DLL
Traversing
Forward_traverse:
Backward _traverse:
Insertion
The new node is inserted at the beginning.
The new node is inserted at the end.
The new node is inserted after a given node.
The new node is inserted before a given node.
Deletion
The first node is deleted.
The last node is deleted.
The node after a given node is deleted.
The node before a given node is deletedon
TRAVERSAL
Traversal is a technique of visiting each node
in the linked list.
In a doubly linked list, we have two types of
traversals as we have two pointers with
different directions in the doubly linked list.
Forward traversal – Traversal is done using
the next pointer which is in the forward
direction.
Backward traversal – Traversal is done
using the previous pointer which is the
backward direction
FORWARD TRAVERSAL
Start with the front node and visit all the
nodes untill the node becomes NULL.
void Doubly_Linked_List :: forward_traverse() {
node *trav;
trav = front;
while(trav != NULL) {
cout<<trav->data<<endl;
trav = trav->next;
}
}
BACKWARD TRAVERSAL
Start with the end node and visit all the
nodes until the node becomes NULL.
void Doubly_Linked_List :: backward_traverse() {
node *trav;
trav = end;
while(trav != NULL) {
cout<<trav->data<<endl;
trav = trav->prev;
}}
INSERT DATA IN THE BEGINNING
The prev pointer of first node will always be
NULL and next will point to front.
If the node is inserted is the first node of the
list then we make front and end point to this
node.
Else we only make front point to this node.
void Doubly_Linked_List :: add_front(int d) {
// Creating new node
node *temp;
temp = new node();
temp->data = d;
temp->prev = NULL;
temp->next = front;
// List is empty
if(front == NULL)
end = temp;
else
front->prev = temp;
front = temp;
}
INSERT DATA IN THE END
The next pointer of last node will always be
NULL and prev will point to end.
If the node is inserted is the first node of the
list then we make front and end point to this
node.
Else we only make end point to this node.
void Doubly_Linked_List :: add_end(int d) {
// create new node
node *temp;
temp = new node();
temp->data = d;
temp->prev = end;
temp->next = NULL;
// if list is empty
if(end == NULL)
front = temp;
else
end->next = temp;
end = temp;
}
INSERT DATA BEFORE A NODE
Let’s say we are inserting node X before Y.
Then X’s next pointer will point to Y and X’s
prev pointer will point the node Y’s prev
pointer is pointing. And Y’s prev pointer will
now point to X. We need to make sure that if
Y is the first node of list then after adding X
we make front point to X.
void Doubly_Linked_List :: add_before(node *n, int
d) {
node *temp;
temp = new node();
temp->data = d;
temp->next = n;
temp->prev = n->prev;
n->prev = temp;
//if node is to be inserted before first node
if(n->prev == NULL)
front = temp;
}
INSERT DATA AFTER A NODE
Let’s say we are inserting node Y after X.
Then Y’s prev pointer will point to X and Y’s
next pointer will point the node X’s next
pointer is pointing. And X’s next pointer will
now point to Y. We need to make sure that if
X is the last node of list then after adding Y
we make end point to Y.
void Doubly_Linked_List :: add_after(node *n, int d)
{
node *temp;
temp = new node();
temp->data = d;
temp->prev = n;
temp->next = n->next;
n->next = temp;
//if node is to be inserted after last node
if(n->next == NULL)
end = temp;
}
REMOVE A NODE
Removal of a node is quite easy in Doubly
linked list but requires special handling if the
node to be deleted is first or last element of
the list.
Unlike singly linked list where we require the
previous node, here only the node to be
deleted is needed.
We simply make the next of the previous
node point to next of current node (node to
be deleted) and prev of next node point to
prev of current node.
void Doubly_Linked_List :: delete_node(node *n) {
// if node to be deleted is first node of list
if(n->prev == NULL) {
front = n->next; //the next node will be front of list
front->prev = NULL;
}
// if node to be deleted is last node of list else
if(n->next == NULL) {
end = n->prev; // the previous node will be last of list end->next
= NULL;
}
else { //previous node's next will point to current node's
next n->prev->next = n->next; //next node's prev will point to
current node's
prev n->next->prev = n->prev;
}
//delete node
delete(n);
}
CIRCULAR LINKED LIST
A circular linked list is a sequence of
elements in which every element has a
link to its next element in the sequence
and the last element has a link to the
first element.
That means circular linked list is similar to
the single linked list except that the last node
points to the first node in the list
OPERATIONS
In a circular linked list, we perform the following
operations...
Insertion
Deletion
Display
Before we implement actual operations, first we need to
setup empty list. First perform the following steps before
implementing actual operations.
Step 1 - Include all the header files which are used in
the program.
Step 2 - Declare all the user defined functions.
Step 3 - Define a Node structure with two
members data and next
Step 4 - Define a Node pointer 'head' and set it
to NULL.
Step 5 - Implement the main method by displaying
operations menu and make suitable function calls in the
main method to perform user selected operation.
INSERTION
In a circular linked list, the insertion
operation can be performed in three ways.
They are as follows...
Inserting At Beginning of the list
Inserting At End of the list
Inserting At Specific location in the list
DELETION
In a circular linked list, the deletion operation
can be performed in three ways those are as
follows...
Deleting from Beginning of the list
Deleting from End of the list
Deleting a Specific Node
ADVANTAGES OF CIRCULAR
LINKED LISTS:
1) Any node can be a starting point. We can traverse
the whole list by starting from any point. We just need
to stop when the first visited node is visited again.
2) Useful for implementation of queue. Unlike this
implementation, we don’t need to maintain two
pointers for front and rear if we use circular linked list.
We can maintain a pointer to the last inserted node
and front can always be obtained as next of last.
3) Circular lists are useful in applications to repeatedly
go around the list.
4) Circular Doubly Linked Lists are used for
implementation of advanced data structures like
Fibonacci Heap.
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *next;
};
struct Node* head = NULL;
void insert(int newdata) {
struct Node *newnode = (struct Node *)malloc(sizeof(struct Node));
struct Node *ptr = head;
newnode->data = newdata;
newnode->next = head;
if (head!= NULL) {
while (ptr->next != head)
ptr = ptr->next;
ptr->next = newnode; }
else
newnode->next = newnode;
head = newnode;
}
void display() {
struct Node* ptr;
ptr = head;
do {
cout<<ptr->data <<" ";
ptr = ptr->next;
} while(ptr != head);
}
int main() {
insert(3);
insert(1);
insert(7);
insert(2);
insert(9);
cout<<"The circular linked list is: ";
display();
return 0; }