K.B.
SAI SAMPATH
(VU21BTEN0100030)
S.NO TOPIC PAGE NO
1 1. Search for an
Element in a Singly
(Easy Level Programming Linked List 3-6
Tasks)
2. Check if a Linked
List is Empty
6-9
2 1. Delete a Node
Without Head
(Medium Level Pointer 9-12
Programming Task)
3 1. Reverse a Linked
(Hard Level Programming List in Groups of K
Task) 12-15
ASSIGNMENT – 4
Linked Lists:
Easy Level Programming Tasks
1. Search for an Element in a Singly Linked List
o Problem Description: Write a program to search for a given element in a
linked list.
o Input: A linked list: 1 -> 2 -> 3 -> 4 -> 5 and the element to search: 3
o Expected Output: True
Algorithm:
1. Initialize the Current Node: Start with the head of the linked list.
2. Traverse the Linked List:
o Check if the current node's value matches the target element.
o If it matches, return True.
o Otherwise, move to the next node in the list.
3. End of List:
o If you reach the end of the list (current node is None), return False, indicating
the element is not found.
# Define the Node class
class Node:
def __init__(self, data):
self.data = data
self.next = None
# Define the LinkedList class
class LinkedList:
def __init__(self):
self.head = None
# Method to add a new node to the list
def append(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
current = self.head
while current.next:
current = current.next
current.next = new_node
# Method to search for an element in the list
def search(self, target):
current = self.head
while current:
if current.data == target:
return True
current = current.next
return False
# Example usage
linked_list = LinkedList()
for value in [1, 2, 3, 4, 5]:
linked_list.append(value)
# Search for the element
element_to_search = 3
print(linked_list.search(element_to_search)) # Output: True
OUTPUT:
2. Check if a Linked List is Empty
o Problem Description: Write a program to check whether a given linked list is
empty or not.
o Input: A linked list: None
o Expected Output: True
Algorithm to Check if a Linked List is Empty:
1. Initialize:
o Start by accessing the head of the linked list.
o The head is the first node of the list. If the list is empty, this will be None.
2. Check if the head is None:
o If the head is None, it means the linked list is empty because there are no
nodes in the list.
Return True (the list is empty).
o If the head is not None, it means there are one or more nodes in the list.
Return False (the list is not empty).
3. End:
o The check is complete. If the head is None, the list is empty. Otherwise, it
contains at least one node.
CODE:
# Step 1: Define the Node class
class Node:
def __init__(self, data):
self.data = data # Store the value of the node
self.next = None # Initialize next as None (next node is not set yet)
# Step 2: Define the LinkedList class
class LinkedList:
def __init__(self):
self.head = None # Initially, the linked list is empty (head is None)
# Function to check if the linked list is empty
def is_empty(self):
# Step 1: Check if the head is None (list is empty)
if self.head is None:
return True # The list is empty
else:
return False # The list is not empty
# Function to append a new node to the linked list
def append(self, data):
new_node = Node(data) # Create a new node with the given data
if not self.head:
self.head = new_node # If the list is empty, make the new node the head
else:
current = self.head
while current.next: # Traverse until we find the last node
current = current.next
current.next = new_node # Add the new node at the end
# Function to print the linked list
def print_list(self):
current = self.head
while current:
print(current.data, end=" -> ") # Print the current node's data
current = current.next # Move to the next node
print("None") # Indicate the end of the list
# Driver code to test the functionality
if __name__ == "__main__":
ll = LinkedList() # Create an empty linked list
# Step 3: Check if the linked list is empty
print("Is the linked list empty?", ll.is_empty()) # Should print True
# Add some nodes to the linked list
ll.append(10)
ll.append(20)
# Check if the linked list is empty again after adding elements
print("Is the linked list empty?", ll.is_empty()) # Should print False
# Print the linked list
ll.print_list() # Should print: 10 -> 20 -> None
Output :
Medium Level Programming Tasks:
2. Delete a Node Without Head Pointer
o Problem Description: Given access to only a node to be deleted in a linked
list (not the head), delete the node.
o Input: A linked list: 4 -> 5 -> 1 -> 9 and the node 5 to delete.
o Expected Output: 4 -> 1 -> 9
Algorithm:
1. Check if the node is not the last node:
o We cannot delete the last node if we only have access to it. This algorithm
works only if the node is not the last node in the list.
2. Copy the data from the next node to the current node:
o Replace the data in the current node with the data from the next node.
3. Update the next pointer:
o Set the next pointer of the current node to point to the next node’s next node.
4. The node is deleted:
o By copying the next node’s data and bypassing the next node, we have
effectively "deleted" the current node and removed it from the list.
5. End:
o The node is deleted from the linked list.
CODE:
# Step 1: Define the Node class
class Node:
def __init__(self, data):
self.data = data # Store the value of the node
self.next = None # Initialize the next pointer as None
# Step 2: Define the LinkedList class
class LinkedList:
def __init__(self):
self.head = None # Initially, the linked list is empty
# Function to append a new node to the linked list
def append(self, data):
new_node = Node(data) # Create a new node with the given data
if not self.head:
self.head = new_node # If the list is empty, make the new node the head
else:
current = self.head
while current.next: # Traverse until we find the last node
current = current.next
current.next = new_node # Add the new node at the end
# Function to print the linked list
def print_list(self):
current = self.head
while current:
print(current.data, end=" -> ") # Print the current node's data
current = current.next # Move to the next node
print("None") # Indicate the end of the list
# Function to delete a node (without head pointer)
def delete_node(self, node):
# Step 1: Check if the node is not the last one
if node is not None and node.next is not None:
node.data = node.next.data # Step 2: Copy the next node's data to the current node
node.next = node.next.next # Step 3: Bypass the next node
# Driver code to test the functionality
if __name__ == "__main__":
ll = LinkedList() # Create an empty linked list
# Append some nodes to the linked list
ll.append(4)
ll.append(5)
ll.append(1)
ll.append(9)
print("Original Linked List:")
ll.print_list() # Should print: 4 -> 5 -> 1 -> 9 -> None
# Suppose we are asked to delete the node with value 5
node_to_delete = ll.head.next # This is the node with value 5
# Delete the node with value 5
ll.delete_node(node_to_delete)
print("Linked List after deleting node 5:")
ll.print_list() # Should print: 4 -> 1 -> 9 -> None
OUTPUT:
Hard Level Programming Tasks:
2. Reverse a Linked List in Groups of K
o Problem Description: Reverse the nodes of a linked list in groups of size K.
o Input:
o List: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
o K: 3
o Expected Output: 3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 8 -> 7
Algorithm:
1. Define the Problem Constraints:
o If there are fewer than K nodes left in the list, do not reverse them.
o If there are exactly K nodes or more in the current segment, reverse that
segment.
2. Reverse a Sublist of K nodes:
o Given the current head of a sublist, reverse it using the standard method of
altering the next pointers.
o Once the sublist is reversed, reconnect it with the rest of the list.
3. Break Down the Process:
oUse a dummy node: To handle edge cases, such as when the head of the list
changes after the first group reversal, we use a dummy node. This dummy
node will simplify managing the head of the list.
o Group-wise Reversal: Process the list in chunks of K nodes. For each chunk,
reverse the K nodes, and then reconnect them properly.
4. Reconnection after Reversal:
o After reversing a group, the last node of that group should point to the
remaining list, and the previous group should be connected to the first node of
the reversed group.
CODE:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverseKGroup(head, k):
# Step 1: Check if the list is empty or if K is 1 (no reversal needed)
if not head or k == 1:
return head
# Step 2: Create a dummy node to simplify edge cases (e.g., if the head of the list changes)
dummy = ListNode(0)
dummy.next = head
prev_group_end = dummy # This will point to the node before the current group to
reverse
# Step 3: Traverse the list in groups of K nodes
current = head
while current:
# Step 3a: Find the Kth node in the current group
group_end = current
for _ in range(k - 1):
group_end = group_end.next
if not group_end: # If there are less than K nodes remaining, no need to reverse
return dummy.next
# Step 3b: Save the next node after the current group
next_group_start = group_end.next
# Step 3c: Reverse the current group
prev, curr = None, current
while curr != next_group_start:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
# Step 3d: Connect the reversed group to the rest of the list
prev_group_end.next = prev
current.next = next_group_start
# Step 3e: Move prev_group_end to the end of the reversed group
prev_group_end = current
current = next_group_start # Move to the next group
# Return the new head of the list (dummy.next points to the new head)
return dummy.next
# Helper function to print the linked list
def print_linked_list(head):
while head:
print(head.val, end=" -> " if head.next else "")
head = head.next
print()
# Example usage:
# Constructing the linked list: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
head.next.next.next.next = ListNode(5)
head.next.next.next.next.next = ListNode(6)
head.next.next.next.next.next.next = ListNode(7)
head.next.next.next.next.next.next.next = ListNode(8)
k=3
print("Original List:")
print_linked_list(head)
# Reverse the linked list in groups of k
new_head = reverseKGroup(head, k)
print(f"List after reversing in groups of {k}:")
print_linked_list(new_head)
OUTPUT :