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

BBBB

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

BBBB

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

SGSGFVv

){
// Create two sorted linked lists
Node* list1 = new Node(1);
list1->next = new Node(3);
list1->next->next = new Node(5);

Node* list2 = new Node(2);


list2->next = new Node(4);
list2->next->next = new Node(6);

// Merge the lists


Node* mergedList = mergeSortedLists(list1, list2);

// Print the merged list


std::cout << "Merged List: ";
printList(mergedList);

return 0;
}

Q:3: Delete an ith node from a linked list. Be sure that such a node
exists.
ANS: To delete the ith node from a linked list, we need to update the links to bypass that
node:
#include <iostream>

struct Node {
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
// Function to delete the ith node from a linked list
void deleteNodeAtIndex(Node*& head, int index) {
if (index == 0) {
Node* temp = head;
head = head->next;
delete temp;
} else {
Node* current = head;
for (int i = 0; i < index - 1; i++) {
if (current == nullptr) {
// Make sure the node at the given index exists
std::cout << "Node at index " << index << " does not exist." << std::endl;
return;
}
current = current->next;
}
if (current == nullptr || current->next == nullptr) {
// Make sure the node at the given index exists
std::cout << "Node at index " << index << " does not exist." << std::endl;
return;
}
Node* temp = current->next;
current->next = temp->next;
delete temp;
}
}

// Function to print the linked list


void printList(Node* head) {
while (head) {
std::cout << head->data << " -> ";
head = head->next;
}
std::cout << "nullptr" << std::endl;
}

int main() {
// Create a sample linked list
Node* head = new Node(1);
head->next = new Node(2);
head->next->next = new Node(3);
head->next->next->next = new Node(4);

// Print the original list


std::cout << "Original List: ";
printList(head);

// Delete the ith node


int indexToDelete = 2;
deleteNodeAtIndex(head, indexToDelete);

// Print the modified list


std::cout << "List after deleting node at index " << indexToDelete << ": ";
printList(head);

return 0;
}

Q:4: Delete from list L1 nodes whose positions are to be found in an


ordered list L2. For instance, if L1 = (A B C D E) and L2 = (2 4 8), then
the second and the fourth nodes are to be deleted from list L1 (the
eighth node does not exist), and after deletion, L1 = (A C E).
ANS: To delete nodes from list L1 based on the positions specified in an ordered list L2, we
can follow these steps in C++:

1. Create a function to delete nodes at the specified positions.


2. Iterate through L2 to identify the positions to delete in L1.
3. Delete the nodes at those positions from L1.
CODE:
#include <iostream>
#include <list>

// Function to delete nodes from L1 at the positions specified in L2


void deleteNodesAtPositions(std::list<char>& L1, const std::list<int>& L2) {
int index = 0;
auto itL1 = L1.begin();
auto itL2 = L2.begin();

while (itL1 != L1.end() && itL2 != L2.end()) {


int positionToDelete = *itL2;

while (index < positionToDelete && itL1 != L1.end()) {


++itL1;
++index;
}

if (itL1 != L1.end()) {
itL1 = L1.erase(itL1);
++itL2;
}
}
}
int main() {
// Create list L1
std::list<char> L1 = {'A', 'B', 'C', 'D', 'E'};

// Create list L2 with positions to delete


std::list<int> L2 = {2, 4, 8}; // The positions 2 and 4 will be deleted

// Delete nodes from L1 based on L2


deleteNodesAtPositions(L1, L2);

// Print the modified list L1


for (char elem : L1) {
std::cout << elem << " ";
}
std::cout << std::endl;

return 0;
}

Q:5:Delete from list L1 nodes occupying positions indicated in


ordered lists L2 and L3 . For instance, if L1 = (A B C D E), L2 = (2 4 8),
and L3 = (2 5), then after deletion, L1 = (A C).
ANS: To delete nodes from list L1 based on the positions specified in two ordered lists, L2
and L3, we can follow a similar approach as before.
#include <iostream>
#include <list>
#include <set>

// Function to delete nodes from L1 at the positions specified in L2 and L3


void deleteNodesAtPositions(std::list<char>& L1, const std::set<int>& L2, const
std::set<int>& L3) {
int index = 0;
auto itL1 = L1.begin();
auto itL2 = L2.begin();
auto itL3 = L3.begin();

while (itL1 != L1.end() && (itL2 != L2.end() || itL3 != L3.end())) {


int positionToDelete = std::min(*itL2, *itL3);

while (index < positionToDelete && itL1 != L1.end()) {


++itL1;
++index;
}

if (itL1 != L1.end() && (itL2 != L2.end() || itL3 != L3.end())) {


itL1 = L1.erase(itL1);
if (itL2 != L2.end() && *itL2 == positionToDelete) {
++itL2;
}
if (itL3 != L3.end() && *itL3 == positionToDelete) {
++itL3;
}
}
}
}

int main() {
// Create list L1
std::list<char> L1 = {'A', 'B', 'C', 'D', 'E'};

// Create ordered lists L2 and L3 with positions to delete


std::set<int> L2 = {2, 4, 8}; // The positions 2 and 4 will be deleted
std::set<int> L3 = {2, 5}; // The positions 2 and 5 will be deleted
// Delete nodes from L1 based on L2 and L3
deleteNodesAtPositions(L1, L2, L3);

// Print the modified list L1


for (char elem : L1) {
std::cout << elem << " ";
}
std::cout << std::endl;

return 0;
}

Q:6: Delete from an ordered list L nodes occupying positions


indicated in list L itself. For instance, if L = (1 3 5 7 8), then after
deletion, L = (3 7).
ANS: To delete nodes from an ordered list `L` based on the positions indicated in `L` itself,
we can follow a straightforward approach. Since we want to delete nodes at the specified
positions, we should iterate through `L` and remove nodes at the specified positions.
#include <iostream>
#include <list>

// Function to delete nodes from an ordered list L at the positions specified in L itself
void deleteNodesAtSelfPositions(std::list<int>& L) {
auto it = L.begin();
int index = 0;

while (it != L.end()) {


if (index % 2 == 1) { // Check if the position should be deleted
it = L.erase(it);
} else {
++it;
}

++index;
}
}

int main() {
// Create an ordered list L
std::list<int> L = {1, 3, 5, 7, 8};

// Delete nodes from L at the specified positions


deleteNodesAtSelfPositions(L);

// Print the modified list L


for (int elem : L) {
std::cout << elem << " ";
}
std::cout << std::endl;

return 0;
}

Q:7: A linked list does not have to be implemented with pointers.


Suggest other implementations of linked lists.
ANS: While linked lists are traditionally implemented using pointers to create the links
between nodes, there are alternative implementations for linked lists that don't use explicit
pointers. Here are a couple of alternative implementations:

1. Array-Based Linked List:


We can implement a linked list using arrays instead of pointers. In this approach, we
allocate a fixed-size array to hold elements, and each element in the array contains an index
that points to the next element in the list. We would need to manage the array and track
available indices for insertion and deletion.
2. Dynamic Arrays (Vectors in C++):
We can use dynamic arrays, such as vectors in C++, to simulate a linked list. Vectors
automatically handle resizing and reallocation of memory. By keeping track of indices or
offsets for the next element, we can achieve a similar effect as a linked list.

3. Contiguous Memory Block:


Instead of using explicit pointers, we can allocate a large contiguous memory block and
store elements sequentially. We can use indices or offsets to navigate between elements.
This approach is commonly used in memory pool implementations.

4. Circular Buffer or Ring Buffer


A circular buffer is a fixed-size data structure that overwrites the oldest data when it
reaches capacity. We can use this structure to implement a linked list where the next
element is determined by the current element's index modulo the buffer size.

5. Indexed Data Structures:


Some databases and data structures store linked list-like structures with indexing
mechanisms rather than explicit pointers. These indexing structures allow for efficient access
and traversal without using traditional pointers.

Q:8: Write a member function to check whether two singly linked


lists have the same
contents.
ANS: To check whether two singly linked lists have the same contents, we can create a
member function in our C++ class for the linked list.
#include <iostream>

class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
class SinglyLinkedList {
private:
Node* head;

public:
SinglyLinkedList() : head(nullptr) {}

// Function to check whether two linked lists have the same contents
bool isEqual(SinglyLinkedList& otherList) {
Node* current1 = this->head;
Node* current2 = otherList.head;

while (current1 != nullptr && current2 != nullptr) {


if (current1->data != current2->data) {
return false; // The data is not the same
}
current1 = current1->next;
current2 = current2->next;
}

// Check if both lists have reached the end (nullptr) at the same time
return current1 == nullptr && current2 == nullptr;
}

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


void insert(int val) {
Node* newNode = new Node(val);
if (head == nullptr) {
head = newNode;
} else {
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = newNode;
}
}
};

int main() {
SinglyLinkedList list1;
SinglyLinkedList list2;

// Populate the lists with data


list1.insert(1);
list1.insert(2);
list1.insert(3);

list2.insert(1);
list2.insert(2);
list2.insert(3);

// Check if the two lists have the same contents


bool areEqual = list1.isEqual(list2);

if (areEqual) {
std::cout << "The lists have the same contents." << std::endl;
} else {
std::cout << "The lists do not have the same contents." << std::endl;
}
return 0;
}

Q:9: Write a member function to reverse a singly linked list using


only one pass through
the list.
ANS: To reverse a singly linked list using only one pass through the list, you can implement
the reverse operation iteratively.
#include <iostream>

class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};

class SinglyLinkedList {
private:
Node* head;

public:
SinglyLinkedList() : head(nullptr) {}

// Function to reverse the linked list in one pass


void reverse() {
Node* prev = nullptr;
Node* current = head;
Node* nextNode = nullptr;

while (current != nullptr) {


nextNode = current->next; // Save the next node
// Reverse the link of the current node
current->next = prev;

// Move to the next node


prev = current;
current = nextNode;
}

// Update the head to point to the new first node (prev)


head = prev;
}

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


void insert(int val) {
Node* newNode = new Node(val);
if (head == nullptr) {
head = newNode;
} else {
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = newNode;
}
}

// Function to print the linked list


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

int main() {
SinglyLinkedList list;

// Populate the list with data


list.insert(1);
list.insert(2);
list.insert(3);
list.insert(4);

std::cout << "Original List: ";


list.printList();

// Reverse the list


list.reverse();

std::cout << "Reversed List: ";


list.printList();

return 0;
}

Q:10: Insert a new node into a singly linked list (a) before and (b)
after a node pointed to
by p in this list (possibly the first or the last). Do not use a loop in
either operation.
ANS: To insert a new node into a singly linked list (a) before and (b) after a node pointed to
by `p` without using a loop, you can implement these operations within our
`SinglyLinkedList` class.
#include <iostream>

class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};

class SinglyLinkedList {
private:
Node* head;

public:
SinglyLinkedList() : head(nullptr) {}

// Function to insert a new node before the node pointed to by p


void insertBefore(Node* p, int val) {
if (p == nullptr) {
// If p is nullptr, insert the new node at the beginning of the list
Node* newNode = new Node(val);
newNode->next = head;
head = newNode;
} else {
Node* newNode = new Node(val);
newNode->next = p->next;
p->next = newNode;
}
}

// Function to insert a new node after the node pointed to by p


void insertAfter(Node* p, int val) {
if (p == nullptr) {
// If p is nullptr, insert the new node at the end of the list
Node* newNode = new Node(val);
if (head == nullptr) {
head = newNode;
} else {
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = newNode;
}
} else {
Node* newNode = new Node(val);
newNode->next = p->next;
p->next = newNode;
}
}

// Function to print the linked list


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

int main() {
SinglyLinkedList list;

// Populate the list with data


list.insert(1);
list.insert(2);
list.insert(3);

std::cout << "Original List: ";


list.printList();

Node* targetNode = list.head->next; // Node to insert before/after

// Insert a new node before the target node


list.insertBefore(targetNode, 4);

std::cout << "List after inserting before: ";


list.printList();

// Insert a new node after the target node


list.insertAfter(targetNode, 5);

std::cout << "List after inserting after: ";


list.printList();

return 0;
}
Q:11: Attach a singly linked list to the end of another singly linked
list.
ANS: To attach one singly linked list to the end of another singly linked list, you need to find
the last node of the first list and make it point to the head of the second list.
#include <iostream>

class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};

class SinglyLinkedList {
private:
Node* head;

public:
SinglyLinkedList() : head(nullptr) {}

// Function to insert a new node at the end of the list


void insert(int val) {
Node* newNode = new Node(val);
if (head == nullptr) {
head = newNode;
} else {
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = newNode;
}
}

// Function to attach another list to the end of this list


void attachList(SinglyLinkedList& otherList) {
if (head == nullptr) {
head = otherList.head;
} else {
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = otherList.head;
}
// Reset the other list so that it doesn't get destroyed when its destructor is called
otherList.head = nullptr;
}

// Function to print the linked list


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

int main() {
SinglyLinkedList list1;
SinglyLinkedList list2;

// Populate the first list with data


list1.insert(1);
list1.insert(2);
list1.insert(3);

// Populate the second list with data


list2.insert(4);
list2.insert(5);
list2.insert(6);

std::cout << "List 1: ";


list1.printList();
std::cout << "List 2: ";
list2.printList();

// Attach list2 to the end of list1


list1.attachList(list2);

std::cout << "List 1 after attaching list 2: ";


list1.printList();

return 0;
}

Q:12: Put numbers in a singly linked list in ascending order. Use this
operation to find the
median in the list of numbers.
ANS:
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};

class SortedLinkedList {
private:
Node* head;

public:
SortedLinkedList() : head(nullptr) {}

// Function to insert a number into the list while maintaining ascending order
void insert(int val) {
Node* newNode = new Node(val);
if (head == nullptr || val <= head->data) {
newNode->next = head;
head = newNode;
} else {
Node* current = head;
while (current->next != nullptr && val > current->next->data) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
// Function to find the median in the list
double findMedian() {
if (head == nullptr) {
return 0.0;
}

Node* slow = head;


Node* fast = head;
Node* prev = nullptr;

while (fast != nullptr && fast->next != nullptr) {


prev = slow;
slow = slow->next;
fast = fast->next->next;
}

if (fast == nullptr) {
// The list has an even number of elements
return (static_cast<double>(prev->data) + static_cast<double>(slow->data)) / 2.0;
} else {
// The list has an odd number of elements
return static_cast<double>(slow->data);
}
}
};

int main() {
SortedLinkedList sortedList;

// Insert numbers into the list


sortedList.insert(3);
sortedList.insert(1);
sortedList.insert(2);
sortedList.insert(5);
sortedList.insert(4);

// Find and print the median


double median = sortedList.findMedian();
std::cout << "Median: " << median << std::endl;

return 0;
}

Q:13: How can a singly linked list be implemented so that insertion


requires no test for
whether head is null?
ANS: To implement a singly linked list where insertion does not require a test for whether
the head is null :
#include <iostream>

class Node {
public:
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};

class SinglyLinkedList {
private:
Node* head;

public:
SinglyLinkedList() : head(nullptr) {}
// Function to insert a new node at the beginning of the list
void insert(int val) {
Node* newNode = new Node(val);
Node** current = &head; // Pointer to a pointer

newNode->next = *current;
*current = newNode;
}

// Function to print the linked list


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

int main() {
SinglyLinkedList list;

// Insert numbers into the list at the beginning


list.insert(3);
list.insert(1);
list.insert(2);

std::cout << "Linked List: ";


list.printList();
return 0;
}

Q:14: Insert a node in the middle of a doubly linked list.


ANS: To insert a node in the middle of a doubly linked list, you need to update the `next`
and `prev` pointers of the adjacent nodes to connect the new node properly:
#include <iostream>

class Node {
public:
int data;
Node* prev;
Node* next;
Node(int val) : data(val), prev(nullptr), next(nullptr) {}
};

class DoublyLinkedList {
private:
Node* head;
Node* tail;

public:
DoublyLinkedList() : head(nullptr), tail(nullptr) {}

// Function to insert a new node in the middle of the list


void insertInMiddle(int val) {
Node* newNode = new Node(val);

if (head == nullptr) {
head = newNode;
tail = newNode;
} else {
Node* slow = head;
Node* fast = head;

while (fast != nullptr && fast->next != nullptr) {


slow = slow->next;
fast = fast->next->next;
}

newNode->prev = slow;
newNode->next = slow->next;
if (slow->next != nullptr) {
slow->next->prev = newNode;
}
slow->next = newNode;

if (slow == tail) {
tail = newNode;
}
}
}

// Function to print the linked list from head to tail


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

int main() {
DoublyLinkedList list;

// Insert numbers into the list


list.insertInMiddle(1);
list.insertInMiddle(2);
list.insertInMiddle(3);

std::cout << "Linked List: ";


list.printList();

return 0;
}

Q:15: How likely is the worst case for searching a skip list to occur?
ANS: The likelihood of encountering the worst case scenario when searching a skip list
depends on several factors, including how the skip list is constructed, the distribution of
elements, and the specific search pattern.

In a well-balanced skip list, the worst-case scenario is less likely to occur because the
structure of the skip list ensures that most searches are efficient. However, it's still possible
to encounter the worst-case scenario under certain conditions:

1. Unbalanced Skip List:If the skip list is unbalanced, meaning that the levels are not evenly
distributed, you are more likely to encounter the worst-case scenario. In an unbalanced skip
list, you might have to traverse many levels to find the target element, leading to inefficient
searches.

2. Extreme Distribution:The distribution of elements in the skip list matters. If you have an
extreme distribution where elements are densely clustered at one end of the list or at the
highest levels, you are more likely to encounter the worst case when searching for elements
in the sparse regions.
3. Specific Search Patterns: The specific search pattern also affects the likelihood of worst-
case scenarios. If your search pattern consistently targets elements in a way that forces you
to traverse multiple levels, you are more likely to experience worst-case performance.

Overall, well-balanced skip lists are designed to provide efficient average and worst-case
search times, but worst-case scenarios are still possible. To minimize the likelihood of
encountering the worst case, it's essential to maintain the balance of the skip list and ensure
a reasonably uniform distribution of elements. Additionally, it's a good practice to design
your search patterns and algorithms to be as efficient as possible in typical usage scenarios.

You might also like