DATA STRUCTURES WITH
C++ ASSIGNMENT-4
24/10/2024
ABHISHEK S K
ECE-01
B220634EC
1. Realize all the operations on stacks and queues using
a) Arrays
b) linked lists
A.
#include <iostream>
using namespace std;
class ArrayStack {
int *arr, cap, topIdx;
public:
ArrayStack(int size) : cap(size), topIdx(-1) { arr = new int[cap]; }
bool push(int elem) { if (topIdx == cap - 1) return false; arr[++topIdx] = elem; return true; }
bool pop() { if (topIdx == -1) return false; --topIdx; return true; }
int top() { return topIdx == -1 ? -1 : arr[topIdx]; }
bool isEmpty() { return topIdx == -1; }
};
class ArrayQueue {
int *arr, cap, frontIdx, rearIdx, size;
public:
ArrayQueue(int size) : cap(size), frontIdx(0), rearIdx(cap - 1), size(0) { arr = new int[cap]; }
bool enqueue(int elem) { if (size == cap) return false; rearIdx = (rearIdx + 1) % cap;
arr[rearIdx] = elem; ++size; return true; }
bool dequeue() { if (size == 0) return false; frontIdx = (frontIdx + 1) % cap; --size; return
true; }
int front() { return size == 0 ? -1 : arr[frontIdx]; }
bool isEmpty() { return size == 0; }
};
int main() {
ArrayStack stack(5);
ArrayQueue queue(5);
stack.push(10); queue.enqueue(20);
cout << "Stack Top: " << stack.top() << endl;
cout << "Queue Front: " << queue.front() << endl;
return 0;
}
B.
#include <iostream>
using namespace std;
struct NodeStack {
int data;
NodeStack *next;
NodeStack(int val) : data(val), next(nullptr) {}
};
class LinkedStack {
NodeStack *topNode;
public:
LinkedStack() : topNode(nullptr) {}
bool push(int elem) { NodeStack *n = new NodeStack(elem); n->next = topNode; topNode = n; return
true; }
bool pop() { if (!topNode) return false; NodeStack *tmp = topNode; topNode = topNode->next;
delete tmp; return true; }
int top() { return topNode ? topNode->data : -1; }
};
struct NodeQueue {
int data;
NodeQueue *next;
NodeQueue(int val) : data(val), next(nullptr) {}
};
class LinkedQueue {
NodeQueue *frontNode, *rearNode;
public:
LinkedQueue() : frontNode(nullptr), rearNode(nullptr) {}
bool enqueue(int elem) { NodeQueue *n = new NodeQueue(elem); if (!rearNode) frontNode = rearNode
= n; else { rearNode->next = n; rearNode = n; } return true; }
bool dequeue() { if (!frontNode) return false; NodeQueue *tmp = frontNode; frontNode =
frontNode->next; if (!frontNode) rearNode = nullptr; delete tmp; return true; }
int front() { return frontNode ? frontNode->data : -1; }
};
int main() {
LinkedStack stack;
LinkedQueue queue;
stack.push(15); queue.enqueue(25);
cout << "Linked Stack Top: " << stack.top() << endl;
cout << "Linked Queue Front: " << queue.front() << endl;
return 0;
}
2. Realize the following operations of a singly linked list. Output the results for each operation.
a. Insert Node at beginning
b. Insert node at last
c. Insert node at position
d. Sort Linked List
e. Delete a Particular Node
f. Update Node Value
g. Search Element
h. Display Linked List
i. Reverse Linked List
#include <iostream>
#include <stdexcept>
class LinkedList {
private:
struct Node {
int data;
Node* next;
explicit Node(int value) : data(value), next(nullptr) {}
};
Node* head;
int size;
// Helper method to get node at position
Node* getNodeAt(int position) const {
if (position < 0 || position >= size) {
throw std::out_of_range("Invalid position");
}
Node* current = head;
for (int i = 0; i < position; i++) {
current = current->next;
}
return current;
}
public:
LinkedList() : head(nullptr), size(0) {}
// Destructor to clean up memory
~LinkedList() {
Node* current = head;
while (current != nullptr) {
Node* next = current->next;
delete current;
current = next;
}
}
// a. Insert node at beginning
void insertAtBeginning(int value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
size++;
}
// b. Insert node at last
void insertAtLast(int value) {
if (head == nullptr) {
insertAtBeginning(value);
return;
}
Node* current = head;
while (current->next != nullptr) {
current = current->next;
}
current->next = new Node(value);
size++;
}
// c. Insert node at position
void insertAtPosition(int value, int position) {
if (position < 0 || position > size) {
throw std::out_of_range("Invalid position");
}
if (position == 0) {
insertAtBeginning(value);
return;
}
Node* previous = getNodeAt(position - 1);
Node* newNode = new Node(value);
newNode->next = previous->next;
previous->next = newNode;
size++;
}
// d. Sort Linked List (using bubble sort)
void sort() {
if (size <= 1) return;
bool swapped;
do {
swapped = false;
Node* current = head;
Node* previous = nullptr;
while (current->next != nullptr) {
if (current->data > current->next->data) {
// Swap nodes
Node* temp = current->next;
current->next = temp->next;
temp->next = current;
if (previous == nullptr) {
head = temp;
} else {
previous->next = temp;
}
previous = temp;
swapped = true;
} else {
previous = current;
current = current->next;
}
}
} while (swapped);
}
// e. Delete a Particular Node
void deleteNode(int value) {
if (head == nullptr) {
throw std::runtime_error("List is empty");
}
if (head->data == value) {
Node* temp = head;
head = head->next;
delete temp;
size--;
return;
}
Node* current = head;
while (current->next != nullptr && current->next->data != value) {
current = current->next;
}
if (current->next == nullptr) {
throw std::runtime_error("Value not found");
}
Node* temp = current->next;
current->next = temp->next;
delete temp;
size--;
}
// f. Update Node Value
void updateNode(int oldValue, int newValue) {
Node* current = head;
bool found = false;
while (current != nullptr) {
if (current->data == oldValue) {
current->data = newValue;
found = true;
break;
}
current = current->next;
}
if (!found) {
throw std::runtime_error("Value not found");
}
}
// g. Search Element
bool search(int value) const {
Node* current = head;
while (current != nullptr) {
if (current->data == value) {
return true;
}
current = current->next;
}
return false;
}
// Find position of element
int findPosition(int value) const {
Node* current = head;
int position = 0;
while (current != nullptr) {
if (current->data == value) {
return position;
}
current = current->next;
position++;
}
return -1;
}
// h. Display Linked List
void display() const {
if (head == nullptr) {
std::cout << "List is empty" << std::endl;
return;
}
Node* current = head;
while (current != nullptr) {
std::cout << current->data;
if (current->next != nullptr) {
std::cout << " -> ";
}
current = current->next;
}
std::cout << std::endl;
}
// i. Reverse Linked List
void reverse() {
Node *prev = nullptr, *current = head, *next = nullptr;
while (current != nullptr) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head = prev;
}
// Additional utility methods
bool isEmpty() const {
return head == nullptr;
}
int getSize() const {
return size;
}
};
int main() {
try {
LinkedList list;
// Test insertions
std::cout << "Inserting elements..." << std::endl;
list.insertAtBeginning(3);
list.insertAtLast(7);
list.insertAtBeginning(1);
list.insertAtPosition(5, 2);
std::cout << "List after insertions: ";
list.display();
// Test sorting
std::cout << "\nSorting list..." << std::endl;
list.sort();
std::cout << "Sorted list: ";
list.display();
// Test searching
int searchValue = 5;
std::cout << "\nSearching for " << searchValue << "..." << std::endl;
if (list.search(searchValue)) {
std::cout << "Found " << searchValue << " at position " <<
list.findPosition(searchValue) << std::endl;
}
// Test updating
std::cout << "\nUpdating 5 to 6..." << std::endl;
list.updateNode(5, 6);
std::cout << "List after update: ";
list.display();
// Test deletion
std::cout << "\nDeleting node with value 3..." << std::endl;
list.deleteNode(3);
std::cout << "List after deletion: ";
list.display();
// Test reverse
std::cout << "\nReversing list..." << std::endl;
list.reverse();
std::cout << "Reversed list: ";
list.display();
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
Tree Questions
1. Take a binary tree and do tree traversals
#include <iostream>
using namespace std;
struct NodeTree {
int data;
NodeTree *left, *right;
NodeTree(int val) : data(val), left(nullptr), right(nullptr) {}
};
class BinaryTree {
public:
void inOrder(NodeTree *node) { if (node) { inOrder(node->left); cout << node->data << " ";
inOrder(node->right); } }
void preOrder(NodeTree *node) { if (node) { cout << node->data << " "; preOrder(node->left);
preOrder(node->right); } }
void postOrder(NodeTree *node) { if (node) { postOrder(node->left); postOrder(node->right); cout
<< node->data << " "; } }
};
int main() {
NodeTree *root = new NodeTree(59);
root->left = new NodeTree(43);
root->right = new NodeTree(68);
root->left->left = new NodeTree(32);
root->left->right = new NodeTree(50);
BinaryTree tree;
tree.inOrder(root);
cout << endl;
tree.preOrder(root);
cout << endl;
tree.postOrder(root);
cout << endl;
return 0;
}
2. Construct a BST and do the following on it:
a) Insert
b) Delete
c) Search
d) Max
e) Min
f) Predecessor
g) Successor
#include <iostream>
#include <stdexcept>
#include <stack>
class BST {
private:
struct Node {
int data;
Node *left, *right;
explicit Node(int val) : data(val), left(nullptr), right(nullptr) {}
};
Node* root;
// Helper method to clean up memory
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
Node* insert(Node* node, int val) {
if (!node) return new Node(val);
if (val < node->data) node->left = insert(node->left, val);
else if (val > node->data) node->right = insert(node->right, val);
return node;
}
Node* deleteNode(Node* node, int key) {
if (!node) return nullptr;
if (key < node->data) {
node->left = deleteNode(node->left, key);
} else if (key > node->data) {
node->right = deleteNode(node->right, key);
} else {
// Node with only one child or no child
if (!node->left) {
Node* temp = node->right;
delete node;
return temp;
} else if (!node->right) {
Node* temp = node->left;
delete node;
return temp;
}
// Node with two children: Get the inorder successor (smallest
// in the right subtree)
Node* temp = minValueNode(node->right);
node->data = temp->data;
node->right = deleteNode(node->right, temp->data);
}
return node;
}
Node* minValueNode(Node* node) const {
if (!node) return nullptr;
while (node->left) node = node->left;
return node;
}
Node* maxValueNode(Node* node) const {
if (!node) return nullptr;
while (node->right) node = node->right;
return node;
}
Node* search(Node* node, int key) const {
if (!node || node->data == key) return node;
return (key < node->data) ? search(node->left, key) : search(node->right, key);
}
void inorderTraversal(Node* node, std::ostream& out) const {
if (node) {
inorderTraversal(node->left, out);
out << node->data << " ";
inorderTraversal(node->right, out);
}
}
public:
BST() : root(nullptr) {}
// Destructor to prevent memory leaks
~BST() {
destroyTree(root);
}
// Delete copy constructor and assignment operator to prevent shallow copying
BST(const BST&) = delete;
BST& operator=(const BST&) = delete;
void insert(int val) {
root = insert(root, val);
}
void remove(int key) {
if (!search(root, key)) {
throw std::runtime_error("Key not found in the tree");
}
root = deleteNode(root, key);
}
bool contains(int key) const {
return search(root, key) != nullptr;
}
int minValue() const {
if (!root) throw std::runtime_error("Tree is empty");
return minValueNode(root)->data;
}
int maxValue() const {
if (!root) throw std::runtime_error("Tree is empty");
return maxValueNode(root)->data;
}
int predecessor(int key) const {
Node* current = root;
Node* pred = nullptr;
while (current) {
if (key > current->data) {
pred = current;
current = current->right;
} else {
current = current->left;
}
}
if (!pred) throw std::runtime_error("No predecessor found");
return pred->data;
}
int successor(int key) const {
Node* current = root;
Node* succ = nullptr;
while (current) {
if (key < current->data) {
succ = current;
current = current->left;
} else {
current = current->right;
}
}
if (!succ) throw std::runtime_error("No successor found");
return succ->data;
}
bool empty() const {
return root == nullptr;
}
void display(std::ostream& out = std::cout) const {
if (empty()) {
out << "Empty tree" << std::endl;
return;
}
inorderTraversal(root, out);
out << std::endl;
}
};
int main() {
try {
BST bst;
// Test insertion
bst.insert(45);
bst.insert(25);
bst.insert(65);
bst.insert(15);
bst.insert(35);
bst.insert(55);
bst.insert(75);
std::cout << "Inorder traversal of the BST: ";
bst.display();
// Test deletion
bst.remove(15);
std::cout << "After deleting 15: ";
bst.display();
// Test search
int key = 35;
std::cout << "Search " << key << ": " << (bst.contains(key) ? "Found" : "Not Found") <<
std::endl;
// Test min/max
std::cout << "Minimum value: " << bst.minValue() << std::endl;
std::cout << "Maximum value: " << bst.maxValue() << std::endl;
// Test predecessor/successor
std::cout << "Predecessor of 35: " << bst.predecessor(35) << std::endl;
std::cout << "Successor of 35: " << bst.successor(35) << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}