0% found this document useful (0 votes)
23 views

FDS Unit 4 Notes

FDS Notes Unit 4

Uploaded by

artkatta468
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

FDS Unit 4 Notes

FDS Notes Unit 4

Uploaded by

artkatta468
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

1|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

Unit – IV
Linked List
Introduction to Static and Dynamic Memory Allocation

In programming, memory allocation refers to reserving memory space for data storage during
the execution of a program. There are two main types:

1. Static Memory Allocation:

o Memory is allocated at compile-time, meaning the size and type of data must be known
before the program runs.

o This allocation is usually managed by the compiler, and variables are stored in the stack.

o Since the memory size is fixed, static allocation is faster but less flexible.

o Examples: Global and local variables in languages like C and C++.

2. Dynamic Memory Allocation:

o Memory is allocated at runtime, allowing for flexibility in memory size as the program
requires.

o This allocation is handled on the heap, and the program can request and release memory
as needed.

o Functions like malloc and free in C or new and delete in C++ are used for dynamic
allocation.

o Dynamic allocation is slower but offers better memory management for variable data
sizes.

1. Linked List
A linked list is a linear data structure which can store a collection of "nodes" connected together
via links i.e. pointers. Linked lists nodes are not stored at a contiguous location, rather they are
linked using pointers to the different memory locations. A node consists of the data value and
a pointer to the address of the next node within the linked list.
2|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

A linked list is a dynamic linear data structure whose memory size can be allocated or de-
allocated at run time based on the operation insertion or deletion, this helps in using system
memory efficiently. Linked lists can be used to implement various data structures like a stack,
queue, graph, hash maps, etc.

A linked list starts with a head node which points to the first node. Every node consists of data
which holds the actual data (value) associated with the node and a next pointer which holds the
memory address of the next node in the linked list. The last node is called the tail node in the
list which points to null indicating the end of the list.

Linked Lists vs Arrays

In case of arrays, the size is given at the time of creation and so arrays are of fixed length
whereas Linked lists are dynamic in size and any number of nodes can be added in the linked
lists dynamically. An array can accommodate similar types of data types whereas linked lists
can store various nodes of different data types.

Dynamic Data Structure

A dynamic data structure is a data structure that can grow, shrink, or change in size during
program execution. Unlike static data structures (e.g., arrays), which have a fixed size
determined at compile-time, dynamic data structures can adjust their size based on the
program's needs, thanks to dynamic memory allocation.

Key features of dynamic data structures include:

1. Flexible Size: They can expand or contract as elements are added or removed,
providing efficient use of memory.

2. Efficient Memory Use: Memory is allocated only when needed, which helps manage
memory more effectively.

3. Pointer-Based Implementation: They often use pointers to link elements or nodes, as


seen in linked lists, trees, and graphs.

1.1 Operations
3|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

The basic operations in the linked lists are insertion, deletion, searching, sorting, traversing,
finding length, concatenating, and deleting an element at a given key.

1. Creation:

o Initializes an empty linked list.

o Sets the head (and optionally tail) to NULL, preparing the list to add nodes.

o The first step before performing any other operation on the list.

2. Insertion:

o Adds a new node to the list.

o Can occur at the beginning (head), at the end (tail), or at a specified position within the
list.

o Requires adjusting pointers to maintain the link between nodes.

3. Deletion:

o Removes a node from the list.

o Can delete from the beginning, end, or a specified position.

o Pointers need to be updated to maintain the structure, and memory for the deleted node
should be freed.

4. Traversal:

o Accesses each node in the list sequentially, usually starting from the head.

o Used to search for elements, print the list, or perform operations on each element.

5. Search:

o Finds whether a particular element exists in the list.

o Involves traversing the list until the element is found or the end of the list is reached.

6. Finding Length:

 Calculates the number of nodes in the list.

 Typically involves traversing through each node and counting until the end of the list.
4|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

7. Concatenation:

 Combines two linked lists into a single list.

 Involves linking the end of the first list to the head of the second list.

8. Sorting:
 Arranges the nodes in the list in a specific order, such as ascending or descending.
 Common sorting algorithms for linked lists include bubble sort, merge sort, and
insertion sort, with adjustments to handle pointers rather than indices.

1.2 Linked List as ADT

The data is generally stored in key sequence in a list which has a head structure consisting
of count, pointers and address of compare function needed to compare the data in the list.

The data node contains the pointer to a data structure and a self-referential pointer which points
to the next node in the list.

The List ADT Functions are given below:

 get() – Return an element from the list at any given position.

 insert() – Insert an element at any position of the list.

 remove() – Remove the first occurrence of any element from a non-empty list.

 removeAt() – Remove the element at a specified location from a non-empty list.

 replace() – Replace an element at any position by another element.

 size() – Return the number of elements in the list.

 isEmpty() – Return true if the list is empty, otherwise return false.

 isFull() – Return true if the list is full, otherwise return false.

2. Types of Linked List

2.1 Singly Linked List

A singly linked list is a fundamental data structure in computer science and programming, it
consists of nodes where each node contains a data field and a reference to the next node in
the node. The last node points to null, indicating the end of the list. This linear structure
5|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

supports efficient insertion and deletion operations, making it widely used in various
applications.

Node Structure

In a singly linked list, each node consists of two parts: data and a pointer to the next node. The
data part stores the actual information, while the pointer (or reference) part stores the address
of the next node in the sequence. This structure allows nodes to be dynamically linked together,
forming a chain-like sequence.

In this representation, each box represents a node, with an arrow indicating the link to the next
node. The last node points to NULL, indicating the end of the list.

Syntax to Declare a Singly Linked List:

struct Node {
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {} // Constructor
//for node
};
Opera ons on Singly Linked List

1. Creation of a Singly Linked List

Creating a Singly Linked List involves initializing an empty list and then adding nodes to it
as needed. The list starts with head set to nullptr, indicating it’s empty. Nodes can be added
at the beginning, end, or any specific position to build the list progressively.

struct Node {
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {} // Constructor
6|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

//for node
};

void createList(Node*& head, int values[], int size) {


head = nullptr; // Initialize the head to nullptr
Node* current = nullptr;

for (int i = 0; i < size; i++) {


Node* newNode = new Node(values[i]); // Create a new node with
//each value
if (head == nullptr) { // If list is empty, set head to new
//node
head = newNode;
current = head;
} else { // Else add new node to the end
current->next = newNode;
current = newNode;
}
}
}
2. Traversal in Singly Linked List

Traversal in a Singly Linked List involves visiting each node in the list, typically starting
from the head node and moving through each node sequentially until reaching the end (where
the next pointer is nullptr). This operation is commonly used to display node values, search
for specific data, or perform any action on each element of the list.

void traverse(Node* head) {

Node* current = head; // Start with the head node

while (current != nullptr) { // Continue until the end of the list

cout << current->data << " "; // Process the current node

current = current->next; // Move to the next node


7|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

3. Searching in Singly Linked List

Searching in a Singly Linked List involves traversing the list from the head to find a node
containing a specific value. The process continues until the value is found or the end of the list
is reached. This linear search is efficient for small lists, but since a singly linked list requires
sequential access, it can be slower for larger lists.

bool search(Node* head, int target) {


Node* current = head; // Start with the head node
while (current != nullptr) { // Traverse until the end of the list
if (current->data == target) { // Check if current node
//contains the target
return true; // Target found
}
current = current->next; // Move to the next node
}
return false; // Target not found in the list
}
4. Finding length of a Singly Linked List

Finding the Length in a Singly Linked List involves traversing the list from the head and
counting each node until reaching the end. This process provides the total number of nodes in
the list.

int findLength(Node* head) {


int count = 0; // Initialize count to zero
Node* current = head; // Start with the head node
while (current != nullptr) { // Traverse until the end of the list
count++; // Increment count for each node
current = current->next; // Move to the next node
}
return count; // Return the total count as the length of the list
8|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
5. Insertion in Singly Linked List

Insertion in a Singly Linked List involves adding a new node at a specified position—
typically at the beginning, at the end, or at a specific index within the list. Each insertion
requires adjusting pointers to ensure the list remains properly linked.

Types of Insertion

a. Insertion at the Beginning: It involves adding a new node as the first element in the list.
This is done by setting the new node's next pointer to the current head node and then updating
the head to point to the new node. This operation is efficient since it requires only a few pointer
adjustments.

void insertAtBeginning(Node*& head, int data) {


Node* newNode = new Node(data); // Create a new node with the
//given data
newNode->next = head; // Point new node to the current head
head = newNode; // Update head to the new node
}
b. Insertion at the End: It involves adding a new node as the last element. This requires
traversing the list to reach the last node, then setting its next pointer to the new node, and
setting the new node's next to nullptr, indicating the end of the list.
9|Page © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

void insertAtEnd(Node*& head, int data) {


Node* newNode = new Node(data); // Create a new node with the
//given data
newNode->next = nullptr; // Set new node's next to nullptr

if (head == nullptr) { // If the list is empty, new node becomes


//the head
head = newNode;
return;
}

Node* current = head; // Start at the head node


while (current->next != nullptr) { // Traverse to the last node
current = current->next;
}
current->next = newNode; // Link the last node to the new node
}
c. Insertion at a Specific Position: It involves placing a new node at a given index within the
list. We first traverse the list to find the node just before the desired position, then adjust
pointers to insert the new node.
10 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

void insertAtPosition(Node*& head, int data, int position) {


Node* newNode = new Node(data); // Create a new node with the
//given data

if (position == 0) { // Insert at the beginning


newNode->next = head;
head = newNode;
return;
}

Node* current = head;


for (int i = 0; i < position - 1 && current != nullptr; i++) {
//Traverse to node before position
current = current->next;
}

if (current == nullptr) { // Position is out of bounds


delete newNode; // Free allocated memory
return;
}

newNode->next = current->next; // Link new node to next node


current->next = newNode; // Link previous node to new node
}
6. Deletion in Singly Linked List
11 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

Deletion involves removing a node from the linked list. Similar to insertion, there are different
scenarios for deletion:

a. Deletion at the Beginning: It involves removing the first node (head node) from the list.
This is done by updating the head pointer to the next node in the list, then freeing the memory
of the removed node.

void deleteAtBeginning(Node*& head) {


if (head == nullptr) { // Check if the list is empty
return;
}

Node* temp = head; // Store the current head node


head = head->next; // Update head to the next node
delete temp; // Free memory of the old head node
}
b. Deletion at the End: It involves removing the last node. This is done by traversing the list
to the second-to-last node, updating its next pointer to nullptr, and then freeing the memory
of the last node.
12 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

void deleteAtEnd(Node*& head) {


if (head == nullptr) { // Check if the list is empty
return;
}

if (head->next == nullptr) { // Only one node in the list


delete head;
head = nullptr;
return;
}

Node* current = head;


while (current->next->next != nullptr) {
// Traverse to the second-to-last node
current = current->next;
}

delete current->next; // Delete the last node


current->next = nullptr; // Update second-to-last node's next to
//nullptr
}
c. Deletion at a specific position: It involves removing a node at a given index. We first
traverse the list to reach the node just before the target position, then adjust pointers to bypass
the node to be deleted.

void deleteAtPosition(Node*& head, int position) {


13 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

if (head == nullptr || position < 0) { // Check if the list is


//empty or position is invalid
return;
}

if (position == 0) { // Delete the head node


Node* temp = head;
head = head->next;
delete temp;
return;
}

Node* current = head;


for (int i = 0; i < position - 1 && current->next != nullptr; i++) {
// Traverse to the node before the position
current = current->next;
}

if (current->next == nullptr) { // Check if position is out of


//bounds
return;
}

Node* temp = current->next; // Node to delete


current->next = temp->next; // Bypass the node to be deleted
delete temp; // Free the memory
}
7. Sorting in Singly Linked List

Sorting in a Singly Linked List involves rearranging the nodes in a specific order, typically
in ascending or descending order based on their values. One common approach to sort a singly
14 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

linked list is to use the Bubble Sort algorithm, which repeatedly steps through the list,
compares adjacent nodes, and swaps them if they are in the wrong order.

void sortList(Node* head) {


if (head == nullptr) return; // Check if the list is empty

bool swapped;
do {
swapped = false; // Initialize swapped as false
Node* current = head; // Start from the head of the list

while (current->next != nullptr) { // Traverse the list


if (current->data > current->next->data) { // Compare
//current and next node
// Swap data if they are in the wrong order
int temp = current->data;
current->data = current->next->data;
current->next->data = temp;
swapped = true; // Set swapped to true indicating a
//swap occurred
}
current = current->next; // Move to the next node
}
} while (swapped); // Repeat until no swaps are needed
}
8. Concatenation in Singly Linked Lists

Concatenation in Singly Linked Lists involves joining two singly linked lists to form a single
list. This is achieved by linking the last node of the first list to the head of the second list. The
process is efficient since it does not require creating new nodes; instead, it simply adjusts
pointers.

void concatenate(Node*& head1, Node*& head2) {


if (head1 == nullptr) { // If the first list is empty
15 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

head1 = head2; // Set head1 to head2


return;
}
if (head2 == nullptr) { // If the second list is empty
return; // No action needed
}

Node* current = head1; // Start from the head of the first list
while (current->next != nullptr) { // Traverse to the last node
// of the first list
current = current->next;
}

current->next = head2; // Link the last node of the first list to


// the head of the second list
}
Q. Write a pseudo (C++) code for following func ons using Singly Linked List of students
(roll_number and name stored in every node)

i) Search given roll no and delete that record. Draw diagram of opera on.

ii) Add given number a er specified number in the list. Draw diagram of opera on.

Answer:

i) Search for a Given Roll Number and Delete That Record

struct StudentNode {
int roll_number;
string name;
StudentNode* next;
};

void deleteRecord (StudentNode*& head, int rollNumber) {


if (head == nullptr) { // Check if the list is empty
16 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

return; // Nothing to delete


}

// Handle the case of deleting the head node


if (head->roll_number == rollNumber) {
StudentNode* temp = head;
head = head->next; // Move head to the next node
delete temp; // Free memory of the deleted node
return;
}

// Traverse the list to find the node to delete


StudentNode* current = head;
StudentNode* previous = nullptr;

while (current != nullptr && current->roll_number != rollNumber){


previous = current;
current = current->next;
}

if (current != nullptr) { // Node found


previous->next = current->next; // Bypass the current node
delete current; // Free memory of the deleted node
}
}
Diagram of Operation:
17 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

2. Add Given Number After Specified Number in the List

void addNumber(StudentNode*& head, int sRollNumber, int nRollNumber,


string newName) {
StudentNode* newNode = new StudentNode(); // Create new node
newNode->roll_number = nRollNumber;
newNode->name = newName;
newNode->next = nullptr;

// If the list is empty


if (head == nullptr) {
head = newNode; // Make the new node the head
return;
}

// Traverse the list to find the specified roll number


StudentNode* current = head;
while (current != nullptr && current->roll_number != sRollNumber){
current = current->next;
}

if (current != nullptr) { // Specified roll number found


newNode->next = current->next; // Link new node to the next
// node
current->next = newNode; // Link current node to new node
18 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

} else {
delete newNode; // Specified roll number not found, discard
// new node
}
}
Diagram of Operation:

Q. Write pseudocode to perform merging of two sorted singly linked lists of integers into
third list. Write complexity of it.

Node* mergeSortedLists(Node* head1, Node* head2) {


Node* mergedHead = nullptr; // Head of the merged list
Node* tail = nullptr; // Pointer to build the merged list

// Initialize the merged list


if (head1 == nullptr) return head2; // If the first list is empty,
// return the second
if (head2 == nullptr) return head1; // If the second list is
// empty, return the first

// Set the head of the merged list


if (head1->data < head2->data) {
mergedHead = head1;
head1 = head1->next;
} else {
mergedHead = head2;
19 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

head2 = head2->next;
}

tail = mergedHead; // Initialize tail to the head of the merged list

// Merge the two lists


while (head1 != nullptr && head2 != nullptr) {
if (head1->data < head2->data) {
tail->next = head1; // Link to the smaller node
head1 = head1->next; // Move to the next node in the first
// list
} else {
tail->next = head2; // Link to the smaller node
head2 = head2->next; // Move to the next node in the
// second list
}
tail = tail->next; // Move the tail pointer forward
}

// Link the remaining nodes, if any


if (head1 != nullptr) {
tail->next = head1; // Link remaining nodes from the first list
} else {
tail->next = head2; // Link remaining nodes from the second list
}

return mergedHead; // Return the head of the merged list


}
Complexity
20 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

 Time Complexity: O(n + m) where n is the number of nodes in the first list and m is
the number of nodes in the second list. This is because we traverse each list exactly
once.

 Space Complexity: O(1) if we are merging in place and not using additional data
structures for the merged list. The space used for the merged list nodes is not counted
since we are merely rearranging the existing nodes without creating new ones.

2.2 Doubly Linked List

A doubly linked list is a data structure that consists of a set of nodes, each of which contains
a value and two pointers, one pointing to the previous node in the list and one pointing to
the next node in the list. This allows for efficient traversal of the list in both directions,
making it suitable for applications where frequent insertions and deletions are required.

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)

Each node in a Doubly Linked List contains the data it holds, a pointer to the next node in
the list, and a pointer to the previous node in the list. By linking these nodes together through
the next and prev pointers, we can traverse the list in both directions (forward and
backward), which is a key feature of a Doubly Linked List.
21 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

Syntax to Declare a Doubly Linked List:

struct Node {
int data;
Node* next;
Node* prev;
};
1. Creation of a Doubly Linked List: To create a doubly linked list, we link each node’s next
pointer to the following node and its prev pointer to the preceding node.

struct Node {
int data;
Node* next;
Node* prev;
};
Node* createDoublyLinkedList(int values[], int n) {
if (n == 0) return nullptr; // Empty list

// Create the first node


Node* head = new Node();
head->data = values[0];
head->next = nullptr;
head->prev = nullptr;

Node* last = head;

// Add the rest of the nodes


for (int i = 1; i < n; ++i) {
Node* newNode = new Node();
newNode->data = values[i];
newNode->next = nullptr;
newNode->prev = last;
last->next = newNode;
22 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

last = newNode; // Update last to the new node


}

return head; // Return the doubly linked list's head


}
2. Traversal in a Doubly Linked List

Traversal in a doubly linked list can occur in two directions: forward (from head to tail) and
backward (from tail to head). This is possible because each node contains pointers to both the
next and previous nodes.

1. Forward Traversal:

o Start from the head and move through each node using the next pointer until
reaching a node with next as nullptr.

2. Backward Traversal:

o Start from the tail and move back through each node using the prev pointer
until reaching a node with prev as nullptr.

// Function for forward traversal


void traverseForward(Node* head) {
Node* current = head;
while (current != nullptr) {
cout << current->data << " ";
current = current->next;
}
cout << endl;
}

// Function for backward traversal


void traverseBackward(Node* tail) {
Node* current = tail;
while (current != nullptr) {
cout << current->data << " ";
23 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

current = current->prev;
}
cout << endl;
}
3. Searching in a Doubly Linked List

Searching in a doubly linked list involves traversing the list from either the head (for a
forward search) or the tail (for a backward search) to find a node with a specified value. Since
each node in a doubly linked list has both next and prev pointers, you can search in both
directions efficiently.

// Function to search for a target value in the list


Node* search(Node* head, int target) {
Node* current = head;
while (current != nullptr) {
if (current->data == target) {
return current; // Target found
}
current = current->next; // Move to the next node
}
return nullptr; // Target not found
}
4. Finding length of a Doubly Linked List

To find the length of a doubly linked list, you need to traverse the list from the head to the
tail, counting each node until reaching the end.

int findLength(Node* head) {


int count = 0;
Node* current = head;
while (current != nullptr) {
count++; // Increment the counter for each node
current = current->next; // Move to the next node
}
return count;
24 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
5. Insertion in a Doubly Linked List:

Inserting a new node in a doubly linked list can be done at the beginning, end, or at a specified
position. When inserting, both next and prev pointers of the new node and adjacent nodes
must be updated to maintain the bidirectional links.

a. Insertion at the beginning in a doubly linked list: It involves adding a new node before
the current head node. After insertion, the new node becomes the new head of the list, and its
pointers must be updated to maintain the doubly linked structure.

void insertAtBeginning(Node*& head, int data) {


Node* newNode = new Node();
newNode->data = data;
newNode->next = head; // Point new node to the current head
newNode->prev = nullptr; // New node's prev is nullptr since it's
// now the first node

if (head != nullptr) {
head->prev = newNode; // Update the current head's prev to
// point to the new node
}
head = newNode; // Make the new node the new head of the list
}
b. Insertion at the end in a doubly linked list: It involves adding a new node after the current
last node, making it the new tail of the list. This operation requires updating the pointers of
both the new node and the previous last node.
25 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

void insertAtEnd(Node*& head, int data) {


Node* newNode = new Node();
newNode->data = data;
newNode->next = nullptr; // New node's next is nullptr since it's
// the last node

if (head == nullptr) {
newNode->prev = nullptr; // New node's prev is nullptr since
// it will be the only node
head = newNode; // Make the new node the head if list is empty
return;
}

Node* last = head;


while (last->next != nullptr) {
last = last->next; // Traverse to the last node
}

last->next = newNode; // Point the last node's next to the new node
newNode->prev = last; // Point the new node's prev to the last node
}
26 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

c. Insertion at a specific position in a doubly linked list: It involves adding a new node at a
given index, updating the pointers of both the new node and the adjacent nodes to maintain the
doubly linked structure.

// Function to insert at a specific position (0-based index)


void insertAtPosition(Node*& head, int data, int position) {
Node* newNode = new Node();
newNode->data = data;

// Insert at the beginning


if (position == 0) {
newNode->next = head;
newNode->prev = nullptr;
if (head != nullptr) {
head->prev = newNode;
}
head = newNode;
return;
}

Node* current = head;


for (int i = 0; i < position - 1 && current != nullptr; i++) {
current = current->next; // Traverse to the node before the
//desired position
}

if (current == nullptr) {
27 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// If current is null, position is out of bounds, just insert


// at end
delete newNode; // Clean up new node as we won't be using it
return;
}

// Insertion at the specified position


newNode->next = current->next; // Point new node's next to
// current's next
newNode->prev = current; // Point new node's prev to current

if (current->next != nullptr) {
current->next->prev = newNode; // Update next node's prev if
// it exists
}
current->next = newNode; // Link current's next to new node
}

6. Deletion in a Doubly Linked List

Deletion in a doubly linked list involves removing a specified node and updating the pointers
of the adjacent nodes to maintain the integrity of the list. The deletion can occur at the
beginning, end, or at a specific position.

a. Deletion in a Doubly Linked List at the beginning: It involves removing the first node
(head) of the list and updating the head pointer to point to the next node in the list.

// Function to delete the node at the beginning


void deleteAtBeginning(Node*& head) {
28 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Check if the list is empty


if (head == nullptr) {
cout << "List is empty. Nothing to delete." << endl;
return;
}

Node* temp = head; // Store the current head

// Update head to the next node


head = head->next;

// Update the new head's prev pointer if it exists


if (head != nullptr) {
head->prev = nullptr;
}

delete temp; // Free the memory of the old head node


}
b. Deletion in a Doubly Linked List at the end: It involves removing the last node (tail) of
the list and updating the pointers of the previous node to maintain the integrity of the list.

// Function to delete the node at the end


void deleteAtEnd(Node*& head) {
// Check if the list is empty
if (head == nullptr) {
cout << "List is empty. Nothing to delete." << endl;
return;
29 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

Node* last = head;

// Traverse to the last node


while (last->next != nullptr) {
last = last->next;
}

// If the list has only one node


if (last == head) {
head = nullptr; // Update head to nullptr
} else {
// Update the previous node's next pointer
last->prev->next = nullptr;
}

delete last; // Free the memory of the last node


}
c. Deletion in a Doubly Linked List at a specific position: It involves removing a node at a
given index and updating the pointers of the adjacent nodes to maintain the integrity of the list.

// Function to delete a node at a specific position (0-based index)


void deleteAtPosition(Node*& head, int position) {
// Check if the list is empty
if (head == nullptr) {
cout << "List is empty. Nothing to delete." << endl;
30 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

return;
}

Node* current = head;

// If the position is 0, delete the head node


if (position == 0) {
head = current->next; // Update head to the next node
if (head != nullptr) {
head->prev = nullptr; // Update the new head's prev
// pointer
}
delete current; // Free the memory of the old head node
return;
}

// Traverse to the desired position


for (int i = 0; i < position && current != nullptr; i++) {
current = current->next; // Move to the next node
}

// If the current is nullptr, the position is out of bounds


if (current == nullptr) {
cout << "Position out of bounds. Nothing to delete." <<
endl;
return;
}

// Update pointers to delete the current node


if (current->prev != nullptr) {
current->prev->next = current->next; // Link previous node
// to the next node
31 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
if (current->next != nullptr) {
current->next->prev = current->prev; // Link next node back
// to the previous node
}

delete current; // Free the memory of the node being deleted


}
7. Sorting in a Doubly Linked List:

Sorting a doubly linked list at a specific position with bubble sort involves repeatedly
swapping adjacent nodes if they are out of order, working only within a sublist defined by the
specific range. This can be useful when you need to sort only a part of the list rather than the
entire structure.

void bubbleSortRange(Node* start, int rangeLength) {


if (!start || rangeLength <= 1) return;

for (int i = 0; i < rangeLength - 1; ++i) {


Node* current = start;
Node* nextNode = start->next;

for (int j = 0; j < rangeLength - i - 1 && nextNode != nullptr; ++j){

if (current->data > nextNode->data) {


// Swap the data of the current node and the next node
int temp = current->data;
current->data = nextNode->data;
nextNode->data = temp;
}
// Move to the next pair
current = nextNode;
nextNode = nextNode->next;
}
32 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
}
8. Concatenation of Doubly Linked Lists:

Concatenation of doubly linked lists involves combining two doubly linked lists into a single
list. This operation requires adjusting the pointers of the last node of the first list and the head
of the second list so that they connect seamlessly.

// Function to concatenate two doubly linked lists


void concatenate(Node*& head1, Node*& head2) {
// Check if the first list is empty
if (head1 == nullptr) {
head1 = head2; // If head1 is empty, point to head2
return;
}

// Check if the second list is empty


if (head2 == nullptr) {
return; // Nothing to do if head2 is empty
}

// Find the last node of the first list


Node* last = head1;
while (last->next != nullptr) {
last = last->next;
}

// Link the last node of the first list to the head of the second list
last->next = head2;
head2->prev = last; // Link the head of the second list back to
// the last node of the first list
}
2.3 Circular Linked List
33 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

A circular linked list is a data structure where the last node connects back to the first, forming
a loop. This structure allows for continuous traversal without any interruptions. Circular linked
lists are especially helpful for tasks like scheduling and managing playlists, thus allowing for
smooth navigation.

In Circular Singly Linked List, each node has just one pointer called the “next” pointer. The
next pointer of last node points back to the first node and this results in forming a circle. In
this type of Linked list, we can only move through the list in one direction.

Representation of a Circular Singly Linked List

Syntax to Declare a Circular Linked List:

struct Node {
int data;
Node* next;

Node(int value){
data = value;
next = nullptr;
}
};
1. Creation of a Circular Linked List:

Creation of a circular linked list involves creating a linked list in which the last node points
back to the first node, forming a circle. This structure allows for continuous traversal of the list
without needing to keep track of the end.

// Function to create a circular linked list with n nodes


34 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

Node* createCircularLinkedList(int n) {
if (n <= 0) {
return nullptr; // Return null if the number of nodes is non-
positive
}

Node* head = new Node(); // Create the first node


head->data = 1;
head->next = head; // Point to itself to form a circular link

Node* current = head;

for (int i = 2; i <= n; i++) {


Node* newNode = new Node(); // Create a new node
newNode->data = i;
newNode->next = head; // Link new node to head (to make it
// circular)

current->next = newNode; // Link current node to the new node


current = newNode; // Move current to the new node
}

return head; // Return the head of the circular linked list


}
2. Traversal in a Circular Linked List:

Traversal in a circular linked list involves visiting each node in the list starting from a given
node (usually the head) and continuing until you return to the starting node. Because of the
circular structure, it is important to avoid infinite loops by keeping track of when you return to
the starting point.

// Function to traverse and print the elements of a circular linked list


void traverseCircularLinkedList(Node* head) {
if (head == nullptr) {
35 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

cout << "The circular linked list is empty." << endl;


return;
}

Node* current = head; // Start from the head node

do {
cout << current->data << " "; // Print current node's data
current = current->next; // Move to the next node
} while (current != head); // Stop when we reach the head again

cout << endl; // Print a new line after traversal


}
3. Finding Length of a Circular Linked List:

Finding the length of a circular linked list involves counting the number of nodes in the list.
Since the list is circular, a specific method is used to ensure that the traversal stops after visiting
all nodes without getting stuck in an infinite loop.

// Function to find the length of a circular linked list


int findLengthOfCircularLinkedList(Node* head) {
if (head == nullptr) {
return 0; // Length is zero if the list is empty
}

int count = 0; // Initialize counter


Node* current = head; // Start from the head node

do {
count++; // Increment count for each node visited
current = current->next; // Move to the next node
} while (current != head); // Stop when we reach the head again
36 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

return count; // Return the total count


}
4. Searching in a Circular Linked List:

Searching in a circular linked list involves traversing the list to find a node that contains a
specific value. Since the list is circular, care must be taken to avoid infinite loops during
traversal.

// Function to search for a value in a circular linked list


Node* searchInCircularLinkedList(Node* head, int target) {
if (head == nullptr) {
return nullptr; // Return null if the list is empty
}

Node* current = head; // Start from the head node

do {
if (current->data == target) {
return current; // Return the node if found
}
current = current->next; // Move to the next node
} while (current != head); // Stop when we reach the head again

return nullptr; // Return null if the target is not found


}
5. Insertion in a Circular Linked List

Insertion in a circular linked list involves adding a new node to the list at a specified position.
This can be done in three main scenarios: inserting at the beginning, at the end, or at a specific
position in the list.

a. Insertion in a Circular Linked List at the beginning: It involves adding a new node as
the new head of the list. Since the list is circular, the last node should continue to point to the
head, and this needs to be updated to accommodate the new node.
37 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Function to insert a node at the beginning of a circular linked list


void insertAtBeginning(Node*& head, int newValue) {
Node* newNode = new Node(newValue); // Create a new node

if (head == nullptr) {
// If the list is empty, make the new node point to itself
head = newNode;
newNode->next = head;
} else {
// Find the last node
Node* last = head;
while (last->next != head) {
last = last->next;
}

// Insert the new node at the beginning


newNode->next = head; // New node points to current head
last->next = newNode; // Last node points to new node
head = newNode; // Update head to the new node
}
}
b. Insertion in a Circular Linked List at the end: It involves adding a new node after the
current last node, making it the new last node. In a circular linked list, the new node should
point back to the head to maintain the circular structure.
38 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Function to insert a node at the end of a circular linked list


void insertAtEnd(Node*& head, int newValue) {
Node* newNode = new Node(newValue); // Create a new node

if (head == nullptr) {
// If the list is empty, make the new node point to itself
head = newNode;
newNode->next = head;
} else {
// Find the last node
Node* last = head;
while (last->next != head) {
last = last->next;
}

// Insert the new node at the end


last->next = newNode; // Last node points to new node
newNode->next = head; // New node points to head
}
}
c. Insertion in a Circular Linked List at a specific position: It involves adding a new node
at a particular index in the list. The circular structure of the list must be maintained, so the
inserted node’s next pointer must correctly link back to the rest of the list.
39 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Function to insert a node at a specific position in a circular linked list

void insertAtPosition(Node*& head, int newValue, int position) {


Node* newNode = new Node(newValue); // Create a new node

if (position == 0) {
// Insert at the beginning
if (head == nullptr) {
head = newNode;
newNode->next = head; // Point to itself
} else {
// Find the last node to update its next pointer
Node* last = head;
while (last->next != head) {
last = last->next;
}

newNode->next = head; // New node points to current head


last->next = newNode; // Last node points to new node
head = newNode; // Update head to new node
}
} else {
// Traverse to the node just before the desired position
Node* current = head;
for (int i = 0; i < position - 1 && current->next != head; ++i) {
current = current->next;
}
40 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Insert the new node at the specified position


newNode->next = current->next; // New node points to next node
// in sequence
current->next = newNode; // Current node points to new node
}
}
6. Deletion of a Circular Linked List:

Deletion involves removing a node from the linked list. The main difference is that we need to
ensure the list remains circular after the deletion. We can delete a node in a circular linked list
in three ways:

a. Deletion in a Circular Linked List at the beginning: It involves removing the head node
while maintaining the circular structure. The next pointer of the last node needs to be updated
to point to the new head after deletion.

// Function to delete the first node in a circular linked list


void deleteAtBeginning(Node*& head) {
if (head == nullptr) return; // List is empty, nothing to delete

Node* temp = head;

// Case 1: Only one node in the list


if (head->next == head) {
delete head;
head = nullptr;
} else {
// Find the last node
Node* last = head;
41 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

while (last->next != head) {


last = last->next;
}

// Update last node's next to new head, which is head->next


last->next = head->next;
head = head->next; // Update head to the next node
delete temp; // Delete old head node
}
}
b. Deletion in a Circular Linked List at the end:

It involves removing the last node in the list while maintaining the circular structure. The next
pointer of the second-to-last node must be updated to point back to the head after deletion.

// Function to delete the last node in a circular linked list


void deleteAtEnd(Node*& head) {
if (head == nullptr) return; // List is empty, nothing to delete

// Case 1: Only one node in the list


if (head->next == head) {
delete head;
head = nullptr;
} else {
// Traverse to the second-to-last node
Node* temp = head;
while (temp->next->next != head) {
temp = temp->next;
42 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Now temp points to the second-to-last node, and temp->next


// is the last node
Node* lastNode = temp->next;
temp->next = head; // Update second-to-last node's next to
// point to head
delete lastNode; // Delete the last node
}
}
c. Deletion in a Circular Linked List at a specific position:

It involves removing a node at the given position while maintaining the circular structure of
the list. After deletion, the next pointers must be adjusted to keep the list circular.

// Function to delete a node at a specific position in a circular linked list

void deleteAtPosition(Node*& head, int position) {


if (head == nullptr) return; // List is empty, nothing to delete

Node* temp = head;

// Case 1: Deleting the head node


if (position == 0) {
// If there's only one node
if (head->next == head) {
delete head;
head = nullptr;
} else {
43 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Find the last node


Node* last = head;
while (last->next != head) {
last = last->next;
}
// Update last node's next to the new head (head->next)
last->next = head->next;
head = head->next;
delete temp; // Delete old head node
}
} else {
// Traverse to the node just before the target position
Node* prev = nullptr;
for (int i = 0; i < position && temp->next != head; ++i) {
prev = temp;
temp = temp->next;
}

// If position is valid
if (temp->next != head || position == 0) {
prev->next = temp->next; // Bypass the node to delete
delete temp;
}
}
}
7. Sorting in a Circular Linked List:

Sorting in a circular linked list involves arranging the nodes in ascending or descending order
based on their values. Since a circular linked list does not have a natural "end," care must be
taken during the sorting process to ensure that the entire list is sorted without causing an infinite
loop.

Common Sorting Algorithm


44 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

One common method to sort a circular linked list is to use the Bubble Sort algorithm. Bubble
Sort repeatedly steps through the list, compares adjacent nodes, and swaps them if they are in
the wrong order. This process is repeated until no more swaps are needed.

// Function to sort a circular linked list using Bubble Sort


void sortCircularLinkedList(Node* head) {
if (head == nullptr) {
return; // No need to sort if the list is empty
}

bool swapped;
Node* current;
Node* nextNode = nullptr;

// Bubble Sort
do {
swapped = false;
current = head;

do {
nextNode = current->next; // Get the next node

// Compare and swap values if they are in the wrong order


if (current->data > nextNode->data) {
swap(current->data, nextNode->data); // Swap values
swapped = true; // Set swapped to true
}
current = nextNode; // Move to the next node
} while (current != head); // Continue until we loop back to
// the head

} while (swapped); // Repeat until no swaps are made


45 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
8. Concatenation of Circular Linked Lists:

Concatenation of circular linked lists involves combining two circular linked lists into a
single circular linked list. This process ensures that the resulting list maintains its circular
property.

// Function to concatenate two circular linked lists


Node* concatenateCircularLinkedLists(Node* head1, Node* head2) {
if (head1 == nullptr) {
return head2; // If the first list is empty, return the second
// list
}
if (head2 == nullptr) {
return head1; // If the second list is empty, return the first
// list
}

// Find the last node of the first list


Node* last1 = head1;
while (last1->next != head1) {
last1 = last1->next;
}

// Find the last node of the second list


Node* last2 = head2;
while (last2->next != head2) {
last2 = last2->next;
}

// Link the last node of the first list to the head of the second list
last1->next = head2;
// Link the last node of the second list to the head of the first list
46 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

last2->next = head1;

// Return the head of the concatenated list


return head1;
}
2.4 Doubly Circular Linked List

In circular doubly linked list, each node has two pointers prev and next, similar to doubly
linked list. The prev pointer points to the previous node and the next points to the next node.
Here, in addition to the last node storing the address of the first node, the first node will also
store the address of the last node.

Syntax to Declare a Circular Linked List:

struct Node {
int data;
Node* next;

Node(int value){
data = value;
next = nullptr;
}
};
2.5 Advantages of Doubly Linked List Over Singly Linked List

1. Bidirectional Traversal:

o Doubly linked lists allow traversal in both forward and backward directions,
thanks to each node containing a pointer to both the next and previous nodes.
47 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

o This is particularly useful for operations that require frequent backtracking,


such as finding the previous node or navigating to the end of the list without
starting from the head.

2. Efficient Deletion of a Given Node:

o In a doubly linked list, deleting a specific node is easier and more efficient
because each node has a pointer to its previous node.

o Unlike a singly linked list, where we must traverse from the head to find the
previous node to update pointers, in a doubly linked list, we can directly access
the previous node, making deletion quicker.

3. Insertion and Deletion at Both Ends:

o Inserting or deleting a node at the end of a doubly linked list is more efficient
since we can traverse from either end and update the tail node if needed.

o In a singly linked list, we need to start from the head and go through the list to
find the last node, especially when inserting or deleting at the tail.

4. Better for Implementing Complex Data Structures:

o Doubly linked lists are commonly used in the implementation of complex data
structures, such as deques (double-ended queues) and certain tree structures,
where forward and backward navigation is beneficial.

5. Ease of Reversing the List:

o Reversing a doubly linked list is more straightforward and efficient, as each


node has a prev pointer. We can swap the next and prev pointers of each node
and set the last node as the new head.

o In contrast, reversing a singly linked list requires reassigning next pointers and
is more cumbersome.

2.6 Time and Space Complexities of all Operations

 Insertion:

o Time: O(1) at the beginning; O(n) at the end or specific position.

o Space: O(1)
48 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

 Deletion:

o Time: O(1) at the beginning; O(n) at the end or specific position.

o Space: O(1)

 Traversal:

o Time: O(n)

o Space: O(1)

 Finding Length:

o Time: O(n) for all types.

o Space: O(1) for all types.

 Creation:

o Time: O(n) total, O(1) per node for all types.

o Space: O(n) for all types.

 Sorting (Bubble Sort):

o Time: O(n²) for all types.

o Space: O(1) for all types.

 Searching:

o Time: O(n) for all types.

o Space: O(1) for all types.

 Concatenation:

o Time:

 O(m + n) for singly and doubly linked lists (because you need to traverse
to the end of the first list to connect it).

 O(1) for circular and doubly circular linked lists (since you can link the
tail of one list directly to the head of the other).

o Space: O(1) for all types.


49 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

3. Polynomial Manipulations
3.1 Polynomial Addition

Polynomial addition using linked lists involves representing each polynomial as a linked list,
where each node stores the coefficient and exponent of a term. By aligning terms of the same
degree, we can efficiently add polynomials.

Steps for Polynomial Addition

1. Represent Each Polynomial:

o Each polynomial is represented as a linked list of nodes.

o Each node contains two parts: coefficient and exponent, along with a next
pointer to the next term.

2. Traverse Both Lists Simultaneously:

o Start at the head of both linked lists and compare the exponents.

o If the exponents are equal, add the coefficients and create a new node with the
summed coefficient and same exponent.

o If the exponent in the first list is greater, add the term from the first list to the
result list.

o If the exponent in the second list is greater, add the term from the second list to
the result list.
50 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

3. Handle Remaining Terms:

o If one polynomial has remaining terms after the other list is exhausted, append
these remaining terms to the result list.

4. Resulting Polynomial:

o The resulting linked list represents the sum of the two polynomials, where terms
are ordered by descending exponent.

Q. Write Pseudo C++ code for addition of two polynomials using singly linked list.

struct Node {
int coeff; // Coefficient of the term
int pow; // Exponent of the term
Node* next; // Pointer to the next term

Node(int c, int p) : coeff(c), pow(p), next(nullptr) {}


};

// Function to add two polynomials represented as linked lists


Node* addPolynomials(Node* poly1, Node* poly2) {
Node* result = nullptr; // Resultant polynomial
Node** lastPtrRef = &result; // Pointer to the last node

while (poly1 != nullptr && poly2 != nullptr) {


Node* newNode;

if (poly1->pow > poly2->pow) {


newNode = new Node(poly1->coeff, poly1->pow);
poly1 = poly1->next; // Move to the next term in poly1
} else if (poly1->pow < poly2->pow) {
newNode = new Node(poly2->coeff, poly2->pow);
poly2 = poly2->next; // Move to the next term in poly2
} else { // Exponents are equal
51 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

int sumCoeff = poly1->coeff + poly2->coeff;


if (sumCoeff != 0) { // Only add if the coefficient is
// non-zero
newNode = new Node(sumCoeff, poly1->pow);
} else {
poly1 = poly1->next; // Skip zero coefficient
poly2 = poly2->next;
continue; // Move to the next iteration
}
poly1 = poly1->next; // Move to the next term in both
// polynomials
poly2 = poly2->next;
}

*lastPtrRef = newNode; // Attach the new node


lastPtrRef = &newNode->next; // Update last pointer
}

// Attach remaining terms from either polynomial


while (poly1 != nullptr) {
*lastPtrRef = new Node(poly1->coeff, poly1->pow);
lastPtrRef = &(*lastPtrRef)->next;
poly1 = poly1->next;
}

while (poly2 != nullptr) {


*lastPtrRef = new Node(poly2->coeff, poly2->pow);
lastPtrRef = &(*lastPtrRef)->next;
poly2 = poly2->next;
}

return result; // Return the resultant polynomial


52 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

// Function to print the polynomial


void printPolynomial(Node* head) {
while (head != nullptr) {
cout << head->coeff << "x^" << head->pow;
head = head->next;
if (head != nullptr) cout << " + ";
}
cout << endl;
}
Q. Write pseudocode to perform addition of two polynomials using doubly linked lists
into third list. Write time complexity of it.

struct Node {
int coeff; // Coefficient of the term
int pow; // Exponent of the term
Node* next; // Pointer to the next term
Node* prev; // Pointer to the previous term

Node(int c, int p) : coeff(c), pow(p), next(nullptr),


prev(nullptr) {}
};

// Function to add two polynomials represented as doubly linked lists


Node* addPolynomials(Node* poly1, Node* poly2) {
Node* result = nullptr; // Resultant polynomial
Node* last = nullptr; // Pointer to the last node in the result

// Traverse both lists


while (poly1 != nullptr || poly2 != nullptr) {
Node* newNode = nullptr;
53 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

if (poly1 == nullptr) { // poly1 is exhausted


newNode = new Node(poly2->coeff, poly2->pow);
poly2 = poly2->next;
} else if (poly2 == nullptr) { // poly2 is exhausted
newNode = new Node(poly1->coeff, poly1->pow);
poly1 = poly1->next;
} else if (poly1->pow > poly2->pow) { // poly1 has higher power
newNode = new Node(poly1->coeff, poly1->pow);
poly1 = poly1->next;
} else if (poly1->pow < poly2->pow) { // poly2 has higher power
newNode = new Node(poly2->coeff, poly2->pow);
poly2 = poly2->next;
} else { // Powers are equal
int sumCoeff = poly1->coeff + poly2->coeff;
if (sumCoeff != 0) { // Only create a new node if the
// coefficient is non-zero
newNode = new Node(sumCoeff, poly1->pow);
}
poly1 = poly1->next; // Move to next nodes in both polynomials
poly2 = poly2->next;
}

// Attach the new node to the result


if (newNode != nullptr) {
if (result == nullptr) {
result = newNode; // Set first node
last = newNode; // Initialize last pointer
} else {
last->next = newNode; // Link new node
newNode->prev = last; // Set previous pointer
last = newNode; // Update last pointer
}
54 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

}
}

return result; // Return the resultant polynomial


}

// Function to print the polynomial


void printPolynomial(Node* head) {
while (head != nullptr) {
cout << head->coeff << "x^" << head->pow;
head = head->next;
if (head != nullptr) cout << " + ";
}
cout << endl;
}
The time complexity of the addition of two polynomials using doubly linked lists is O(n + m),
where:

 n is the number of terms in the first polynomial.

 m is the number of terms in the second polynomial.

3.2 Generalized Linked List (GLL) Concept

A Generalized Linked List L, is defined as a finite sequence of n >= 0 elements, l1, l2, l3, l4, …,
ln, such that li are either item or the list of items. Thus L = (l1, l2, l3, l4, …, ln) where n is total
number of nodes in the list.

To represent a list of items there are certain assumptions about the node structure.

 Flag = 1 implies that down pointer exists

 Flag = 0 implies that next pointer exists


55 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

 Data means the item.

 Down pointer is the address of node which is down of the current node

 Next pointer is the address of node which is attached as the next node

Generalized linked lists are used because although the efficiency of polynomial operations
using linked list is good but still, the disadvantage is that the linked list is unable to use multiple
variable polynomial equation efficiently. It helps us to represent multi-variable polynomial
along with the list of elements.

Example of GLL {List representation} (a, (b, c), d)

When first field is 0, it indicates that the second field is variable. If first field is 1 means the
second field is a down pointer, means some list is starting.

Syntax of Generalized Linked List:

class GeneralizedListNode{
private:
GeneralizedListNode *next;
bool tag;
union{
char data;
GeneralizedListNode *down;
};
};
3.3 Representation of Polynomial using GLL

The typical node structure will be:


56 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

 Here Flag = 0 means variable is present

 Flag = 1 means down pointer is present

 Flag = 2 means coefficient and exponent is present

Example: 9x5 + 7x4y + 10xz

In the above example the head node is of variable x. The temp node shows the first field as 2
means coefficient and exponent are present.

Since temp node is attached to head node and head node is having variable x, temp node having
coefficient = 9 and exponent = 5. The above two nodes can be read as 9x5.

Similarly, in the above figure, the node temp1 can be read as x4.

 The flag field is 1 means that there is a down pointer.


57 | P a g e © Haris Chaus | ALL RIGHTS ARE RESERVED as per copyright act.

 temp2 = y

 temp3 = coefficient = 7

 exponent = 1

 flag = 2 means the node contains coefficient and exponent values.

 temp2 is attached to temp3 this means 7y1 and temp2 is also attached to temp1 means

 temp1 × temp2

 x4 × 7y1 = 7x4y1 value is represented by above figure

You might also like