advanced data structures
advanced data structures
A PRACTICAL RECORD
Submitted by
JOANISHA DONNA A
2023506004
B. Tech (4/8)
Reg. No : 2023506004
Date:
Ms.R. Shanmugapriya
STAFF-IN-CHARGE
COURSE OBJECTIVES
CO3 To learn and implement different data structures using Object oriented concepts
COURSE OUTCOMES
CO1 Understand the usage of amortized analysis and Skip lists for real world
problem solving
CO2 Implement balanced trees through ADTs.
CO5 Analyze and apply the graph data structures for a given problem
CO-PO MATRIX
List of Experiments
S. Page
Date Name of the Experiment Signature
No. No
IMPLEMENTATION OF DYNAMIC
1. 09.01.25 TABLE USING AMORTIZED 1
OPERATIONS
IMPLEMENTATION OF BINARY COUNTER
2A. 23.01.25 USING AGGEGATE METHOD 7
IMPLEMENTATION OF B-TREE
6. 20.02.25 57
IMPLEMENTATION OF TRIES TO
8B. 27.02.25 AUTOCOMPLETE A TEXT 85
IMPLEMENTATION OF B TREE
AIM:
To implement the B Tree in C++.
ALGORITHM:
4. If choice = 1:
Input key
If root is null → create root and insert key
Else if root is full → split and insert into proper child
Else → insert into non-full node
5. If choice = 2:
Input key
Search from root using B-Tree search rules
Output "Key found" or "Key not found"
6. If choice = 3:
Recursively print all nodes level by level
For each level, print the keys in that node
7. If choice = 4:
End the program
SOURCE CODE:
#include <iostream>
using namespace std;
class BTreeNode {
public:
int *keys;
int t;
BTreeNode **C;
int n;
bool leaf;
BTreeNode *search(int k) {
int i = 0;
while (i < n && k > keys[i])
i++;
if (i < n && keys[i] == k)
return this;
if (leaf)
return nullptr;
return C[i]->search(k);
}
void insertNonFull(int k) {
int i = n - 1;
if (leaf) {
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
n++;
} else {
while (i >= 0 && keys[i] > k)
i--;
if (C[i + 1]->n == 2 * t - 1) {
splitChild(i + 1, C[i + 1]);
if (keys[i + 1] < k)
i++;
}
C[i + 1]->insertNonFull(k);
}
}
class BTree {
public:
BTreeNode *root;
int t;
BTree(int _t) {
root = nullptr;
t = _t;
}
void traverse() {
if (root)
root->traverseWithLevels();
else
cout << "Tree is empty\n";
}
BTreeNode *search(int k) {
return (root == nullptr) ? nullptr : root->search(k);
}
void insert(int k) {
if (root == nullptr) {
root = new BTreeNode(t, true);
root->keys[0] = k;
root->n = 1;
} else {
if (root->n == 2 * t - 1) {
BTreeNode *s = new BTreeNode(t, false);
s->C[0] = root;
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k)
i++;
s->C[i]->insertNonFull(k);
root = s;
} else
root->insertNonFull(k);
}
}
};
int main() {
int degree;
cout << "Enter the minimum degree of B-Tree: ";
cin >> degree;
BTree t(degree);
int choice, key;
while (true) {
OUTPUT:
cout << "\n1. Insert\n2. Search\n3. Traverse\n4. Exit\nEnter choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter key to insert: ";
cin >> key;
t.insert(key);
break;
case 2:
cout << "Enter key to search: ";
cin >> key;
if (t.search(key))
cout << "Key found\n";
else
cout << "Key not found\n";
break;
case 3:
cout << "Tree structure:\n";
t.traverse();
break;
case 4:
return 0;
default:
cout << "Invalid choice\n";
}
}
}
RESULT:
Thus,B Tree has been successfully implemented with insert,search
and display functions in C++ and its output has been verified.
Exp No. 7
Date: 20/02/2025
AIM:
To implement Red-Black trees and perform insertion,deletion and display
operations.
ALGORTIHM:
1. Insertion:
Create a RED node for the key.
Find its position in BST and attach it.
Fix violations using fixInsert():
o If uncle is RED, recolor and move up.
o If uncle is BLACK, rotate and recolor.
Ensure root is BLACK.
2. Fix Insertion:
While parent is RED:
o If uncle is RED, recolor parent, uncle, and grandparent.
o If uncle is BLACK, rotate (left/right) and swap colors.
Ensure root is BLACK.
3. Deletion:
Find node (z) to delete.
If z has one/no child, replace it with its child.
If z has two children, replace with in-order successor.
If deleted node was BLACK, fix balance.
SOURCE CODE:
#include <iostream>
using namespace std;
Node* root;
public:
RedBlackTree() : root(nullptr) {}
void printTree() {
OUTPUT:
if (!root) cout << "Tree is empty.\n";
else printHelper(root, "", true);
}
};
int main() {
RedBlackTree<int> rbtree;
int choice, value;
cout << "\n1. Insert\n2. Delete\n3. Print Tree\n4. Exit";
do {
cout << "Enter choice: ";
cin >> choice;
switch (choice) {
case 1: cout << "Enter value: "; cin >> value; rbtree.insert(value); break;
case 2: cout << "Enter value: "; cin >> value; rbtree.remove(value); break;
case 3: rbtree.printTree(); break;
case 4: break;
default: cout << "Invalid choice!\n";
}
} while (choice != 4);
return 0;
}
RESULT:
Thus a red black tree has been successfully implemented with insertion and
deletion operations.
Exp No. 8A
Date: 27/02/2025
IMPLEMENTATION OF TRIES TO
SPELLCHECK A TEXT
AIM:
To implement tries to perform spellcheck of a text in C++
ALGORITHM:
1. Initialize TrieNode:
Create children[26] (for lowercase letters).
Set isEndOfWord = false.
2. Insert Word:
Traverse Trie, create nodes if missing.
Mark last node as isEndOfWord = true.
3. Search Word:
Traverse Trie; if any letter is missing, return false.
If traversal completes, check isEndOfWord.
4. Main Execution:
Insert n words.
Search query word.
Print "Correct spelling!" if found, else "Incorrect spelling!".
SOURCE CODE:
#include <iostream>
#include <vector>
using namespace std;
class TrieNode {
public:
TrieNode *children[26]; // For lowercase English letters
bool isEndOfWord;
TrieNode() {
isEndOfWord = false;
for (int i = 0; i < 26; i++)
children[i] = nullptr;
}
};
class Trie {
public:
TrieNode *root;
Trie() {
root = new TrieNode();
}
int main() {
Trie trie;
int n;
cout << "Enter the number of words to insert in dictionary: ";
cin >> n;
if (trie.search(query))
cout << "Correct spelling!\n";
else
cout << "Incorrect spelling!\n";
return 0;
}
RESULT:
Thus, Tries have been implemented to spellcheck the entered word and output has
been verified.
Exp No. 8B
Date: 27/02/2025
IMPLEMENTATION OF TRIES TO
AUTOCOMPLETE A TEXT
AIM:
To implement tries to perform autocomplete of a text in C++
ALGORTIHM:
1. Initialize TrieNode:
Create children[26] (for lowercase letters).
Set isEndOfWord = false.
2. Insert Word:
Traverse Trie, create nodes if missing.
Mark last node as isEndOfWord = true.
3. Autocomplete:
Traverse Trie using the given prefix.
If prefix exists, recursively print all possible completions.
If missing, print "No suggestions found."
4. Main Execution:
Insert n words.
Input prefix and display autocomplete suggestions.
SOURCE CODE:
#include <iostream>
#include <vector>
using namespace std;
class TrieNode {
public:
TrieNode *children[26];
bool isEndOfWord;
TrieNode() {
isEndOfWord = false;
for (int i = 0; i < 26; i++)
children[i] = nullptr;
}
};
class Trie {
public:
TrieNode *root;
Trie() {
root = new TrieNode();
}
int main() {
Trie trie;
int n;
cout << "Enter the number of words to insert in dictionary: ";
cin >> n;
trie.autoComplete(prefix);
return 0;
}
RESULT:
Thus, Tries have been implemented to autocomplete a text and has been verified.
Exp No. 9
Date: 06/03/2025
AIM:
To implement leftist heap using templates in C++.
ALGORTIHM:
2. Merge Operation:
Base cases: Return non-null node if the other is null.
Ensure the smaller root remains.
Recursively merge right subtree.
Swap children if needed and update rank.
3. Insert Element:
Merge root with a new node.
5. Heap Merge:
Merge two heaps, setting the other’s root to nullptr.
6. Display Heap:
Print heap structure recursively.
7. Main Execution
Menu-driven insert, delete, display, and exit options.
SOURCE CODE:
#include <iostream>
Node* root;
public:
LeftistHeap() : root(nullptr) {}
void deleteMin() {
if (!root) {
cout << "Heap is empty.\n";
return;
}
Node* oldRoot = root;
cout << "Deleted minimum element: " << root->data << endl;
root = merge(root->left, root->right);
delete oldRoot;
}
bool isEmpty() {
return root == nullptr;
}
void display() {
if (!root) cout << "Heap is empty.\n";
else display(root);
}
};
int main() {
LeftistHeap<int> heap;
int choice, value;
while (true) {
cout << "\nLeftist Heap Menu:\n";
cout << "1. Insert\n2. Delete Min\n3. Display\n4. Exit\n";
cout << "Enter choice: ";
cin >> choice;
switch (choice) {
OUTPUT:
case 1:
cout << "Enter value: ";
cin >> value;
heap.insert(value);
break;
case 2:
heap.deleteMin();
break;
case 3:
heap.display();
break;
case 4:
return 0;
default:
cout << "Invalid choice!\n";
}
}
}
RESULT:
Thus, a leftist heap has been implemented with insertion,deleting min and display
operation using templates and has been executed successfully.
Exp No. 10
Date: 13/03/25
AIM:
To implement Fibonacci heap using amortized analysis in C++.
ALGORITHM:
1. Insert:
Create a new node.
Insert it into the root list.
Update the minimum node if necessary.
2. Get Minimum:
Return the minimum node's key.
3. Extract Minimum:
If the heap is not empty, remove the minimum node.
Move children of the minimum node to the root list.
Consolidate the heap by linking nodes of the same degree.
Return the key of the extracted minimum node.
4. Consolidate:
Traverse the root list and merge nodes of the same degree by linking
them.
SOURCE CODE:
#include <iostream>
#include <cmath>
using namespace std;
struct Node {
int key, degree;
Node *parent, *child, *left, *right;
bool mark;
Node(int val) {
key = val;
degree = 0;
parent = child = nullptr;
left = right = this;
mark = false;
}
[100]
};
class FibonacciHeap {
private:
Node* minNode;
int nodeCount;
void consolidate() {
int maxDegree = log2(nodeCount) + 1;
Node* A[maxDegree] = {nullptr};
Node* start = minNode;
Node* current = minNode;
do {
Node* x = current;
int d = x->degree;
while (A[d]) {
Node* y = A[d];
if (x->key > y->key) swap(x, y);
link(y, x);
A[d] = nullptr;
d++;
}
A[d] = x;
current = current->right;
} while (current != start);
minNode = nullptr;
for (int i = 0; i < maxDegree; i++) {
if (A[i]) {
if (!minNode) {
minNode = A[i];
minNode->left = minNode->right = minNode;
} else {
A[i]->left = minNode;
A[i]->right = minNode->right;
minNode->right->left = A[i];
minNode->right = A[i];
if (A[i]->key < minNode->key)
minNode = A[i];
}
}
}
}
public:
FibonacciHeap() : minNode(nullptr), nodeCount(0) {}
int getMin() {
return minNode ? minNode->key : -1;
}
int extractMin() {
if (!minNode) return -1;
Node* min = minNode;
if (min->child) {
Node* child = min->child;
do {
Node* nextChild = child->right;
child->left = minNode;
child->right = minNode->right;
minNode->right->left = child;
minNode->right = child;
child->parent = nullptr;
child = nextChild;
} while (child != min->child);
}
min->left->right = min->right;
min->right->left = min->left;
int minValue = min->key;
if (min == min->right) {
minNode = nullptr;
} else {
minNode = min->right;
consolidate();
}
delete min;
nodeCount--;
return minValue;
}
};
int main() {
FibonacciHeap heap;
int choice, value;
while (true) {
cout << "\nFibonacci Heap Menu:\n";
cout << "1. Insert\n2. Get Min\n3. Extract Min\n4. Exit\nEnter choice:
";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter value to insert: ";
cin >> value;
heap.insert(value);
cout << "Inserted " << value << "\n";
break;
case 2:
cout << "Minimum value: " << heap.getMin() << "\n";
break;
case 3:
cout << "Extracted Min: " << heap.extractMin() << "\n";
break;
OUTPUT:
case 4:
cout << "Exiting...\n";
return 0;
default:
cout << "Invalid choice! Try again.\n";
}
}
return 0;
}
RESULT:
Thus Fibonacci Heap has been implemented successfully using
amortized analysis and its output has been verified.
Exp No. 11
Date: 20/03/25
IMPLEMENTATION OF TREAPS
AIM:
To implement Treaps in c++.
ALGORITHM:
1. Start
2. Initialize root as nullptr.
3. Repeat until the user chooses to exit:
Display the menu:
4. Read user choice.
Switch based on choice:
o Case 1: Insert
Prompt user to enter a key.
Call insert(root, key) and update root.
o Case 2: Delete
Prompt user to enter a key.
Call deleteNode(root, key) and update root.
o Case 3: Display
Call inorder(root) to print the Treap in inorder format.
o Case 4: Exit
Print exit message and break the loop.
o Default:
Print invalid choice message.
5. End
SOURCE CODE:
#include <iostream>
#include <cstdlib>
using namespace std;
struct Node {
int key, priority;
Node *left, *right;
Node(int k) {
key = k;
priority = rand();
left = right = nullptr;
}
};
// Inorder traversal
void inorder(Node* root) {
if (root) {
inorder(root->left);
cout << "(" << root->key << ", " << root->priority << ") ";
inorder(root->right);
}
}
int main() {
Node* root = nullptr;
int choice, key;
do {
cout << "\nTreap Menu:\n";
cout << "1. Insert\n";
cout << "2. Delete\n";
cout << "3. Display (Inorder)\n";
cout << "4. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter key to insert: ";
cin >> key;
root = insert(root, key);
break;
case 2:
cout << "Enter key to delete: ";
cin >> key;
OUTPUT:
root = deleteNode(root, key);
break;
case 3:
cout << "Inorder traversal of the Treap:\n";
inorder(root);
cout << endl;
break;
case 4:
cout << "Exiting...\n";
break;
default:
cout << "Invalid choice, try again.\n";
}
} while (choice != 4);
return 0;
}
RESULT:
Thus ,Treaps with insert,delete and display functions has been
implemented and its output has been verified successfully.
Exp No. 12
Date: 27/03/25
AIM:
To implement disjoint sets using union/find algorithm in C++.
ALGORITHM:
SOURCE CODE:
#include <iostream>
using namespace std;
void makeSet() {
for (int i = 0; i < SIZE; i++) {
parent[i] = i;
rankArr[i] = 0;
}
}
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
OUTPUT:
void unionSets(int x, int y) {
int xroot = find(x);
int yroot = find(y);
if (xroot == yroot) return;
if (rankArr[xroot] < rankArr[yroot])
parent[xroot] = yroot;
else if (rankArr[xroot] > rankArr[yroot])
parent[yroot] = xroot;
else {
parent[yroot] = xroot;
rankArr[xroot]++;
}
}
int main() {
makeSet();
unionSets(0, 1);
unionSets(1, 2);
unionSets(2, 3);
unionSets(3, 4);
unionSets(5, 6);
cout << "Are 0 and 4 in the same set? " << (isSameSet(0, 4) ? "Yes" :
"No") << endl;
cout << "Are 5 and 6 in the same set? " << (isSameSet(5, 6) ? "Yes" :
"No") << endl;
return 0;
}
RESULT:
Thus Disjoint set has been implemented using Union Algorithm.
Exp No. 13
Date: 03/04/25
AIM:
To implement a program to check whether an Undirected graph is
Biconnected in C++.
ALGORITHM:
1. Initialize
Create arrays:
o visited[]: Track visited nodes
o disc[]: Discovery time of each node during DFS
o low[]: Lowest discovery time reachable from the node
o parent[]: Parent of each node in DFS tree
Use a set to store articulation points.
2. DFS Traversal
For each unvisited node u:
1. Mark u as visited.
2. Set its discovery time and low value.
3. For each adjacent node v:
o If v is not visited:
Set u as parent of v.
Recursively call DFS for v.
After DFS:
Update low[u] = min(low[u], low[v])
If:
u is root and has more than one child → u
is an articulation point
low[v] >= disc[u] → u is an articulation
point
o If v is visited and not parent of u, update low[u] = min(low[u],
disc[v])
3. Result
If no articulation points were found → graph is biconnected.
Else → print the articulation points.
SOURCE CODE:
#include <iostream>
#include <vector>
#include <set>
using namespace std;
class Graph {
int V;
vector<vector<int>> adj;
void DFS(int u, vector<bool>& visited, vector<int>& disc, vector<int>&
low, vector<int>& parent, set<int>& articulationPoints, int& time) {
visited[u] = true;
disc[u] = low[u] = ++time;
int children = 0;
for (int v : adj[u]) {
if (!visited[v]) {
children++;
parent[v] = u;
DFS(v, visited, disc, low, parent, articulationPoints, time);
low[u] = min(low[u], low[v]);
if (parent[u] == -1 && children > 1)
articulationPoints.insert(u);
if (parent[u] != -1 && low[v] >= disc[u])
articulationPoints.insert(u);
}
else if (v != parent[u]) {
low[u] = min(low[u], disc[v]);
}
}
}
public:
Graph(int V) {
this->V = V;
adj.resize(V);
}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void findArticulationPoints() {
vector<bool> visited(V, false);
vector<int> disc(V), low(V), parent(V, -1);
set<int> articulationPoints;
OUTPUT:
int time = 0;
for (int i = 0; i < V; i++) {
if (!visited[i])
DFS(i, visited, disc, low, parent, articulationPoints, time);
}
if (articulationPoints.empty())
cout << "Graph is Biconnected\n";
else {
cout << "Articulation Points: ";
for (int ap : articulationPoints)
cout << ap << " ";
cout << endl;
}
}
};
int main() {
Graph g(5);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(2, 1);
g.addEdge(0, 3);
g.addEdge(3, 4);
g.findArticulationPoints();
return 0;
}
RESULT:
Thus an program to find whether an undirected graph is biconnected
or not has been executed and its output has been verified.
Exp No. 14
Date: 05/04/25
AIM:
To implement Bellman ford algorithm in C++.
ALGORITHM:
1. Input:
Number of vertices V, number of edges E
List of edges with u, v, and weight
Source vertex src
2. Initialization:
Set distance to all vertices as ∞ (or a large value like 1e9)
Set distance to source vertex as 0
3. Relaxation Step (Repeat V - 1 times):
For each edge (u, v, weight):
o If distance[u] + weight < distance[v], update distance[v] =
distance[u] + weight
4. Negative Cycle Check:
For each edge (u, v, weight):
o If distance[u] + weight < distance[v], report negative weight
cycle
5. Output:
Print shortest distances from source to all vertices
SOURCE CODE:
#include <iostream>
#include <vector>
using namespace std;
struct Edge {
int u, v, w;
};
int main() {
int V, E, src;
cout << "Enter number of vertices: ";
cin >> V;
cout << "Enter number of edges: ";
cin >> E;
cout << "Enter source vertex (0 to " << V-1 << "): ";
OUTPUT:
cin >> src;
vector<Edge> edges(E);
cout << "Enter each edge in format: u v weight\n";
for (int i = 0; i < E; i++) {
cout << "Edge " << i + 1 << ": ";
cin >> edges[i].u >> edges[i].v >> edges[i].w;
}
vector<int> dist(V, 1e9);
dist[src] = 0;
return 0;
}
RESULT:
Thus a program to find the shortest path from a source vertex using
Bellman Ford algorithm has been executed and its output has been verified.
Exp No. 15
Date: 24/04/25
IMPLEMENTATION OF FLOYD-WARSHALL
ALGORTIHM
AIM:
To implement Floyd Warshall algorithm in c++.
ALGORITHM:
1. Input number of vertices V and adjacency matrix graph[V][V], using a large number for
no edge
2. Replace large numbers (>=999999) with infinity (INT_MAX).
3. Set dist = graph.
4. For each vertex k:
For each pair (i, j):
o If dist[i][k] and dist[k][j] are not infinity:
Update dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]).
5. Output the distance matrix:
Print "INF" for infinity, else print distance value.
6. End.
SOURCE CODE:
#include <iostream>
#include <vector>
#include <limits>
int main() {
int V;
cout << "Enter the number of vertices: ";
cin >> V;
floydWarshall(graph, V);
return 0;
}
RESULT:
Thus Floyd-Warshall algorithm has been executed in C++ successfully.
Exp No. 16
Date: 24/04/25
ALGORITHM:
1. Start.
2. Input the number of vertices V and edges E.
3. Input each edge (from, to, capacity) and build the graph.
4. Input the source and sink vertices.
5. Initialize:
residualGraph = graph
maxFlow = 0
6. While there is a path from source to sink in residualGraph (found using BFS):
Find the minimum capacity pathFlow along the found path.
Update the residual capacities:
o Subtract pathFlow along the forward edges.
o Add pathFlow along the reverse edges.
Add pathFlow to maxFlow.
7. Output the maxFlow.
8. End.
SOURCE CODE:
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
while (!q.empty()) {
int u = q.front();
q.pop();
int main() {
int V, E;
cout << "Enter number of vertices and edges: ";
cin >> V >> E;
\
int u, v, capacity;
cin >> u >> v >> capacity;
graph[u][v] = capacity;
}
cout << "Maximum Flow: " << fordFulkerson(graph, source, sink) << endl;
return 0;
}
RESULT:
Thus Ford Fulkerson’s algorithm has been implemented in C++.