0% found this document useful (0 votes)
22 views71 pages

1-1 MTech ADSA Manual

Uploaded by

Lovely Rohith
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views71 pages

1-1 MTech ADSA Manual

Uploaded by

Lovely Rohith
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 71

1.

Functions of Dictionary using Hashing


Aim: To Implement All Functions of Dictionary (ADT) Using Hashing
Description:
1. Division Method
If ‘k’ is a key and ‘m’ is the size of the hash table, the hash function h( ) is
calculated as:
h(k) = k mod m
For example, If the size of a hash table is 10 and k = 112 then h(k) = 112 mod 10
=2. The value of m must not be the powers of 2. This is because the powers of 2 in
binary format are 10, 100, 1000, …. When we find k mod m, we will always get the
lower order p-bits.
if m = 22, k = 17, then h(k) = 17 mod 22 = 10001 mod 100 = 01
if m = 23, k = 17, then h(k) = 17 mod 22 = 10001 mod 100 = 001
if m = 24, k = 17, then h(k) = 17 mod 22 = 10001 mod 100 = 0001
if m = 2p, then h(k) = p lower bits of m

2. Multiplication Method
h(k) = ⌊m(kA mod 1)⌋
where,
kA mod 1 gives the fractional part kA,
⌊ ⌋ gives the floor value
A is any constant. The value of A lies between 0 and 1. But, an optimal choice will
be ≈ (√5-1)/2 suggested by Knuth.

3. Universal Hashing
In Universal hashing, the hash function is chosen at random independent of keys.
Source Code:
#include <iostream>
#include <list>
using namespace std;

class HashTable
{
int capacity;
list<int> *table;

public:
HashTable(int V);
void insertItem(int key, int data);
void deleteItem(int key);
int checkPrime(int n)
{
int i;
if (n == 1 || n == 0)
{
return 0;
}
for (i = 2; i < n / 2; i++)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
}
int getPrime(int n)
{
if (n % 2 == 0)
{
n++;
}
while (!checkPrime(n))
{
n += 2;
}
return n;
}

int hashFunction(int key)


{
return (key % capacity);
}
void displayHash();
};
HashTable::HashTable(int c)
{
int size = getPrime(c);
this->capacity = size;
table = new list<int>[capacity];
}
void HashTable::insertItem(int key, int data)
{
int index = hashFunction(key);
table[index].push_back(data);
}

void HashTable::deleteItem(int key)


{
int index = hashFunction(key);

list<int>::iterator i;
for (i = table[index].begin();
i != table[index].end(); i++)
{
if (*i == key)
break;
}

if (i != table[index].end())
table[index].erase(i);
}

void HashTable::displayHash()
{
for (int i = 0; i < capacity; i++)
{
cout << "table[" << i << "]";
for (auto x : table[i])
cout << " --> " << x;
cout << endl;
}
}

int main()
{
int key[] = {231, 321, 212, 321, 433, 262};
int data[] = {123, 432, 523, 43, 423, 111};
int size = sizeof(key) / sizeof(key[0]);

HashTable h(size);

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


h.insertItem(key[i], data[i]);

h.deleteItem(12);
h.displayHash();
}
Output:
table[0] --> 123
table[1]
table[2] --> 523
table[3] --> 111
table[4]
table[5]
table[6] --> 432 --> 43 --> 423
2. Operations on AVL Trees
Aim: To implement various operations on AVL trees.
Description:
An AVL tree defined as a self-balancing Binary Search Tree (BST) where the
difference between heights of left and right subtrees for any node cannot be more
than one.
Example:

Operations on an AVL Tree:


 Insertion
 Deletion
 Searching
Source Code:
#include<iostream>
#include<stdlib.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define NULL 0
class AVL;
class AVLNODE
{
friend class AVL;
private:
int data;
AVLNODE *left,*right;
int bf;
};
class AVL
{
private:
AVLNODE *root;
public:
AVLNODE *loc,*par;
AVL()
{
root=NULL;
}
int insert(int);
void displayitem();
void display(AVLNODE *);
void removeitem(int);
void remove1(AVLNODE *,AVLNODE *,int);
void remove2(AVLNODE *,AVLNODE *,int);
void search(int x);
void search1(AVLNODE *,int);
};
int AVL::insert(int x)
{
AVLNODE *a,*b,*c,*f,*p,*q,*y,*clchild,*crchild;
int found,unbalanced;
int d;
if(!root) //special case empty tree
{
y=new AVLNODE;
y->data=x;
root=y;
root->bf=0;
root->left=root->right=NULL;
return TRUE;
}
//phase 1:locate insertion point for x.a keeps track of the most
// recent node with balance factor +/-1,and f is the parent of a
// q follows p through the tree.
f=NULL;
a=p=root;
q=NULL;
found=FALSE;
while(p&&!found)
{
//search for insertion point for x
if(p->bf)
{
a=p;
f=q;
}
if(x<p->data) //take left branch
{
q=p;
p=p->left;
}
else if(x>p->data)
{
q=p;
p=p->right;
}
else
{
y=p;
found=TRUE;
}
} //end while
//phase 2:insert and rebalance.x is not in the tree and
// may be inserted as the appropriate child of q.
if(!found)
{
y = new AVLNODE;
y->data=x;
y->left=y->right=NULL;
y->bf=0;
if(x<q->data) //insert as left child
q->left=y;
else
q->right=y; //insert as right child
//adjust balance factors of nodes on path from a to q
//note that by the definition of a,all nodes on this
//path must have balance factors of 0 and so will change
//to +/- d=+1 implies that x is inserted in the left
// subtree of a d=-1 implies
//to that x inserted in the right subtree of a.
if(x>a->data)
{
p=a->right;
b=p;
d=-1;
}
else
{
p=a->left;
b=p;
d=1;
}
while(p!=y)
if(x>p->data) //height of right increases by 1
{
p->bf=-1;
p=p->right;
}
else //height of left increases by 1
{
p->bf=1;
p=p->left;
}
//is tree unbalanced
unbalanced=TRUE;
if(!(a->bf)||!(a->bf+d))
{
//tree still balanced
a->bf+=d;
unbalanced=FALSE;
}
if(unbalanced) //tree unbalanced,determine rotation type
{
if(d==1)
{
//left imbalance
if(b->bf==1) //rotation type LL
{
a->left=b->right;
b->right=a;
a->bf=0;
b->bf=0;
}
else //rotation type LR
{
c=b->right;
b->right=c->left;
a->left=c->right;
c->left=b;
c->right=a;
switch(c->bf)
{
case 1:
a->bf=-1; //LR(b)
b->bf=0;
break;
case -1:
b->bf=1; //LR(c)
a->bf=0;
break;
case 0:
b->bf=0; //LR(a)
a->bf=0;
break;
}
c->bf=0;
b=c; //b is the new root
} //end of LR
} //end of left imbalance
else //right imbalance
{
if(b->bf==-1) //rotation type RR
{
a->right=b->left;
b->left=a;
a->bf=0;
b->bf=0;
}
else //rotation type LR
{
c=b->right;
b->right=c->left;
a->right=c->left;
c->right=b;
c->left=a;
switch(c->bf)
{
case 1:
a->bf=-1; //LR(b)
b->bf=0;
break;
case -1:
b->bf=1; //LR(c)
a->bf=0;
break;
case 0:
b->bf=0; //LR(a)
a->bf=0;
break;
}
c->bf=0;
b=c; //b is the new root
} //end of LR
}
//subtree with root b has been rebalanced and is the new subtree
if(!f)
root=b;
else if(a==f->left)
f->left=b;
else if(a==f->right)
f->right=b;
} //end of if unbalanced
return TRUE;
} //end of if(!found)
return FALSE;
} //end of AVL INSERTION
void AVL::displayitem()
{
display(root);
}
void AVL::display(AVLNODE *temp)
{
if(temp==NULL)
return;
cout<<temp->data<<" ";
display(temp->left);
display(temp->right);
}
void AVL::removeitem(int x)
{
search(x);
if(loc==NULL)
{
cout<<"\nitem is not in tree :(";
return;
}
if(loc->right!=NULL&&loc->left!=NULL)
remove1(loc,par,x);
else
remove2(loc,par,x);
}
void AVL::remove1(AVLNODE *l,AVLNODE *p,int x)
{
AVLNODE *ptr,*save,*suc,*psuc;
ptr=l->right;
save=l;
while(ptr->left!=NULL)
{
save=ptr;
ptr=ptr->left;
}
suc=ptr;
psuc=save;
remove2(suc,psuc,x);
if(p!=NULL)
if(l==p->left)
p->left=suc;
else
p->right=suc;
else
root=l;
suc->left=l->left;
suc->right=l->right;
return;
}
void AVL::remove2(AVLNODE *s,AVLNODE *p,int x)
{
AVLNODE *child;
if(s->left==NULL && s->right==NULL)
child=NULL;
else if(s->left!=NULL)
child=s->left;
else
child=s->right;
if(p!=NULL)
if(s==p->left)
p->left=child;
else
p->right=child;
else
root=child;
}
void AVL::search(int x)
{
search1(root,x);
}
void AVL::search1(AVLNODE *temp,int x)
{
AVLNODE *ptr,*save;
int flag;
if(temp==NULL)
{
cout<<"\nthe tree is empty";
return;
}
if(temp->data==x)
{
cout<<"\nThe item is root and is found :)";
par=NULL;
loc=temp;
par->left=NULL;
par->right=NULL;
return;
}
if( x < temp->data)
{
ptr=temp->left;
save=temp;
}
else
{
ptr=temp->right;
save=temp;
}
while(ptr!=NULL)
{
if(x==ptr->data)
{
flag=1;
cout<<"\nItemfound :)";
loc=ptr;
par=save;
}
if(x<ptr->data)
ptr=ptr->left;
else
ptr=ptr->right;
}
if(flag!=1)
{
cout<<"Item is not there in tree :(";
loc=NULL;
par=NULL;
cout<<loc;
cout<<par;
}
}
int main()
{
AVL a;
int x,y,c;
char ch;
do
{
cout<<"\n1.Insert";
cout<<"\n2.Display";
cout<<"\n3.Delete";
cout<<"\n4.Search";
cout<<"\n5.Exit";
cout<<"\nEnter your choice of operation on AVL Tree :";
cin>>c;
switch(c)
{
case 1:
cout<<"\nEnter an Element to be inserted into Tree :";
cin>>x;
a.insert(x);
break;
case 2:
a.displayitem();
break;
case 3:
cout<<"\nEnter an item for Deletion :";
cin>>y;
a.removeitem(y);
break;
case 4:
cout<<"\nEnter an element to perform Search :";
cin>>c;
a.search(c);
break;
case 5:
exit(0);
break;
default :
cout<<"\nInvalid option try again";
}
cout<<"\nDo u want to continue (y/n) :";
cin>>ch;
}
while(ch=='y'||ch=='Y');<br> return 0;
}
OUTPUT:
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on AVL Tree :1
Enter an Element to be inserted into Tree :10
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on AVL Tree :1
Enter an Element to be inserted into Tree :14
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on AVL Tree :1
Enter an Element to be inserted into Tree :9
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on AVL Tree :2
10 9 14
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on AVL Tree :4
Enter an element to perform Search :14
Itemfound :)
Do u want to continue (y/n) :n
3. Operations on 2-3 Trees
Aim: To implement various operations on 2-3 Trees
Description:
A 2-3 tree is a B-tree of order 3.
Properties of 2-3 tree:
 Nodes with two children are called 2-nodes. The 2-nodes have one data
value and two children.
 Nodes with three children are called 3-nodes. The 3-nodes have two data
values and three children.
 Data is stored in sorted order.
 It is a balanced tree.
 All the leaf nodes are at same level.
 Each node can either be leaf, 2 node, or 3 nodes.
 Always insertion is done at leaf.
Source code:

#include <iostream>
using namespace std;
struct Node {
int key1;
int key2;
Node* child1;
Node* child2;
Node* child3;
bool isTwoNode;
Node(int k1, Node* c1 = nullptr, Node* c2 = nullptr, bool isTwo = true)
: key1(k1), key2(-1), child1(c1), child2(c2), child3(nullptr), isTwoNode(isTwo)
{}

Node(int k1, int k2, Node* c1 = nullptr, Node* c2 = nullptr, Node* c3 = nullptr)
: key1(k1), key2(k2), child1(c1), child2(c2), child3(c3), isTwoNode(false) {}
};

class TwoThreeTree {
private:
Node* root;

// Helper functions
Node* insert(Node* root, int key);
Node* split(Node* root);
Node* merge(Node* root);
Node* findMin(Node* root);
Node* remove(Node* root, int key);
void display(Node* root, int level);

public:
TwoThreeTree() : root(nullptr) {}

void insert(int key);


void remove(int key);
bool search(int key);
void display();
};

void TwoThreeTree::insert(int key) {


root = insert(root, key);
}

Node* TwoThreeTree::insert(Node* root, int key) {


if (!root) {
return new Node(key);
}

if (root->isTwoNode) {
if (key < root->key1) {
root->key2 = root->key1;
root->key1 = key;
} else if (key > root->key1) {
root->key2 = key;
}
} else {
if (key < root->key1) {
root->child1 = insert(root->child1, key);
} else if (key > root->key2) {
root->child3 = insert(root->child3, key);
} else {
root->child2 = insert(root->child2, key);
}
}

if (root->key2 != -1) {
return split(root);
}

return root;
}

Node* TwoThreeTree::split(Node* root) {


Node* newNode = new Node(root->key2, root->child2, root->child3, false);
root->key2 = -1;
root->child2 = nullptr;
root->child3 = nullptr;

if (root == this->root) {
this->root = new Node(root->key1, root, newNode, true);
return this->root;
} else {
return newNode;
}
}

void TwoThreeTree::remove(int key) {


root = remove(root, key);
}

Node* TwoThreeTree::remove(Node* root, int key) {


// Implement the remove operation here
return root;
}

bool TwoThreeTree::search(int key) {


Node* current = root;
while (current) {
if (current->isTwoNode) {
if (key == current->key1) {
return true;
} else if (key < current->key1) {
current = current->child1;
} else {
current = current->child2;
}
} else {
if (key == current->key1 || key == current->key2) {
return true;
} else if (key < current->key1) {
current = current->child1;
} else if (key > current->key2) {
current = current->child3;
} else {
current = current->child2;
}
}
}
return false;
}

void TwoThreeTree::display() {
display(root, 0);
}

void TwoThreeTree::display(Node* root, int level) {


if (root) {
display(root->child3, level + 1);
for (int i = 0; i < level; i++) {
cout << " ";
}
if (root->isTwoNode) {
cout << root->key1 << "\n";
} else {
cout << root->key1 << "," << root->key2 << "\n";
}
display(root->child1, level + 1);
display(root->child2, level + 1);
}
}

int main() {
TwoThreeTree tree;
int x,y,c;
char ch;
do
{
cout<<"\n1.Insert";
cout<<"\n2.Display";
cout<<"\n3.Delete";
cout<<"\n4.Search";
cout<<"\n5.Exit";
cout<<"\nEnter your choice of operation on 2-3 Tree :";
cin>>c;
switch(c)
{
case 1:
cout<<"\nEnter an Element to be inserted into Tree :";
cin>>x;
tree.insert(x);
break;
case 2:
tree.display();
break;
case 3:
cout<<"\nEnter an item for Deletion :";
cin>>y;
tree.remove(y);
break;
case 4:
cout<<"\nEnter an element to perform Search :";
cin>>c;
cout << (tree.search(c) ? "Element Found" : "Element Not Found");
break;
case 5:
exit(0);
break;
default :
cout<<"\nInvalid option try again";
}
cout<<"\nDo u want to continue (y/n) :";
cin>>ch;
}
while(ch=='y'||ch=='Y');
return 0;
}
Output:
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on 2-3 Tree :1
Enter an Element to be inserted into Tree :8
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on 2-3 Tree :1
Enter an Element to be inserted into Tree :11
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on 2-3 Tree :1
Enter an Element to be inserted into Tree :7
Do u want to continue (y/n) :y
1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on 2-3 Tree :2
7
7
8
8,-1
11,-1

Do u want to continue (y/n) :y


1.Insert
2.Display
3.Delete
4.Search
5.Exit
Enter your choice of operation on 2-3 Tree :4
Enter an element to perform Search :8
Element Found
Do u want to continue (y/n) :n
4. Operations on Binary heap
Aim: To implement operations on binary heap.
Description:
A Binary Heap is a complete Binary Tree which is used to store data efficiently to
get the max or min element based on its structure.
A Binary Heap is a Complete Binary Tree.
Example

Source code:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <iterator>
using namespace std;
class BHeap {
private:
vector <int> heap;
int l(int parent);
int r(int parent);
int par(int child);
void heapifyup(int index);
void heapifydown(int index);
public:
BHeap() {}
void Insert(int element);
void DeleteMin();
int ExtractMin();
void showHeap();
int Size();
};
int main() {
BHeap h;
while (1) {
cout<<"1.Insert Element"<<endl;
cout<<"2.Delete Minimum Element"<<endl;
cout<<"3.Extract Minimum Element"<<endl;
cout<<"4.Show Heap"<<endl;
cout<<"5.Exit"<<endl;
int c, e;
cout<<"Enter your choice: ";
cin>>c;
switch(c) {
case 1:
cout<<"Enter the element to be inserted: ";
cin>>e;
h.Insert(e);
break;
case 2:
h.DeleteMin();
break;
case 3:
if (h.ExtractMin() == -1) {
cout<<"Heap is Empty"<<endl;
}
else
cout<<"Minimum Element: "<<h.ExtractMin()<<endl;
break;
case 4:
cout<<"Displaying elements of Hwap: ";
h.showHeap();
break;
case 5:
exit(1);
default:
cout<<"Enter Correct Choice"<<endl;
}
}
return 0;
}
int BHeap::Size() {
return heap.size();
}
void BHeap::Insert(int ele) {
heap.push_back(ele);
heapifyup(heap.size() -1);
}
void BHeap::DeleteMin() {
if (heap.size() == 0) {
cout<<"Heap is Empty"<<endl;
return;
}
heap[0] = heap.at(heap.size() - 1);
heap.pop_back();
heapifydown(0);
cout<<"Element Deleted"<<endl;
}
int BHeap::ExtractMin() {
if (heap.size() == 0) {
return -1;
}
else
return heap.front();
}
void BHeap::showHeap() {
vector <int>::iterator pos = heap.begin();
cout<<"Heap --> ";
while (pos != heap.end()) {
cout<<*pos<<" ";
pos++;
}
cout<<endl;
}
int BHeap::l(int parent) {
int l = 2 * parent + 1;
if (l < heap.size())
return l;
else
return -1;
}
int BHeap::r(int parent) {
int r = 2 * parent + 2;
if (r < heap.size())
return r;
else
return -1;
}
int BHeap::par(int child) {
int p = (child - 1)/2;
if (child == 0)
return -1;
else
return p;
}
void BHeap::heapifyup(int in) {
if (in >= 0 && par(in) >= 0 && heap[par(in)] > heap[in]) {
int temp = heap[in];
heap[in] = heap[par(in)];
heap[par(in)] = temp;
heapifyup(par(in));
}
}
void BHeap::heapifydown(int in) {
int child = l(in);
int child1 = r(in);
if (child >= 0 && child1 >= 0 && heap[child] > heap[child1]) {
child = child1;
}
if (child > 0 && heap[in] > heap[child]) {
int t = heap[in];
heap[in] = heap[child];
heap[child] = t;
heapifydown(child);
}
}

Output
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 1
Enter the element to be inserted: 2
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 1
Enter the element to be inserted: 3
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 1
Enter the element to be inserted: 7
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 1
Enter the element to be inserted: 6
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 4
Displaying elements of Hwap: Heap --> 2 3 7 6
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 3
Minimum Element: 2
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 3
Minimum Element: 2
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 2
Element Deleted
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 4
Displaying elements of Hwap: Heap --> 3 6 7
1.Insert Element
2.Delete Minimum Element
3.Extract Minimum Element
4.Show Heap
5.Exit
Enter your choice: 5

5. Operations on Graphs
Aim: To implement operations on graphs.
Description:
Graph is a non-linear data structure consisting of a set of vertices( V ) and a set of
edges( E ).
The graph is denoted by G(V, E).

Basic Operations on Graphs


Insertion
Deletion
Searching
Traversal
Source code:
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

using namespace std;

class Graph {
private:
int vertices;
list<int> *adjList;

public:
Graph(int V) {
vertices = V;
adjList = new list<int>[V];
}

void addEdge(int v, int w) {


adjList[v].push_back(w);
adjList[w].push_back(v);
}

void deleteEdge(int v, int w) {


adjList[v].remove(w);
adjList[w].remove(v);
}

void traverseGraph() {
for (int i = 0; i < vertices; ++i) {
cout << "Vertex " << i << " -> ";
for (const auto &neighbor : adjList[i]) {
cout << neighbor << " ";
}
cout << endl;
}
}

bool searchEdge(int v, int w) {


return find(adjList[v].begin(), adjList[v].end(), w) != adjList[v].end();
}
};

int main() {
int vertices, choice, v, w;

cout << "Enter the number of vertices in the graph: ";


cin >> vertices;
Graph graph(vertices);

do {
cout << "\nMenu:\n1. Insert Edge\n2. Delete Edge\n3. Traverse Graph\n4.
Search Edge\n0. Exit\n";
cout << "Enter your choice: ";
cin >> choice;

switch (choice) {
case 1:
cout << "Enter the vertices for the edge (space-separated): ";
cin >> v >> w;
graph.addEdge(v, w);
cout << "Edge (" << v << ", " << w << ") inserted.\n";
break;
case 2:
cout << "Enter the vertices for the edge to delete (space-separated): ";
cin >> v >> w;
graph.deleteEdge(v, w);
cout << "Edge (" << v << ", " << w << ") deleted.\n";
break;
case 3:
cout << "Graph Traversal:\n";
graph.traverseGraph();
break;
case 4:
cout << "Enter the vertices for the edge to search (space-separated): ";
cin >> v >> w;
if (graph.searchEdge(v, w))
cout << "Edge (" << v << ", " << w << ") found.\n";
else
cout << "Edge (" << v << ", " << w << ") not found.\n";
break;
case 0:
cout << "Exiting the program.\n";
break;
default:
cout << "Invalid choice. Please try again.\n";
}

} while (choice != 0);

return 0;
}

Output:
Enter the number of vertices in the graph: 4
Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 1
Enter the vertices for the edge (space-separated): 0 1
Edge (0, 1) inserted.

Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 1
Enter the vertices for the edge (space-separated): 1 2
Edge (1, 2) inserted.

Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 3
Graph Traversal:
Vertex 0 -> 1
Vertex 1 -> 0 2
Vertex 2 -> 1
Vertex 3 ->

Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 2
Enter the vertices for the edge to delete (space-separated): 1 2
Edge (1, 2) deleted.

Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 3
Graph Traversal:
Vertex 0 -> 1
Vertex 1 -> 0
Vertex 2 ->
Vertex 3 ->

Menu:
1. Insert Edge
2. Delete Edge
3. Traverse Graph
4. Search Edge
0. Exit
Enter your choice: 0
Exiting the program.
6. Depth First Search
Aim: To implement Depth First Search for a graph non-recursively.
Description:
Depth-First Search (DFS) is a graph traversal algorithm exploring as far as possible
along each branch before backtracking. It systematically visits vertices, marking
them as visited. DFS is efficient for connectivity analysis and topological sorting.
Source code:

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

// Data structure to store a graph edge


struct Edge {
int src, dest;
};

// A class to represent a graph object


class Graph
{
public:
// a vector of vectors to represent an adjacency list
vector<vector<int>> adjList;

// Graph Constructor
Graph(vector<Edge> const &edges, int n)
{
// resize the vector to hold `n` elements of type `vector<int>`
adjList.resize(n);

// add edges to the undirected graph


for (auto &edge: edges)
{
adjList[edge.src].push_back(edge.dest);
adjList[edge.dest].push_back(edge.src);
}
}
};

// Perform iterative DFS on graph starting from vertex `v`


void iterativeDFS(Graph const &graph, int v, vector<bool> &discovered)
{
// create a stack used to do iterative DFS
stack<int> stack;

// push the source node into the stack


stack.push(v);

// loop till stack is empty


while (!stack.empty())
{
// Pop a vertex from the stack
v = stack.top();
stack.pop();

// if the vertex is already discovered yet,


// ignore it
if (discovered[v]) {
continue;
}

// we will reach here if the popped vertex `v` is not discovered yet;
// print `v` and process its undiscovered adjacent nodes into the stack
discovered[v] = true;
cout << v << " ";

// do for every edge (v, u)


// we are using reverse iterator (Why?)
for (auto it = graph.adjList[v].rbegin(); it != graph.adjList[v].rend(); it++)
{
int u = *it;
if (!discovered[u]) {
stack.push(u);
}
}
}
}

int main()
{
// vector of graph edges as per the above diagram
vector<Edge> edges = {
// Notice that node 0 is unconnected
{1, 2}, {1, 7}, {1, 8}, {2, 3}, {2, 6}, {3, 4},
{3, 5}, {8, 9}, {8, 12}, {9, 10}, {9, 11}
// {6, 9} introduces a cycle
};

// total number of nodes in the graph (labelled from 0 to 12)


int n = 13;

// build a graph from the given edges


Graph graph(edges, n);

// to keep track of whether a vertex is discovered or not


vector<bool> discovered(n);

// Do iterative DFS traversal from all undiscovered nodes to


// cover all connected components of a graph
for (int i = 0; i < n; i++)
{
if (discovered[i] == false) {
iterativeDFS(graph, i, discovered);
}
}
return 0; }

Output:

0 1 2 3 4 5 6 7 8 9 10 11 12
7. Breadth First Search
Aim: To implement Breadth First Search for a graph non-recursively.
Description:
Breadth-First Search (BFS) is a graph traversal algorithm exploring vertices level by
level. Starting from a source, it visits neighbors before moving deeper, ensuring
the shortest path is found. BFS is well-suited for finding the shortest path and
connected components.
Source code:
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

// Data structure to store a graph edge


struct Edge {
int src, dest;
};

// A class to represent a graph object


class Graph
{
public:
// a vector of vectors to represent an adjacency list
vector<vector<int>> adjList;

// Graph Constructor
Graph(vector<Edge> const &edges, int n)
{
// resize the vector to hold `n` elements of type `vector<int>`
adjList.resize(n);

// add edges to the undirected graph


for (auto &edge: edges)
{
adjList[edge.src].push_back(edge.dest);
adjList[edge.dest].push_back(edge.src);
}
}
};

// Perform BFS on the graph starting from vertex `v`


void BFS(Graph const &graph, int v, vector<bool> &discovered)
{
// create a queue for doing BFS
queue<int> q;

// mark the source vertex as discovered


discovered[v] = true;

// enqueue source vertex


q.push(v);

// loop till queue is empty


while (!q.empty())
{
// dequeue front node and print it
v = q.front();
q.pop();
cout << v << " ";

// do for every edge (v, u)


for (int u: graph.adjList[v])
{
if (!discovered[u])
{
// mark it as discovered and enqueue it
discovered[u] = true;
q.push(u);
}
}
}
}

int main()
{
// vector of graph edges as per the above diagram
vector<Edge> edges = {
{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {5, 9},
{5, 10}, {4, 7}, {4, 8}, {7, 11}, {7, 12}
// vertex 0, 13, and 14 are single nodes
};

// total number of nodes in the graph (labelled from 0 to 14)


int n = 15;

// build a graph from the given edges


Graph graph(edges, n);

// to keep track of whether a vertex is discovered or not


vector<bool> discovered(n, false);

// Perform BFS traversal from all undiscovered nodes to


// cover all connected components of a graph
for (int i = 0; i < n; i++)
{
if (discovered[i] == false)
{
// start BFS traversal from vertex `i`
BFS(graph, i, discovered);
}
}

return 0;
}
Output:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
8. Prim’s Algorithm
Aim: To implement Prim’s algorithm to generate a min-cost spanning tree.
Description:
Prim's algorithm is a minimum spanning tree algorithm that takes a graph as
input and finds the subset of the edges of that graph which
 form a tree that includes every vertex
 has the minimum sum of weights among all the trees that can be formed
from the graph

The steps for implementing Prim's algorithm are as follows:


1. Initialize the minimum spanning tree with a vertex chosen at random.
2. Find all the edges that connect the tree to new vertices, find the minimum
and add it to the tree
3. Keep repeating step 2 until we get a minimum spanning tree
Source code:
#include <iostream>
using namespace std;

// Data structure to store adjacency list nodes


struct Node
{
int val;
Node* next;
};

// Data structure to store a graph edge


struct Edge {
int src, dest;
};

class Graph
{
// Function to allocate a new node for the adjacency list
Node* getAdjListNode(int dest, Node* head)
{
Node* newNode = new Node;
newNode->val = dest;

// point new node to the current head


newNode->next = head;

return newNode;
}

int N; // total number of nodes in the graph

public:

// An array of pointers to Node to represent the


// adjacency list
Node **head;

// Constructor
Graph(Edge edges[], int n, int N)
{
// allocate memory
head = new Node*[N]();
this->N = N;

// initialize head pointer for all vertices


for (int i = 0; i < N; i++) {
head[i] = nullptr;
}

// add edges to the directed graph


for (unsigned i = 0; i < n; i++)
{
int src = edges[i].src;
int dest = edges[i].dest;

// insert at the beginning


Node* newNode = getAdjListNode(dest, head[src]);

// point head pointer to the new node


head[src] = newNode;

// uncomment the following code for undirected graph

/*
newNode = getAdjListNode(src, head[dest]);

// change head pointer to point to the new node


head[dest] = newNode;
*/
}
}

// Destructor
~Graph() {
for (int i = 0; i < N; i++) {
delete[] head[i];
}

delete[] head;
}
};

// Function to print all neighboring vertices of a given vertex


void printList(Node* ptr)
{
while (ptr != nullptr)
{
cout << " —> " << ptr->val;
ptr = ptr->next;
}
cout << endl;
}
// Graph implementation in C++ without using STL
int main()
{
// an array of graph edges as per the above diagram
Edge edges[] =
{
// pair {x, y} represents an edge from `x` to `y`
{0, 1}, {1, 2}, {2, 0}, {2, 1}, {3, 2}, {4, 5}, {5, 4}
};

// total number of nodes in the graph (labelled from 0 to 5)


int N = 6;

// calculate the total number of edges


int n = sizeof(edges)/sizeof(edges[0]);

// construct graph
Graph graph(edges, n, N);

// print adjacency list representation of a graph


for (int i = 0; i < N; i++)
{
// print given vertex
cout << i;

// print all its neighboring vertices


printList(graph.head[i]);
}

return 0;
}
Output:

0 —> 1
1 —> 2
2 —> 1 —> 0
3 —> 2
4 —> 5
5 —> 4
9. Kruskal’s Algorithm
Aim: To implement Kruskal’s Algorithm to generate a minimum-cost spanning
tree:
Description:
Kruskal's Algorithm is a widely known graph algorithm for MST detection .A
Minimum Spanning Tree is a tree that contains all vertices of graph with n-1 edges
that sum up to give minimum weight.
ALGORITHM
Step 1: Create a forest in such a way that each graph is a separate tree.
Step 2: Create a priority queue Q that contains all the edges of the graph.
Step 3: Repeat Steps 4 and 5 while Q is NOT EMPTY
Step 4: Remove an edge from Q
Step 5: IF the edge obtained in Step 4 connects two different trees, then Add it to
the forest (for combining two trees into one tree).
ELSE
Discard the edge
Step 6: END
Source Code:
#include<iostream>
#include <algorithm>
#include<vector>
using namespace std;
class edge{
public:
int s;
int d;
int w;
edge()
{
}
edge(int src,int des,int wei){
s=src;
d=des;
w=wei;
}
};

bool compare(edge e1,edge e2){


return e1.w<e2.w;
}

int findparent(int i,int* parent ){


if(parent[i]==i)
return i;
return findparent(parent[i],parent);
}

class graph{
public:
int e,n;
edge* v;

graph(int n,int e){


this->n=n;
this->e=e;
v=new edge[e];
for(int i=0;i<e;i++)
{
int x,y,w;
cout<<"ENTER VERTICES AND WEIGHT OF EDGE "<<i+1<<" : ";
cin>>x>>y>>w;
edge e(x,y,w);
v[i]=e;
}
}

edge* unionfind(){
int* parent=new int[n];
for(int i=0;i<n;i++){
parent[i]=i;
}
sort(v,v+e,compare);

edge* output;
output=new edge[n-1];
int count=0,i=0;
while(count!=n-1){
edge c=v[i];
int sourceparent=findparent(v[i].s,parent);
int desparent=findparent(v[i].d,parent);
if(sourceparent!=desparent){
output[count]=c;
parent[sourceparent]=desparent;
count++;
}
i++;
}
int sum=0;
cout<<endl<<"-------MST-------\n";
for(int i=0;i<n-1;i++){
cout<<output[i].s<<" "<<output[i].d<<" "<<output[i].w<<endl;
sum+=output[i].w;
}
cout<<"\nWEIGHT OF MST IS "<<sum;
return output;
}
};

int main(){
int n,e;
cout<<"KRUSKAL'S ALGORITHM\nENTER NUMBER OF VERTICES : ";
cin>>n;
cout<<"ENTER NUMBER OF EDGEES : ";
cin>>e;
graph g(n,e);
edge* mst=g.unionfind();
}
OUTPUT:
KRUSKAL'S ALGORITHM
ENTER NUMBER OF VERTICES : 4
ENTER NUMBER OF EDGEES : 5
ENTER VERTICES AND WEIGHT OF EDGE 1 : 0 1 10
ENTER VERTICES AND WEIGHT OF EDGE 2 : 1 2 6
ENTER VERTICES AND WEIGHT OF EDGE 3 : 0 3 5
ENTER VERTICES AND WEIGHT OF EDGE 4 : 0 3 15
ENTER VERTICES AND WEIGHT OF EDGE 5 : 2 3 4
-------MST-------
234
035
126

WEIGHT OF MST IS 15
10. Dijkstra’s Algorithm
Aim: To implement Dijkstra’s algorithm to find shortest path in the graph
Description:
Dijkstra's algorithm is used to find the shortest paths from a single source vertex
to all other vertices in a weighted graph. The algorithm assumes that all edge
weights are non-negative. Dijkstra's algorithm uses a greedy approach, always
choosing the vertex with the minimum known distance at each step.
Source Code:
#include<iostream>
using namespace std;
int N;
int graph[10][10];
int dist[10];
bool visited[10];
int parent[10];
void createGraph()
{
int i,j,max,u,v,w;
cout<<"Enter the number of nodes : ";
cin>>N;
for(i=0;i<=N;i++)
for(j=0;j<=N;j++)
graph[i][j]=0;
max=N*(N+1);
for(i=0;i<max;i++)
{
cout<<"Enter Edge and Weight : ";
cin>>u>>v>>w;
if(u==-1) break;
else
{
graph[u][v]=w;
graph[v][u]=w;
}
}
}
int minDistance()
{
int min = 10000, minDist;
for (int v = 0; v < N; v++)
if (visited[v] == false && dist[v] <= min)
{
min = dist[v];
minDist = v;
}
return minDist;
}
void printPath(int j)
{
if (parent[j]==-1)
return;
printPath(parent[j]);
cout<<j<<" ";
}
void dijkstra()
{
int src;
cout<<"Enter the Source Node : ";
cin>>src;
for (int i = 0; i < N; i++)
{
parent[0] = -1;
dist[i] = 10000;
visited[i] = false;
}
dist[src] = 0;
for (int count = 0; count < N-1; count++)
{
int u = minDistance();
visited[u] = true;
for (int v = 0; v < N; v++)
if (!visited[v] && graph[u][v] &&
dist[u] + graph[u][v] < dist[v])
{
parent[v] = u;
dist[v] = dist[u] + graph[u][v];
}
}
cout<<"Src->Dest\tDistance\tPath"<<endl;
for (int i = 1; i < N; i++)
{
cout<<src<<"->"<<i<<"\t\t"<<dist[i]<<"\t\t"<<src<<" ";
printPath(i);
cout<<endl;
}
}
int main()
{
createGraph();
dijkstra();
return 0;
}

OUTPUT
Enter the number of nodes : 5
Enter Edge and Weight : 0 1 3
Enter Edge and Weight : 1 2 4
Enter Edge and Weight : 1 3 2
Enter Edge and Weight : 0 3 7
Enter Edge and Weight : 2 3 5
Enter Edge and Weight : 3 4 4
Enter Edge and Weight : 2 4 6
Enter Edge and Weight : -1 -1 -1
Enter the Source Node : 0

Src->Dest Distance Path


0->1 3 01
0->2 7 012
0->3 5 013
0->4 9 0134

You might also like