DS Unit-Ii
DS Unit-Ii
LINKED LISTS:
Step-by-step approach:
Create a new node with the given value.
Check if the list is empty:
o If it is, make the new node the head and return.
Traverse the list until the last node is reached.
Link the new node to the current last node by setting the last node's next pointer to
the new node.
c. Insertion at a Specific Position of the Singly Linked List: To insert a node at a
specific position, traverse the list to the desired position, link the new node to the next
node, and update the links accordingly.
Step-by-step approach:
Create a new node and assign it a value.
If inserting at the beginning (position = 1):
o Point the new node’s next to the current head.
o Update the head to the new node.
o Return (Insertion done).
Otherwise, traverse the list:
o Start from the head and move to the (position - 1)ᵗʰ node (just before the
desired position).
o If the position is beyond the list length, return an error or append at the end.
Insert the new node:
o Point the new node’s next to the next node of the current position.
o Update the previous node’s next to the new node.
Return the updated list.
5. Deletion in Singly Linked List
Deletion involves removing a node from the linked list. Similar to insertion, there are
different scenarios for deletion:
a. Deletion at the Beginning of Singly Linked List: To delete the first node, update the
head to point to the second node in the list.
Steps-by-step approach:
Check if the head is NULL.
o If it is, return NULL (the list is empty).
Store the current head node in a temporary variable temp.
Move the head pointer to the next node.
Delete the temporary node.
Return the new head of the linked list.
b. Deletion at the End of Singly Linked List: To delete the last node, traverse the list
until the second-to-last node and update its next field to None.
Step-by-step approach:
Check if the head is NULL.
o If it is, return NULL (the list is empty).
Check if the head's next is NULL (only one node in the list).
o If true, delete the head and return NULL.
Traverse the list to find the second last node (second_last).
Delete the last node (the node after second_last).
Set the next pointer of the second last node to NULL.
Return the head of the linked list.
c. Deletion at a Specific Position of Singly Linked List: To delete a node at a specific
position, traverse the list to the desired position, update the links to bypass the node to be
deleted.
Step-by-step approach:
Check if the list is empty or the position is invalid, return if so.
If the head needs to be deleted, update the head and delete the node.
Traverse to the node before the position to be deleted.
If the position is out of range, return.
Store the node to be deleted.
Update the links to bypass the node.
Delete the stored node.
6. Modify a Singly Linked List
Updating in a Singly Linked List means modifying the value of a node at a given position.
Step-by-step approach:
Start from the head of the list.
Traverse to the required position (move current node to position).
Check if the position is valid:
o If the position is out of bounds, return an error.
Update the node’s data with the new value.
Return the modified list.
7. Reversing a Singly Linked List
Reversing a singly linked list means changing the direction of pointers so that the last node
becomes the new head.
Step-by-step approach:
Initialize three pointers:
o prev = NULL (to track the previous node)
o current = head (starting point)
o next = NULL (to store the next node temporarily)
Iterate through the list:
o Store next = current->next (save next node).
o Reverse the link: current->next = prev.
o Move prev and current forward (prev = current, current = next).
Update head to prev (new head is the last node).
DUBLY LINKED LIST
A doubly linked list is a more complex data structure than a singly linked list, but it offers
several advantages. The main advantage of a doubly linked list is that it allows for efficient
traversal of the list in both directions. This is because each node in the list contains a
pointer to the previous node and a pointer to the next node. This allows for quick and easy
insertion and deletion of nodes from the list, as well as efficient traversal of the list in both
directions.
Representation of Doubly Linked List in Data Structure
In a data structure, a doubly linked list is represented using nodes that have three fields:
1. Data
2. A pointer to the next node (next)
3. A pointer to the previous node (prev)
Node Definition
Here is how a node in a Doubly Linked List is typically represented:
struct Node {
// Allocate memory
struct Node *newNode =
(struct Node *)malloc(sizeof(struct Node));
// Set the data
newNode->data = value;
// Initilize nodes
first->data = 2;
second->data = 3;
last->data = 4;
// Connect nodes
first->next = second;
second->next = last;
last->next = first;
In the above code, we have created three nodes first, second, and last having values 2, 3,
and 4 respectively.
After creating three nodes, we have connected these node in a series.
Connect the first node “first” to “second” node by storing the address of “second”
node into first’s next
Connect the second node “second” to “third” node by storing the address of “third”
node into second’s next
After connecting all the nodes, we reach the key characteristic of a circular linked
list: linking the last node back to the first node. Therefore, we store the address of
the “first” node in the “last” node.
Why have we taken a pointer that points to the last node instead of the first node?
For the insertion of a node at the beginning, we need to traverse the whole list. Also, for
insertion at the end, the whole list has to be traversed. If instead of the start pointer, we
take a pointer to the last node, then in both cases there won’t be any need to traverse the
whole list. So insertion at the beginning or at the end takes constant time, irrespective of
the length of the list.
Operations on the Circular Linked list
We can do some operations on the circular linked list similar to the singly and doubly
linked list which are:
1. Insertion
Insertion at the empty list
Insertion at the beginning
Insertion at the end
Insertion at the given position
2. Deletion
Delete the first node
Delete the last node
Delete the node from any position
3. Searching
Insertion in the circular linked list
Insertion is a fundamental operation in linked lists that involves adding a new node to the
list. The only extra step is connecting the last node to the first one. In the circular linked
list mentioned below, we can insert nodes in four ways:
1. Insertion in an empty List in the circular linked list
To insert a node in empty circular linked list, creates a new node with the given data, sets
its next pointer to point to itself, and updates the last pointer to reference this new node.
Stack follows LIFO (Last In First Out) Principle so the element which is pushed last is
popped first.
Types of Stack:
Fixed Size Stack : As the name suggests, a fixed size stack has a fixed size and
cannot grow or shrink dynamically. If the stack is full and an attempt is made to add
an element to it, an overflow error occurs. If the stack is empty and an attempt is
made to remove an element from it, an underflow error occurs.
Dynamic Size Stack : A dynamic size stack can grow or shrink dynamically. When
the stack is full, it automatically increases its size to accommodate the new element,
and when the stack is empty, it decreases its size. This type of stack is implemented
using a linked list, as it allows for easy resizing of the stack.
In order to make manipulations in a stack, there are certain operations provided to us.
push() to insert an element into the stack
pop() to remove an element from the stack
top() Returns the top element of the stack.
isEmpty() returns true if stack is empty else false.
isFull() returns true if the stack is full else false.
To implement stack, we need to maintain reference to the top item.
Push Operation on Stack
Adds an item to the stack. If the stack is full, then it is said to be an Overflow condition.
Algorithm for Push Operation:
Before pushing the element to the stack, we check if the stack is full .
If the stack is full (top == capacity-1) , then Stack Overflows and we cannot insert
the element to the stack.
Otherwise, we increment the value of top by 1 (top = top + 1) and the new value is
inserted at top position.
The elements can be pushed into the stack till we reach the capacity of the stack.
To implement a stack using an array, initialize an array and treat its end as the stack’s top.
Implement push (add to end), pop (remove from end), and peek (check end) operations,
handling cases for an empty or full stack.
Step-by-step approach:
1. Initialize an array to represent the stack.
2. Use the end of the array to represent the top of the stack.
3. Implement push (add to end), pop (remove from the end), and peek (check end)
operations, ensuring to handle empty and full stack conditions.
IMPLEMENTATION OF STACK USING ARRAYS
Here are the following operations of implement stack using array:
Push Operation in Stack:
Adds an item to the stack. If the stack is full, then it is said to be an Overflow condition.
Algorithm for Push Operation:
Before pushing the element to the stack, we check if the stack is full .
If the stack is full (top == capacity-1) , then Stack Overflows and we cannot insert
the element to the stack.
Otherwise, we increment the value of top by 1 (top = top + 1) and the new value is
inserted at top position .
The elements can be pushed into the stack till we reach the capacity of the stack.
Easy to implement.
Memory is saved as pointers are not involved.
It is not dynamic i.e., it doesn’t grow and shrink depending on needs at runtime. [But
in case of dynamic sized arrays like vector in C++, list in Python, ArrayList in Java,
stacks can grow and shrink with array implementation as well].
The total size of the stack must be defined beforehand.
IMPLEMENTATION OF STACK USING LINKED LIST
Stack is a linear data structure that follows the Last-In-First-Out (LIFO) order of
operations. This means the last element added to the stack will be the first one to be
removed. There are different ways using which we can implement stack data structure in
C.
In this article, we will learn how to implement a stack using a linked list in C, its basic
operation along with their time and space complexity analysis.
Implementation of Stack using Linked List in C
Stack is generally implemented using an array but the limitation of this kind of stack is
that the memory occupied by the array is fixed no matter what are the number of elements
in the stack. In the stack implemented using linked list implementation, the size occupied
by the linked list will be equal to the number of elements in the stack. Moreover, its size is
dynamic. It means that the size is gonna change automatically according to the elements
present.