(DStructure - Slides) Linked List
(DStructure - Slides) Linked List
Linked Lists
Let's see how each node of the linked list is represented. Each node
consists:
A data item
An address of another node
Each struct node has a data item and a pointer to another struct node.
Let us create a simple Linked List with three items to understand how
this works.
We wrap both the data item and the next node reference in a struct as:
struct node
{
int data;
struct node *next;
};
// Linked list implementation in C++
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
// Creating a node
class Node {
public:
int value;
Node* next;
};
int main() { // print the linked list value
Node* head; head = one;
Node* one = NULL;
Node* two = NULL;
while (head != NULL) {
Node* three = NULL; cout << head->value;
// allocate 3 nodes in the heap head = head->next;
one = new Node(); }
two = new Node(); }
three = new Node();
// Assign value values
one->value = 1;
two->value = 2;
three->value = 3;
// Connect nodes
one->next = two;
two->next = three;
three->next = NULL;
OPERATION ON LINKED LIST
p: is a pointer
node(p): the node pointed to by p
info(p): the information portion of the node
next(p): the next address portion of the node
getnode(): obtains an empty node
freenode(p): makes node(p) available for reuse even
if the value of the pointer p is changed.
Adding an Element to the front of a Linked List
info next
p p = getnode()
info next
p 6 info(p) = 6
info next info next info next
list 5 3 8 null
Adding an Element to the front of a Linked List
info next
p 6
next(p) = list
info next info next info next
5 3 8 null
list
Adding an Element to the front of a Linked List
info next
p
list
6
list = p
info next info next info next
5 3 8 null
Adding an Element to the front of a Linked List
p = list
info next info next info next info next
list
6 5 3 8 null
p
Removing an Element from the front of a Linked
List
info next
p 6 list = next(p)
info next info next info next
5 3 8 null
list
Removing an Element from the front of a Linked
List
info next
p 6 x = info(p)
info next info next info next
x=6
5 3 8 null
list
Removing an Element from the front of a Linked
List
info next
p
freenode(p)
info next info next info next
x=6
list 5 3 8 null
Removing an Element from the front of a Linked
List
Write a C++ program to create a singly linked list of n nodes and display it in reverse
order
Write a C++ program to create a singly linked list of n nodes and count the number
of nodes
Stack and Queues using
Linked Structures
Implementing stacks using arrays
• Simple implementation
• The size of the stack must be determined
when a stack object is declared
• Space is wasted if we use less elements
• We cannot "push" more elements than the
array can hold
Implement Stack using linked list
• A stack is an abstract data structure that contains a collection
of elements. Stack implements the LIFO mechanism i.e. the
element that is pushed at the end is popped out first. Some of
the principle operations in the stack are −
ItemType* itemPtr;
...
itemPtr = new ItemType;
*itemPtr = newItem;
Dynamic allocation of each
stack element (cont.)
• How should we preserve the order of the
stack elements?
Chaining the stack elements
together
Chaining the stack elements
together (cont.)
• Each node in the stack should contain two
parts:
– info: the user's data
– next: the address of the next element in the stack
Node Type
template<class ItemType>
struct NodeType {
ItemType info;
NodeType* next;
};
Popping the top element
Popping the top
element
(cont.)
Need to use a
temporary
pointer
Popping the last element on the stack
#include <iostream>
using namespace std;
struct Node {
int data; void display() {
struct Node *next; struct Node* ptr;
}; if(top==NULL)
struct Node* top = NULL; cout<<"stack is empty";
void push(int val) { else {
struct Node* newnode = (struct ptr = top;
Node*) malloc(sizeof(struct Node)); cout<<"Stack elements are: ";
newnode->data = val; while (ptr != NULL) {
newnode->next = top; cout<< ptr->data <<" ";
top = newnode; ptr = ptr->next;
} }
void pop() { }
if(top==NULL) cout<<endl;
cout<<"Stack Underflow"<<endl; }
else {
cout<<"The popped element is "<<
top->data <<endl;
top = top->next;
}
int main() {
int ch, val;
cout<<"1) Push in stack"<<endl;
cout<<"2) Pop from stack"<<endl;
cout<<"3) Display stack"<<endl;
cout<<"4) Exit"<<endl;
do {
cout<<"Enter choice: "<<endl;
cin>>ch;
switch(ch) { break;
case 1: { }
cout<<"Enter value to be pushed:"<<endl; case 4: {
cin>>val; cout<<"Exit"<<endl;
push(val); break;
break; }
} default: {
case 2: { cout<<"Invalid Choice"<<endl;
pop(); }
break; }
} }while(ch!=4);
case 3: { return 0;
display(); }
Implementing queues using
arrays
• Simple implementation
• The size of the queue must be determined
when a stack object is declared
• Space is wasted if we use less elements
• We cannot "enqueue" more elements than
the array can hold
Implementing queues using
linked lists
• Allocate memory for each new element
dynamically
• Link the queue elements together
• Use two pointers, qFront and qRear, to
mark the front and rear of the queue
Enqueuing (non-empty queue)
Enqueuing (empty queue)
• We need to make qFront point to the new
node also
qRear = NULL
newNode
Function Enqueue
template <class ItemType>
void QueueType<ItemType>::Enqueue(ItemType
newItem)
{
NodeType<ItemType>* newNode;
newNode = new NodeType<ItemType>;
newNode->info = newItem;
newNode->next = NULL;
if(qRear == NULL)
qFront = newNode;
else
qRear->next = newNode;
qRear = newNode;
}
Dequeueing (the queue contains
more than one element)
Dequeueing (the queue contains
only one element)
• We need to reset qRear to NULL also
qFront After dequeue:
Node qFront = NULL
qRear qRear = NULL
Function Dequeue
template <class ItemType>
void QueueType<ItemType>::Dequeue(ItemType& item)
{
NodeType<ItemType>* tempPtr;
tempPtr = qFront;
item = qFront->info;
qFront = qFront->next;
if(qFront == NULL)
qRear = NULL;
delete tempPtr;
}
qRear, qFront revisited
• The relative positions of qFront and qRear
are important!
A circular linked queue design
#include <iostream>
using namespace std; } else {
struct node { temp=(struct node
int data; *)malloc(sizeof(struct node));
struct node *next; rear->next = temp;
}; temp->data = val;
struct node* front = NULL; temp->next = NULL;
struct node* rear = NULL; rear = temp;
struct node* temp; }
void Insert() { }
int val; void Delete() {
cout<<"Insert the element in queue : temp = front;
"<<endl; if (front == NULL) {
cin>>val; cout<<"Underflow"<<endl;
if (rear == NULL) { return;
rear = (struct node }
*)malloc(sizeof(struct node));
rear->next = NULL;
rear->data = val;
front = rear;
else
if (temp->next != NULL) {
temp = temp->next; cout<<"Queue elements are: ";
cout<<"Element deleted from while (temp != NULL) {
queue is : "<<front->data<<endl; cout<<temp->data<<" ";
free(front); temp = temp->next;
front = temp; }
} else { cout<<endl;
cout<<"Element deleted from }
queue is : "<<front->data<<endl; int main() {
free(front); int ch;
front = NULL; cout<<"1) Insert element to
rear = NULL; queue"<<endl;
} cout<<"2) Delete element from
} queue"<<endl;
void Display() { cout<<"3) Display all the elements of
temp = front; queue"<<endl;
if ((front == NULL) && (rear == cout<<"4) Exit"<<endl;
NULL)) { do {
cout<<"Queue is empty"<<endl;
return;
}
cout<<"Enter your choice :
"<<endl;
cin>>ch;
switch (ch) {
case 1: Insert();
break;
case 2: Delete();
break;
case 3: Display();
break;
case 4:
cout<<"Exit"<<endl;
break;
default: cout<<"Invalid
choice"<<endl;
}
} while(ch!=4);
return 0;
}
QUEUE USING TWO STACKS
• Stack is a data structure where you get Last in First
out implementation,
• and queue is with first in first out implementation.
• To visualise it more clearly here a class with the name
“Queue” has been created, where there will be just
two stacks as member variables and the member
functions will be working as the functions to access
or manipulate the queue. We will use the stack in C++
STl as the stack.
Linked List
PA RT 3
QUEUE USING TWO STACKS
The task at hand is to implement a queue using a
stack data structure, with the push (adding an
element) and pop (removing an element) operations
as the low-level data structure.
A queue is a FIFO (First In First Out), while a stack is a
LIFO (Last In First Out) data structure.
A stack pushes a new element to the top of the stack
and also pops the element at the top. A queue,
however, dequeues (removes) an element from the
top of the queue, but it enqueues (inserts) an
element at the bottom.
So, we take two stacks, s1 and s2.
Øs1 will be working as the main queue and s2 will help us in reversing the order of s1.
The basic difference between a stack and a queue is the popping process, that is called
Dequeue for the queue. If you think the top of the stack is the back of the queue, the
pushing process is the same. But the popping will be in the reverse order. So we will use
a stack (s2) temporarily to reverse the values.
ØSo, the pushing will be pushing to s1.
ØTo pop elements from the back, we will pop out elements from s1 and push it in s2.
ØThen pop only one element.
ØThen again push them into s1. The order of them won’t change for the queue.
ØSame algorithm will be used to check the front value of the queue.
ØThere is another way in which you can turn one stack into a queue. Here it is: Queue
using one stack.
Implementation
There are two methods used to implement a queue using the stack data structure. One method uses two stacks
while the other uses one.
Step 1: loop around all values of linked list and follow step 2& 3.
Step 2: if the value of a node’s exponent. is greater copy this node to result node and head towards the next
node.
Step 3: if the values of both node’s exponent is same add the coefficients and then copy the added value
with node to the result.
Step 4: Print the resultant node.
DOUBLY LINKED LIST
What is the logic of a circular linked list? It is very similar to a singly linked list but the main
difference is that the last node is connected to the first node. To create the list, a head pointer is
set to NULL. When a new node is added, it is created with its data value. The next pointer of the
new node now points to the head of the list, and the head pointer points to the new node.
Insertion at the end
Entering data at the end is much easier than entering data at the beginning. Once
again, we need to create a new node and assign the data to it. Following that, we
need to traverse to the last node of the linked list.
Insertion at the middle
The fundamental algorithm for insertion is followed here for
generalizing the use cases. Traverse the linked list till before the point
where the new node has to be inserted.
Deletion of Element at Start
The process for deletion works almost in a similar manner as for insertion, with only one fundamental
difference – deletion requires two pointers, one for pointing towards the node before, and one for
pointing towards the node after. In a similar fashion as insertion, traverse till the last node of the linked
list with one pointer and store the head of the linked list in another pointer.
Deletion of Element at the End
Deletion from the end is considerably easier. All you need to do is
traverse till the end of the linked list with one pointer and till the node
before the last node with another pointer.
Deletion of Element at the Middle
A generalized algorithm for deletion can be designed similarly to insertion. All one
needs to do is make one pointer traverse to a node before the required node in the
list and one pointer traverse to the required node itself.
TYPES OF LINKED LIST IN
DATA STRUCTURES
Chapter5 part 2
SINGLY LINKED LIST
It is the commonly used linked list in programs. If we are talking about the linked
list, it means it is a singly linked list. The singly linked list is a data structure that
contains two parts, i.e., one is the data part, and the other one is the address part,
which contains the address of the next or the successor node. The address part in
a node is also known as a pointer.
Suppose we have three nodes, and the addresses of these three nodes are 100,
200 and 300 respectively. The representation of three nodes as a linked list is
shown in the below figure:
The linked list, which is shown in the above diagram, is known as a singly linked list as it
contains only a single link. In this list, only forward traversal is possible; we cannot traverse in
the backward direction as it has only one link in the list.
ALGORITHM FOR INSERTING A NODE
ALGORITHM FOR DELETING A NODE
DOUBLY LINKED LISTS
As the name suggests, the doubly linked list contains two pointers. We can define
the doubly linked list as a linear data structure with three parts: the data part and
the other two address part. In other words, a doubly linked list is a list that has three
parts in a single node, includes one data part, a pointer to its previous node, and a
pointer to the next node.
Suppose we have three nodes, and the address of these nodes are 100, 200 and
300, respectively. The representation of these nodes in a doubly-linked list is shown
below:
Disadvantage:
Increase in space requirements.
As we can observe in the above figure, the node in a doubly-linked list has two
address parts; one part stores the address of the next while the other part of the node
stores the previous node's address. The initial node in the doubly linked list has the
NULL value in the address part, which provides the address of the previous node.
A doubly linked list is a bi-directional linked list. So, you can traverse it in both directions. Unlike singly
linked lists, its nodes contain one extra pointer called the previous pointer. This pointer points to the
previous node.
Structure of Doubly Linked List
A doubly linked list of singly linked lists is a data structure that consists of a set of singly linked lists (SLLs),
each of which is doubly linked. It is used to store data in a way that allows for fast insertion and deletion
of elements.
Each SLL is made up of two parts: a head and a tail. The head of each SLL contains a pointer to the first
element in the list, and the tail contains a pointer to the last element.
It is advantageous over other data structures because it allows for quick insertion and deletion of
elements. Additionally, it is easy to implement and can be used in a variety of applications.
Representation of the node in a doubly linked list
struct node
{
int data;
struct node *next;
struct node *prev;
}
In the above representation, we have defined a user-defined structure named a node with three
members, one is data of integer type, and the other two are the pointers, i.e., next and prev of the
node type. The next pointer variable holds the address of the next node, and the prev pointer
holds the address of the previous node. The type of both the pointers, i.e., next and prev is struct
node as both the pointers are storing the address of the node of the struct node type.
Circular linked list
A circular linked list is a variation of a singly linked list. The only difference between the
singly linked list and a circular linked list is that the last node does not point to any node in a
singly linked list, so its link part contains a NULL value. On the other hand, the circular linked
list is a list in which the last node connects to the first node, so the link part of the last node
holds the first node's address. The circular linked list has no starting and ending node. We
can traverse in any direction, i.e., either backward or forward. The diagrammatic
representation of the circular linked list is shown below:
Structure of Circular Linked List
A circular linked list is a type of data structure that uses linked list technology to store data in
a linear, sequential fashion. However, unlike a traditional linked list, a circular linked list has
no beginning or end – it is essentially a ring of nodes. This makes circular linked lists ideal for
applications where data needs to be processed in a continuous loop, such as in real-time
applications or simulations.
Because there is no defined beginning or end to the list, circular linked lists are typically more
efficient than traditional linked lists when it comes to memory usage. This is because
traditional linked lists often require additional memory for pointers that point to the beginning
and end of the list. Circular linked lists, on the other hand, only require a single pointer to be
stored in memory – the head pointer.
DOUBLY CIRCULAR LINKED LIST
The doubly circular linked list has the features of both the circular linked list and
doubly linked list.
The above figure shows the representation of the doubly circular linked list in which
the last node is attached to the first node and thus creates a circle. It is a doubly
linked list also because each node holds the address of the previous node also. The
main difference between the doubly linked list and doubly circular linked list is that
the doubly circular linked list does not contain the NULL value in the previous field of
the node. As the doubly circular linked contains three parts, i.e., two address parts
and one data part so its representation is similar to the doubly linked list.
DCLs are often used in applications where data needs to be processed in a sequential
fashion, such as in a video or audio player. The circular nature of the list allows for
quick and easy movement from one node to the next without the need for special
case handling. DCLs are also sometimes used in applications where data needs to be
accessed randomly, such as in a database. In this case, the circular nature of the list
allows for quick and easy movement to any node in the list without the need for
special case handling