Lecture 5 Lists
Lecture 5 Lists
Lecture 5 Lists
LINKED LISTS
Linked List is a very commonly used linear data structure which consists of group of nodes in a
sequence.
Each node holds its own data and the address of the next node hence forming a chain like
structure.
Linked Lists are used to create trees and graphs.
They are a dynamic in nature which allocates the memory when required.
Insertion and deletion operations can be easily implemented.
Stacks and queues can be easily executed.
Linked List reduces the access time.
Let's know more about them and how they are different from each other.
We will learn about all the 3 types of linked list, one by one, in the next tutorials. So click
on Next button, let's learn more about linked lists.
Array is a collection of elements of similar data Linked List is an ordered collection of elements of same type,
type. which are connected to each other using pointers.
Array supports Random Access, which means Linked List supports Sequential Access, which means to
elements can be accessed directly using their access any element/node in a linked list, we have to
index, like arr[0] for 1st sequentially traverse the complete linked list, upto that
element, arr[6] for 7th element etc. element.
In an array, elements are stored in contiguous In a linked list, new elements can be stored anywhere in the
memory location or consecutive manner in the memory.
memory.
Address of the memory location allocated to the new element
is stored in the previous node of linked list, hence formaing a
link between the two nodes/elements.
In array, Insertion and Deletion operation In case of linked list, a new element is stored at the first free
takes more time, as the memory locations are and available memory location, with only a single overhead
consecutive and fixed. step of 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 Memory is allocated at runtime, as and when a new node is
declared, at compile time. It's also known added. It's also known as Dynamic Memory Allocation.
as Static Memory Allocation.
In array, each element is independent and can In case of a linked list, each node/element points to the next,
be accessed using it's index value. previous, or maybe both nodes.
Size of the array must be specified at time of Size of a Linked list is variable. It grows at runtime, as more
array declaration. nodes are added to it.
Array gets memory allocated in Whereas, linked list gets memory allocated in Heap section.
the Stack section.
Below we have a pictorial representation showing how consecutive memory locations are
allocated for array, while in case of linked list random memory locations are assigned to nodes,
but each node is connected to its next node using pointer.
Hence while writing the code for Linked List we will include methods to insert or add new data
elements to the linked list, both, at the beginning of the list and at the end of the list.
We will also be adding some other useful methods like:
Before learning how we insert data and create a linked list, we must understand the components
forming a linked list, and the main component is the Node.
What is a Node?
A Node in a linked list holds the data value and the pointer which points to the location of the
next node in the linked list.
In the picture above we have a linked list, containing 4 nodes, each node has some data(A, B, C
and D) and a pointer which stores the location of the next node.
You must be wondering why we need to store the location of the next node. Well, because the
memory locations allocated to these nodes are not contiguous hence each node should know
where the next node is stored.
As the node is a combination of multiple information, hence we will be defining a class
for Node which will have a variable to store data and another variable to store the pointer. In C
language, we create a structure using the struct keyword.
class Node
{
public:
// our linked list will only hold int data
int data;
//pointer to the next node
node* next;
// default constructor
Node()
{
data = 0;
next = NULL;
}
// parameterised constructor
Node(int x)
{
data = x;
next = NULL;
}
}
We can also make the Node class properties data and next as private, in that case we will need
to add the getter and setter methods to access them(don't know what getter and setter methods
are: Inline Functions in C++ ). You can add the getter and setter functions to the Node class like
this:
class Node
{
// our linked list will only hold int data
int data;
//pointer to the next node
node* next;
class LinkedList
{
public:
node *head;
//declaring the functions
LinkedList()
{
head = NULL;
}
}
Insertion at the Beginning
Steps to insert a Node at beginning :
1. If the Linked List is empty then we simply, add the new Node as the Head of the Linked
List.
If the Linked List is not empty then we find the last node, and make it' next to the new Node,
hence making the new node the last Node.
If the Node to be deleted is the first node, then simply set the Next pointer of the Head to
point to the next element from the Node to be deleted.
If the Node is in the middle somewhere, then find the Node before it, and make the Node before
it point to the Node next to it.
Now you know a lot about how to handle List, how to traverse it, how to search an element. You
can yourself try to write new methods around the List.
If you are still figuring out, how to call all these methods, then below is how
your main() method will look like. As we have followed OOP standards, we will create the
objects of LinkedList class to initialize our List and then we will create objects of Node class
whenever we want to add any new node to the List.
int main() {
LinkedList L;
//We will ask value from user, read the value and add the value to our Node
int x;
cout << "Please enter an integer value : ";
cin >> x;
Node *n1;
//Creating a new node with data as x
n1 = new Node(x);
//Adding the node to the list
L.addAtFront(n1);
}
Similarly you can call any of the functions of the LinkedList class, add as many Nodes you want
to your List
The real life application where the circular linked list is used is our Personal Computers,
where multiple applications are running. All the running applications are kept in a
circular linked list and the OS gives a fixed time slot to all for running. The Operating
System keeps on iterating over the linked list until all the applications are completed.
Another example can be Multiplayer games. All the Players are kept in a Circular Linked
List and the pointer keeps on moving forward as a player's chance ends.
Circular Linked List can also be used to create Circular Queue. In a Queue we have to
keep two pointers, FRONT and REAR in memory all the time, where as in Circular
Linked List, only one pointer is required.
class Node {
public:
int data;
//pointer to the next node
node* next;
node() {
data = 0;
next = NULL;
}
node(int x) {
data = x;
next = NULL;
}
}
Circular Linked List
Circular Linked List class will be almost same as the Linked List class that we studied in the
previous lesson, with a few difference in the implementation of class methods.
class CircularLinkedList {
public:
node *head;
//declaring the functions
//function to add Node at front
int addAtFront(node *n);
//function to check whether Linked list is empty
int isEmpty();
//function to add Node at the End of list
int addAtEnd(node *n);
//function to search a value
node* search(int k);
//function to delete any Node
node* deleteNode(int x);
CircularLinkedList() {
head = NULL;
}
}
Insertion at the Beginning
Steps to insert a Node at beginning :
The previous Head Node is now the second Node of Linked List, because the new Node is added
at the front.
1. If the Linked List is empty then we simply, add the new Node as the Head of the Linked
List.
2. If the Linked List is not empty then we find the last node, and make it' next to the new
Node, and make the next of the Newly added Node point to the Head of the List.
If the Node to be deleted is the first node, then simply set the Next pointer of the Head to
point to the next element from the Node to be deleted. And update the next pointer of the
Last Node as well.
If the Node is in the middle somewhere, then find the Node before it, and make the Node
before it point to the Node next to it.
If the Node is at the end, then remove it and make the new last node point to the head.
The two links help us to traverse the list in both backward and forward direction. But storing an
extra link requires some extra space.
class Doubly_Linked_List
{
node *front; // points to first node of list
node *end; // points to first las of list
public:
Doubly_Linked_List()
{
front = NULL;
end = NULL;
}
void add_front(int );
void add_after(node* , int );
void add_before(node* , int );
void add_end(int );
void delete_node(node*);
void forward_traverse();
void backward_traverse();
};
// List is empty
if(front == NULL)
end = temp;
else
front->prev = temp;
front = temp;
}
// if list is empty
if(end == NULL)
front = temp;
else
end->next = temp;
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. Look code for more details.
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);
}
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;
}
}