You are on page 1of 58

EXPERIMENT NO: 01

Implement functions of Dictionary using Hashing (division method,


Multiplication method, Universal hashing)

Aim:Implement functions of Dictionary using Hashing (division method, Multiplication


method, Universal hashing)

A)Division Method

DESCRIPTION:
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.

PROGRAM:
#include

<stdio.h

#define size 7

int arr[size];

void init() {

int i; for (i = 0; i <

size; i++) arr[i] = -

1;

void insert(int value) { int key = value %

size; if (arr[key] == -1) { arr[key] =

value; printf("%d inserted at arr[%d]\n",

value, key);
} else { printf("Collision: arr[%d] has element %d already!\n",

key, arr[key]); printf("Unable to insert %d\n", value);

void del(int value) {

int key = value % size;

if (arr[key] == value)

arr[key] = -1;

else

printf("%d not present in the hash table\n", value);

} void search(int value) { int

key = value % size; if

(arr[key] == value)

printf("Search Found\n");

else printf("Search Not

Found\n");

} void

print() {

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

printf("arr[%d] = %d\n", i, arr[i]);

} int

main() {

init();

insert(22); // key = 10 % 7 ==> 3

insert(45); // key = 4 % 7 ==> 4

insert(76); // key = 2 % 7 ==> 2

insert(98); // key = 3 % 7 ==> 3


(collision) printf("Hash table\n");

print(); printf("\n"); printf("Deleting

value 45..\n"); del(45); printf("After

the deletion hash table\n"); print();

printf("\n"); printf("Deleting value

9..\n"); del(9); printf("After the

deletion hash table\n");

print();

printf("\n");

printf("Searching value

98..\n"); search(98);

printf("Searching value

10..\n"); search(10); return

0; }

OUTPUT:
22 inserted at arr[1]

45 inserted at arr[3]

76 inserted at arr[6]

98 inserted at

arr[0] Hash table

arr[0] = 98 arr[1]

= 22
arr[2] = -1

arr[3] = 45

arr[4] = -1

arr[5] = -1

arr[6] = 76

Deleting value 45.. After

the deletion hash table

arr[0] = 98 arr[1] = 22

arr[2] = -1

arr[3] = -1

arr[4] = -1

arr[5] = -1

arr[6] = 76

Deleting value 9.. 9 not

present in the hash table

After the deletion hash

table arr[0] = 98 arr[1] =

22

arr[2] = -1

arr[3] = -1
arr[4] = -1

arr[5] = -1

arr[6] = 76

Searching value 98..

Search Found

Searching value 10..

Search Not Found

B) Multiplication method :

DESCRIPTION:

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 ≈
(√51)/2 suggested by Knuth.

PROGRAM:

#include<stdio.h>

#include<math.

h> #define size

7 int arr[size];

void init() {

int i; for (i = 0; i <

size; i++) arr[i] = -

1;
}

void insert(int value) { float const A = 0.618033; int key

= floor(size * ((float)value * A - floor((float)value * A)));

if (arr[key] == -1) { arr[key] = value; printf("%d

inserted at arr[%d]\n", value, key);

} else { printf("Collision: arr[%d] has element %d already!\n",

key, arr[key]); printf("Unable to insert %d\n", value);

void del(int value) {

int key = value % size;

if (arr[key] == value)

arr[key] = -1; else

printf("%d not present

in the hash table\n",

value);

} void search(int value) { int

key = value % size; if

(arr[key] == value)

printf("Search Found\n");

else printf("Search Not

Found\n");

} void

print() {

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

printf("arr[%d] = %d\n", i, arr[i]);


} int

main() {

init(); insert(78); insert(65);

insert(32); insert(12);

printf("Hash table\n"); print();

printf("\n"); printf("Deleting value

32..\n"); del(32); printf("After the

deletion hash table\n"); print();

printf("\n"); printf("Deleting value

65..\n"); del(65);

printf("After the deletion hash

table\n"); print(); printf("\n");

printf("Searching value 65..\n");

search(65); printf("Searching value

66..\n"); search(66); return 0; }

OUTPUT:
78 inserted at arr[1]

Collision: arr[1] has element 78 already!

Unable to insert 65

32 inserted at arr[5]

12 inserted at

arr[2] Hash table

arr[0] = -1 arr[1]

= 78 arr[2] = 12

arr[3] = -1 arr[4]

= -1 arr[5] = 32

arr[6] = -1
Deleting value 32.. 32 not

present in the hash table

After the deletion hash table

arr[0] = -1 arr[1] = 78 arr[2]

= 12 arr[3] = -1 arr[4] = -1

arr[5] = 32

arr[6] = -1

Deleting value 65.. 65 not

present in the hash table

After the deletion hash table

arr[0] = -1 arr[1] = 78 arr[2]

= 12 arr[3] = -1 arr[4] = -1

arr[5] = 32 arr[6] = -1

Searching value 65..

Search Not Found

Searching value 66..

Search Not Found

(c) Universal Hashing:

DESCRIPTION: In Universal hashing, the hash function is chosen at random


independent of keys.

PROGRAM:

#include <stdio.h>

#include <stdlib.h>

struct set {

int key;

int data;
}; struct set *array; int

capacity = 15; int size = 0; int

hashFunction(int key) {

return (key % capacity);} int

checkPrime(int n) { if (n

== 1 || n == 0) { return

0; } for (int 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;} void

init_array() {

capacity = getPrime(capacity); array = (struct set

*) malloc(capacity * sizeof(struct set)); for (int i =

0; i < capacity; i++) { array[i].key = 0;

array[i].data = 0; }

} void insert(int key, int data) { int index =

hashFunction(key); if (array[index].data ==

0) { array[index].key = key;

array[index].data = data; size++;

printf("\nKey (%d) has been inserted\n", key);


} else if (array[index].key == key) {

array[index].data = data; printf("\nKey

(%d) data updated\n", key);

} else { printf("\nCollision

occurred\n");

} void remove_element(int key) {

int index = hashFunction(key); if

(array[index].data == 0) {

printf("\nThis key does not exist\n");

} else {

array[index].key = 0;

array[index].data = 0;

size--;

printf("\nKey (%d) has been removed\n", key);

} void display() {

printf("\nHash Table:\n"); for

(int i = 0; i < capacity; i++) {

if (array[i].data == 0) {

printf("array[%d]: /\n", i);

} else { printf("key: %d, array[%d]: %d\n", array[i].key,

i, array[i].data); } }

} int size_of_hashtable() { return size;


} int main() { int

choice, key, data, n;

int c = 0; init_array();

do {

printf("\n1. Insert item in the Hash Table\n2. Remove item from the Hash Table\n3.

Check the size of Hash Table\n4. Display Hash Table\n\nPlease enter your choice: ");

scanf("%d", &choice); switch (choice) { case 1:

printf("Enter key: ");

scanf("%d", &key);

printf("Enter data: ");

scanf("%d", &data);

insert(key, data); break;

case 2:

printf("Enter the key to delete:

"); scanf("%d", &key);

remove_element(key);

break;

case 3:

n = size_of_hashtable();

printf("Size of Hash Table is: %d\n", n);

break; case 4: display();

break;

default:

printf("Invalid Input\n"); }

printf("\nDo you want to continue? (Press 1 for yes): ");


scanf("%d", &c); } while (c == 1); free(array);

return 0; }

OUTPUT:
1. Insert item in the Hash Table

2. Remove item from the Hash Table

3. Check the size of Hash Table 4. Display Hash Table

Please enter your choice: 55 34

Size of Hash Table is: 0

Do you want to continue? (Press 1 for yes): 1

1. Insert item in the Hash Table

2. Remove item from the Hash Table

3. Check the size of Hash Table 4. Display Hash Table

Please enter your choice: 1

Enter key: 23

Enter data: 345

Key (23) has been inserted

Do you want to continue? (Press 1 for yes): 1

1. Insert item in the Hash Table

2. Remove item from the Hash Table

3. Check the size of Hash Table 4. Display Hash Table

Please enter your choice: 2

Enter the key to delete: 45

This key does not exist

Do you want to continue? (Press 1 for yes): 1

1. Insert item in the Hash Table


2. Remove item from the Hash Table

3. Check the size of Hash Table 4. Display Hash Table Please enter your choice: 4

Hash

Table:

array[0]: /

array[1]: /

array[2]: /

array[3]: /

array[4]: /

array[5]: /

key: 23,

array[6]:

345

array[7]: /

array[8]: /

array[9]: /

array[10]:

array[11]:

array[12]:

array[13]:

array[14]:

array[15]:
/

array[16]:

Do you want to continue? (Press 1 for yes):


EXPERIMENT NO: 02
Implementation Perform various operations i.e., insertions and deletions on
AVL trees
Aim: Implementation Perform various operations i.e., insertions and deletions on AVL trees

DESCRIPTION:
Insertion in AVL trees:
In the AVL tree, the new node is always added as a leaf node. After the insertion of the new
node, it is necessary to modify the balance factor of each node in the AVL tree using the
rotation operations. The algorithm steps of insertion operation in an AVL tree are:

1. Find the appropriate empty subtree where the new value should be added by
comparing the values in the tree
2. Create a new node at the empty subtree
3. The new node is a leaf ad thus will have a balance factor of zero
4. Return to the parent node and adjust the balance factor of each node through the
rotation process and continue it until we are back at the root. Remember that the
modification of the balance factor must happen in a bottom-up fashion

Deletion in AVL trees:

The deletion operation in the AVL tree is the same as the deletion operation in BST. In the
AVL tree, the node is always deleted as a leaf node and after the deletion of the node, the
balance factor of each node is modified accordingly. Rotation operations are used to modify
the balance factor of each node. The algorithm steps of deletion operation in an AVL tree
are:

1. Locate the node to be deleted


2. If the node does not have any child, then remove the node
3. If the node has one child node, replace the content of the deletion node with the
child node and remove the node
4. If the node has two children nodes, find the inorder successor node ‘k' which has no
child node and replace the contents of the deletion node with the ‘k’ followed by
removing the node.
5. Update the balance factor of the AVL tree

PROGRAM:
#include <stdio.h>
#include<stdlib.h>
struct node { int
data; struct node
*left; struct node
*right; int ht;
};
struct node *root = NULL;
struct node *create(int data) {
struct node *new_node = (struct node *)malloc(sizeof(struct
node)); if (new_node == NULL) { printf("\nMemory
can't be allocated\n"); return NULL;
}

new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
return new_node; }
struct node *rotate_left(struct node
*root) { struct node *right_child =
root->right; root->right = right_child-
>left; right_child->left = root; root-
>ht = height(root); right_child->ht =
height(right_child); return
right_child;
}
struct node *rotate_right(struct node
*root) { struct node *left_child = root-
>left; root->left = left_child->right;
left_child->right = root; root->ht =
height(root); left_child->ht =
height(left_child); return left_child; }
int balance_factor(struct node *root) { if
(root == NULL) return 0; int lh =
root->left ? root->left->ht + 1 : 0; int rh
= root->right ? root->right->ht + 1 : 0;
return lh - rh; } int height(struct node
*root) { if (root == NULL) return
0; int lh = root->left ? root->left->ht + 1
: 0; int rh = root->right ? root->right->ht
+ 1 : 0; return (lh > rh) ? lh : rh;
}
struct node *insert(struct node *root, int
data) { if (root == NULL) { struct
node *new_node = create(data); if
(new_node == NULL) return
NULL; root = new_node; } else if
(data > root->data) { root->right =
insert(root->right, data); if
(balance_factor(root) == -2) { if
(data > root->right->data) root =
rotate_left(root); else {
root->right = rotate_right(root->right);
root = rotate_left(root);
}
}
} else { root->left = insert(root-
>left, data); if (balance_factor(root)
== 2) { if (data < root->left-
>data) root =
rotate_right(root); else {
root->left = rotate_left(root->left);
root = rotate_right(root);
}
}
}
root->ht =
height(root); return
root; }
struct node *delete(struct node *root, int x) {
// Implementation of delete function is omitted for brevity.
}
struct node *search(struct node *root, int
key) { if (root == NULL || root->data ==
key) return root; if (key > root-
>data) return search(root->right, key);
return search(root->left, key);
} int main() { int user_choice, data; char
user_continue = 'y'; struct node *result = NULL;
while (user_continue == 'y' || user_continue == 'Y')
{ printf("\n\n------- AVL TREE --------\n");
printf("\n1. Insert"); printf("\n2. Delete");
printf("\n3. Search"); printf("\n7. EXIT");
printf("\n\nEnter Your Choice: "); scanf("%d",
&user_choice); switch (user_choice) {
case 1:
printf("\nEnter data:
"); scanf("%d", &data);
root = insert(root, data);
break; case 2:
printf("\nEnter data: ");
scanf("%d", &data); root =
delete(root, data); break;
case 3:
printf("\nEnter data: ");
scanf("%d", &data); result =
search(root, data); if (result
== NULL) printf("\nNode
not found!\n"); else
printf("\nNode found\n");
break;
case 7:
printf("\n\tProgram
Terminated\n"); return 0;
default:
printf("\n\tInvalid Choice\n");
}
printf("\nDo you want to continue? (y/n): ");
scanf(" %c", &user_continue);
}
return 0;
}
OUTPUT:
------- AVL TREE --------
1. Insert
2. Delete
3. Search
7. EXIT
Enter Your Choice: 1
Enter data: 4
Do you want to continue? (y/n): Y
------- AVL TREE --------
1. Insert
2. Delete
3. Search
7. EXIT
Enter Your Choice: 1
Enter data: 45
Do you want to continue? (y/n):
------ AVL TREE --------
1. Insert
2. Delete
3. Search
7. EXIT
Enter Your Choice: 1
Enter data: 32
Do you want to continue? (y/n): Y
------- AVL TREE --------
1. Insert
2. Delete
3. Search 7. EXIT
Enter Your Choice: 2
Enter data: 3
Do you want to continue? (y/n): Y
------- AVL TREE --------
1. Insert
2. Delete
3. Search 7. EXIT
Enter Your Choice: 3
Enter data: 32
Node found
Do you want to continue? (y/n): Y
------- AVL TREE --------
1. Insert
2. Delete
3. Search 7. EXIT
Enter Your Choice: 7
Program Terminated
EXPERIMENT NO: 03
a)Perform various operations i.e., insertions and deletions on 2-3 trees

AIM:a)Perform various operations i.e., insertions and deletions on 2-3 trees

DESCRIPTION: 2-3 trees are the data structure same as trees, but it has some different
properties like any node can have either single value or double value. So, there are two types
of nodes in 2-3 trees:

Single valued

If a node is single-valued then it has two children. Left children will contain values less than
parent value, and right children will contain values greater than parent value.

Double valued

If a node has two values then it will have three children. Left children will contain values
lesser than the left parent value, and middle children will contain values greater than the left
parent value but less than the right parent value. Right children will contain a value greater
than the right parent's value. Since, each node has either two children or three children, that's
why it is called 2-3 trees. It is a heightbalanced tree, and the reason is all the leaf nodes will
be at the same level. Since, it looks like a binary search tree it also has very good time
complexity in terms of searching the element. The real-life application of this data structure
is into string files in file systems and database systems. In the worst case, a binary search tree
can cost O(n) operation if the height of the tree is near equal to the number of elements, but
in the case of a 2-3 tree, there will be O(log N) time complexity.

Program:

#include <stdio.h>

#include <stdlib.h>

// Node structure for 2-3 tree

struct Node { int data1, data2;

struct Node *left, *middle, *right;

};
// Function to create a new node struct Node* createNode(int data)

{ struct Node* newNode = (struct Node*)malloc(sizeof(struct

Node)); newNode->data1 = data; newNode->data2 = -1; //

Initialize data2 as -1 (considering a 2-node initially) newNode-

>left = newNode->middle = newNode->right = NULL; return

newNode;

// Function to split a 4-node into two 2-nodes void splitNode(struct Node* parent,

struct Node* child, int data, struct Node* newChild) { if (data < child->data1) {

newChild->data1 = child->data2; // Move larger value to the new child child-

>data2 = -1;

} else { newChild-

>data1 = data;

newChild->left = child->middle; child-

>middle = NULL;

if (parent->data2 == -1) { // parent is a 2-

node if (parent->data1 < newChild-

>data1) { parent->data2 = newChild-

>data1; parent->right = newChild;


} else { parent->data2 =

parent->data1; parent->data1 =

newChild->data1; parent->right

= parent->middle; parent-

>middle = newChild;

} else { // parent is a 3-node if (parent-

>data1 < newChild->data1) { parent-

>data2 = parent->data2; parent->data1

= newChild->data1; parent->right =

newChild; } else if (parent->data2 <

newChild->data1) { parent->data1 =

newChild->data1; parent->right =

parent->middle; parent->middle =

newChild;

} else { parent->data1 =

parent->data2; parent->data2 =

parent->data1; parent->data1 =

newChild->data1; parent->right

= parent->middle; parent-

>middle = newChild;

}
}

// Function to insert data into a 2-3 tree

struct Node* insert(struct Node* root, int

data) { if (!root) { return

createNode(data);

if (root->data2 == -1) { // 2-node

if (data < root->data1) { root-

>left = insert(root->left, data); } else

if (data > root->data1) { root-

>right = insert(root->right, data);

} else { // 3-node if (data < root->data1) {

root->left = insert(root->left, data);

splitNode(root, root->left, root->data1, root->middle);

root->data1 = root->middle->data1; } else if (data

> root->data2) { root->right = insert(root->right,

data); splitNode(root, root->right, data, root-

>middle);

} else { root->middle = insert(root->middle, data);

splitNode(root, root->middle, root->middle->data1, root->right);


} }

return root;

// Function to print inorder traversal of 2-3 tree

void inorder(struct Node* root) {

if (root) { inorder(root-

>left); printf("%d ", root-

>data1); if (root->data2 != -

1) { printf("%d ", root-

>data2);

inorder(root->middle);

inorder(root->right);

// Main function to test the 2-3 tree

operations int main() { struct Node*

root = NULL;

int data;

char choice;
do { printf("Enter data to insert: ");

scanf("%d", &data); root = insert(root, data);

printf("Inorder traversal after insertion: ");

inorder(root); printf("\nDo you want to insert

more data? (y/n): "); scanf(" %c", &choice);

} while (choice == 'y' || choice == 'Y');

return 0;

OUTPUT:

Enter data to insert: 77

Inorder traversal after insertion: 77

Do you want to insert more data? (y/n): Y

Enter data to insert: 65

Inorder traversal after insertion: 65 77

Do you want to insert more data? (y/n): Y

Enter data to insert: 86 Inorder

traversal after insertion: 65 77 86

Do you want to insert more data? (y/n): Y

Enter data to insert: 2

Inorder traversal after insertion: 2 65 77 86

Do you want to insert more data? (y/n): N


EXPERIMENT NO: 04
Implement operations on binary heap.
AIM: a)Perform various operations i.e., insertions and deletions on 2-3 trees

DESCRIPTION:
There are several types of heaps, however in this chapter, we are going to discuss binary
heap. A binary heap is a data structure, which looks similar to a complete binary tree.
Heap data structure obeys ordering properties discussed below. Generally, a Heap is
represented by an array. In this chapter, we are representing a heap by H.
As the elements of a heap is stored in an array, considering the starting index as 1, the
position of the parent node of ith element can be found at ⌊ i/2 ⌋ . Left child and right child
of ith node is at position 2i and 2i + 1.
A binary heap can be classified further as either a max-heap or a min-heap based on the
ordering property.

Max-Heap
In this heap, the key value of a node is greater than or equal to the key value of the highest
child. Hence, H[Parent(i)] ≥ H[i]

Min-Heap
In mean-heap, the key value of a node is lesser than or equal to the key value of the lowest
child. Hence, H[Parent(i)] ≤ H[i]
In this context, basic operations are shown below with respect to Max-Heap. Insertion and
deletion of elements in and from heaps need rearrangement of elements. Hence, Heapify
function needs to be called.

PROGRAM:
#include <stdio.h>
int size = 0;
void swap(int *a, int
*b) { int temp = *b;
*b = *a;
*a = temp;
}
void heapify(int array[], int size, int i)
{ int largest = i; int l = 2 * i + 1;
int r = 2 * i + 2; if (l < size &&
array[l] > array[largest]) largest
= l;
if (r < size && array[r] >
array[largest]) largest = r; if
(largest != i) { swap(&array[i],
&array[largest]); heapify(array,
size, largest);
}
}
void insert(int array[], int newNum)
{ if (size == 0) {

array[0] = newNum; size


+= 1; } else { array[size] =
newNum; size += 1; for
(int i = size / 2 - 1; i >= 0; i--) {
heapify(array, size, i); } }}
void deleteRoot(int array[], int num) {
int i; for (i = 0; i < size; i++) { if
(num == array[i]) break; } if (i ==
size) { printf("Element not found in
the heap\n"); return; }
swap(&array[i], &array[size - 1]); size -
= 1; for (int i = size / 2 - 1; i >= 0; i--) {
heapify(array, size, i); }
}
void printArray(int array[], int size)
{ for (int i = 0; i < size; ++i)
printf("%d ", array[i]);
printf("\n"); } int main() { int
array[10]; insert(array, 3);
insert(array, 4); insert(array, 9);
insert(array, 5); insert(array, 2);
printf("Max-Heap array: ");
printArray(array, size);
deleteRoot(array, 4); printf("After
deleting an element: ");
printArray(array, size); return 0;
}
OUTPUT:
Max-Heap array: 7 6 5 2 1
After deleting an element: 7 6 5 2
EXPERIMENT NO: 05
Implement operations on graphs
a) Vertex insertion
b) Vertex deletion
c) Finding vertex
d) Edge addition and deletion
AIM: Implement operations on graphs
a) Vertex insertion
b) Vertex deletion
c) Finding vertex
d) Edge addition and deletion

PROGRAM:
#include<stdio.h> #include<stdlib.h> struct Edge; struct Vertex {

int info; struct Vertex *nextVertex; /*next vertex in the linked list

of vertices*/ struct Edge *firstEdge; /*first Edge of the adjacency

list of this vertex*/

}*start = NULL; struct Edge { struct Vertex

*destVertex; /*Destination vertex of the Edge*/ struct

Edge *nextEdge; /*next Edge of the adjacency list*/

};

struct Vertex *findVertex(int u);

void insertVertex(int u); void

insertEdge(int u, int v); void

deleteEdge(int u, int v); void

deleteIncomingEdges(int u);

void deleteVertex(int u); void

display(); int main() { int

choice, u, origin, destin;

while(1) {
printf("\n1.Insert a Vertex\n");

printf("2.Insert an Edge\n");

printf("3.Delete a Vertex\n");

printf("4.Delete an Edge\n");

printf("5.Display\n");

printf("6.Exit\n");

printf("\nEnter your choice : ");

scanf("%d", &choice);

switch(choice) { case 1:

printf("\nEnter a vertex to be inserted

: "); scanf("%d", &u);

insertVertex(u); break; case 2:

printf("\nEnter an Edge to be inserted

: "); scanf("%d %d", &origin, &destin);

insertEdge(origin, destin); break;

case 3:

printf("\nEnter a vertex to be deleted : ");

scanf("%d", &u);

/*This function deletes all edges coming to this vertex*/

deleteIncomingEdges(u);

/*This function deletes the vertex from the vertex

list*/ deleteVertex(u); break; case

4:

printf("\nEnter an edge to be deleted

: "); scanf("%d %d", &origin, &destin);

deleteEdge(origin, destin); break;


case 5: display(); break;

case 6:

exit(1);

default:

printf("\nWrong choice\n");

break;

}/*End of

switch*/ }/*End of

while*/ return 0;

}/*End of main()*/ void

insertVertex(int u) { struct

Vertex *tmp, *ptr; tmp =

malloc(sizeof(struct Vertex));

tmp->info = u; tmp->nextVertex

= NULL; tmp->firstEdge =

NULL; if(start == NULL) {

start = tmp; return; } ptr

= start;

while(ptr->nextVertex != NULL)

ptr = ptr->nextVertex; ptr-

>nextVertex = tmp; }/*End of

insertVertex()*/ void deleteVertex(int u)

{ struct Vertex *tmp, *q; struct

Edge *p, *temporary; if(start ==

NULL) { printf("\nNo vertices to

be deleted\n"); return;
} if(start->info == u)/* Vertex to be deleted is first

vertex of list*/

{
tmp = start; start = start->nextVertex }

else /* Vertex to be deleted is in between or at last

*/

{ q=

start;

while(q->nextVertex != NULL) { if(q-

>nextVertex->info == u)

break;

q = q->nextVertex;

if(q->nextVertex == NULL) {

printf("Vertex not found\n");

return; } else { tmp =

q->nextVertex; q->nextVertex

= tmp->nextVertex;

}}

/*Before freeing the node tmp, free all edges going from this

vertex */ p = tmp->firstEdge; while(p != NULL) {

temporary = p; p = p->nextEdge; free(temporary);

free(tmp);

}/*End of deleteVertex()*/
void deleteIncomingEdges(int

u) { struct Vertex *ptr; struct

Edge *q, *tmp; ptr = start;

while(ptr != NULL) { if(ptr->firstEdge == NULL)

/*Edge list for vertex ptr is empty*/

{ ptr = ptr->nextVertex; continue;

/* continue searching in other Edge lists */

if(ptr->firstEdge->destVertex->info == u) {

tmp = ptr->firstEdge; ptr->firstEdge = ptr-

>firstEdge->nextEdge; free(tmp);

continue; /* continue searching in other Edge lists */

q = ptr->firstEdge; while(q-

>nextEdge != NULL) { if(q-

>nextEdge->destVertex->info == u) {

tmp = q->nextEdge; q->nextEdge =

tmp->nextEdge;

free(tmp);

continue;

q = q->nextEdge;

ptr = ptr->nextVertex;

}/*End of while*/

}/*End of

deleteIncomingEdges()*/ struct
Vertex *findVertex(int u) {

struct Vertex *ptr, *loc; ptr =

start; while(ptr != NULL) {

if(ptr->info == u ) { loc

= ptr; return loc;

} else ptr =

ptr->nextVertex;

loc = NULL;

return loc;

}/*End of findVertex()*/

void insertEdge(int u, int v)

{ struct Vertex *locu,

*locv; struct Edge *ptr,

*tmp;

locu = findVertex(u);

locv = findVertex(v);

if(locu == NULL ) { printf("\nStart vertex not

present, first insert vertex %d\n", u); return;

if(locv == NULL ) { printf("\nEnd vertex not present,

first insert vertex %d\n", v); return;

}
tmp = malloc(sizeof(struct Edge));

tmp->destVertex = locv; tmp-

>nextEdge = NULL;

if(locu->firstEdge == NULL)

{ locu->firstEdge = tmp;

return;

ptr = locu->firstEdge; while(ptr-

>nextEdge != NULL) ptr = ptr-

>nextEdge; ptr->nextEdge = tmp;

}/*End of insertEdge()*/

void deleteEdge(int u, int v)

{ struct Vertex *locu;

struct Edge *tmp, *q;

locu = findVertex(u);

if(locu == NULL ) {

printf("\nStart vertex not present\n");

return;

if(locu->firstEdge == NULL) {

printf("\nEdge not present\n");

return;

}
if(locu->firstEdge->destVertex->info == v)

{ tmp = locu->firstEdge; locu-

>firstEdge = locu->firstEdge->nextEdge;

free(tmp); return;

q = locu->firstEdge; while(q-

>nextEdge != NULL) { if(q-

>nextEdge->destVertex->info == v) {

tmp = q->nextEdge; q->nextEdge =

tmp->nextEdge;

free(tmp);

return;

q = q->nextEdge;

printf("\nThis Edge not present in the graph\n");

void display(){

struct Vertex *ptr;

struct Edge *q;

ptr = start;

while(ptr!=NULL)

printf("%d ->",ptr-

>info); q = ptr-

>firstEdge;

while(q!=NULL)
{

printf(" %d",q->destVertex-

>info); q = q->nextEdge; }

printf("\n"); ptr = ptr->nextVertex;

}/*End of display()*/

OUTPUT:
1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 1

Enter a vertex to be inserted : 1

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 1

Enter a vertex to be inserted : 2

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge
5.Display

6.Exit

Enter your choice : 2

Enter an Edge to be inserted : 1 2

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 5

1 -> 2
2 ->
1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 1

Enter a vertex to be inserted : 3

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display
6.Exit

Enter your choice : 1

Enter a vertex to be inserted : 4


1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 1

Enter a vertex to be inserted : 5

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 2

Enter an Edge to be inserted : 2 3

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit

Enter your choice : 2

Enter an Edge to be inserted : 3 4

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge
5.Display
6.Exit

Enter your choice : 2

Enter an Edge to be inserted : 4 5

1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge
5.Display
6.Exit

Enter your choice : 5

1 -> 2
2 -> 3
3 -> 4
4 -> 5
5 ->
1.Insert a Vertex

2.Insert an Edge

3.Delete a Vertex

4.Delete an Edge

5.Display

6.Exit
Enter your choice : 6
EXPERIMENT NO: 06

Implement Depth First Search for a graph non recursively


AIM: Implement Depth First Search for a graph non recursively
DESCRIPTION:
Depth-first search is an algorithm for traversing or searching tree or graph data
structures. The algorithm starts at the root node (selecting some arbitrary node as the
root node in the case of a graph) and explores as far as possible along each branch before
backtracking.

Follow the below steps to solve the problem:

Create a recursive function that takes the index of the node and a visited array.

Mark the current node as visited and print the node.


Traverse all the adjacent and unmarked nodes and call the recursive function with the index
of the adjacent node.

PROGRAM:
#include <stdio.h>

#include

<stdlib.h> struct

node { int

vertex; struct

node* next;

};

struct node* createNode(int

v); struct Graph { int

numVertices; int* visited;

struct node** adjLists;

};

void DFS(struct Graph* graph, int vertex) struct

Graph* createGraph(int vertices); void

addEdge(struct Graph* graph, int src, int dest);

void printGraph(struct Graph* graph); int


main() { struct Graph* graph =

createGraph(4); addEdge(graph, 0, 1);

addEdge(graph, 0, 2); addEdge(graph, 1, 2);

addEdge(graph, 2, 3);

printGraph(graph);

DFS(graph, 2);

return 0; }

struct node* createNode(int v) { struct node*

newNode = malloc(sizeof(struct node));

newNode->vertex = v; newNode->next = NULL;

return newNode;

struct Graph* createGraph(int vertices) { struct

Graph* graph = malloc(sizeof(struct Graph)); graph-

>numVertices = vertices; graph->adjLists =

malloc(vertices * sizeof(struct node*)); graph-

>visited = malloc(vertices * sizeof(int));

int i;

for (i = 0; i < vertices; i++) { graph-

>adjLists[i] = NULL; graph->visited[i]

= 0;

} return

graph; }

void addEdge(struct Graph* graph, int src, int

dest) { struct node* newNode =

createNode(dest); newNode->next = graph-


>adjLists[src]; graph->adjLists[src] =

newNode; newNode = createNode(src);

newNode->next = graph->adjLists[dest];

graph->adjLists[dest] = newNode;} void

printGraph(struct Graph* graph) {

int v;

for (v = 0; v < graph->numVertices; v++) {

struct node* temp = graph->adjLists[v];

printf("\n Adjacency list of vertex %d\n ", v);

while (temp) { printf("%d -> ", temp-

>vertex); temp = temp->next; }

printf("\n"); }} void DFS(struct Graph* graph,

int vertex) { struct node* adjList = graph-

>adjLists[vertex]; struct node* temp =

adjList; graph->visited[vertex] = 1;

printf("Visited %d \n", vertex); while (temp

!= NULL) { int connectedVertex = temp-

>vertex; if (graph-

>visited[connectedVertex] == 0) {

DFS(graph, connectedVertex); } temp

= temp->next; }}

OUTPUT:
Adjacency list of vertex 0

2 -> 1 ->

Adjacency list of vertex 1

2 -> 0 ->

Adjacency list of vertex 2


3 -> 1 -> 0 ->

Adjacency list of vertex 3

2 ->

Visited 2

Visited 3

Visited 1

Visited 0
EXPERIMENT NO: 07
Implement Breadth First Search for a graph non recursively

AIM: Implement Breadth First Search for a graph non recursively

DESCRIPTION:

BFS algorithm
A standard BFS implementation puts each vertex of the graph into one of two categories:
1.Visited
2.Not Visited
The purpose of the algorithm is to mark each vertex as visited while avoiding cycles.
The algorithm works as follows:
1.Start by putting any one of the graph's vertices at the back of a queue.
2.Take the front item of the queue and add it to the visited list.
3.Create a list of that vertex's adjacent nodes. Add the ones which aren't in the visited list to
the back of the queue.
4.Keep repeating steps 2 and 3 until the queue is empty.

PROGRAM:
#include <stdio.h> int n, i, j, visited[10],

queue[10], front = -1, rear = -1; int adj[10][10];

void bfs(int v) { for (i = 1; i <= n; i++) if

(adj[v][i] && !visited[i]) queue[++rear] =

i; if (front <= rear) { visited[queue[front]]

= 1; bfs(queue[front++]); }} int main() {

int v; printf("Enter the number of

vertices: "); scanf("%d", &n); for

(i = 1; i <= n; i++) { queue[i] =

0; visited[i] = 0;

}
printf("Enter graph data in matrix

form:\n"); for (i = 1; i <= n; i++)

for (j = 1; j <= n; j++) scanf("%d", &adj[i][j]);

printf("Enter the starting vertex: "); scanf("%d", &v);

bfs(v); printf("The nodes which are reachable are:\n");

int found = 0; for (i = 1; i <= n; i++) { if (visited[i])

{ printf("%d\t", i); found = 1; } } if

(!found) printf("BFS is not possible. Not all nodes

are reachable"); return 0; }

OUTPUT:
Enter the number of vertices: 4

Enter graph data in matrix form:

4452

2619

9547

1380

Enter the starting vertex: 2

The nodes which are reachable are:

1 2 3 4
EXPERIMENT NO: 08

Implement Prim’s algorithm to generate a min-cost spanning tree.

AIM:Implement Prim’s algorithm to generate a min-cost spanning tree.


ALGORITHM:
Step1: Determine an arbitrary vertex as the starting vertex of the MST.
Step2: Follow steps 3 to 5 till there are vertices that are not included in the MST (known as
fringe vertex).
Step3: Find edges connecting any tree vertex with the fringe vertices.
Step4: Find the minimum among these edges.

Step5: Add the chosen edge to the MST if it does not form any cycle.

Step6: Return the MST and exit

PROGRAM
#include<stdio.h>

#include<stdbool.h>

#define INF

9999999 #define V

5 int G[V][V] = {

{0, 9, 75, 0, 0},

{9, 4, 45, 99, 82},

{75, 95, 0, 71, 66},

{0, 29, 33, 0, 1},

{0, 42, 96, 31, 0}

}; int main() { int no_edge; int

selected[V]; memset(selected, false,

sizeof(selected)); no_edge = 0;

selected[0] = true; int x; int y;

printf("Edge : Weight\n");
while (no_edge < V - 1) { int

min = INF; x = 0; y = 0;

for (int i = 0; i < V; i++) { if

(selected[i]) { for (int j = 0;

j < V; j++) { if

(!selected[j] && G[i][j]) {

if (min > G[i][j]) {

min = G[i][j]; x = i;

y = j; } }

printf("%d - %d : %d\n", x, y,

G[x][y]); selected[y] = true;

no_edge++;

return 0;

OUTPUT:
Edge : Weight

0-1:9

1 - 2 : 45

2 - 4 : 66

4 - 3 : 31
EXPERIMENT NO : 09
Implement Krushkal’s algorithm to generate a min-cost spanning tree.
AIM:Implement Krushkal’s algorithm to generate a min-cost spanning tree
ALGORITHM:
1. Sort all the edges in non-decreasing order of their weight.
2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far.
If the cycle is not formed, include this edge. Else, discard it. 3. Repeat step#2 until
there are (V-1) edges in the spanning tree.

PROGRAM
#include <stdio.h>

#define MAX 30

typedef struct edge {

int u, v, w; } edge;

typedef struct

edge_list { edge

data[MAX];

int n;

} edge_list;

edge_list elist;

int Graph[MAX][MAX], n;

edge_list spanlist; void kruskalAlgo(); int

find(int belongs[], int vertexno); void

applyUnion(int belongs[], int c1, int c2);

void sort(); void print();


// Applying Kruskal's Algorithm

void kruskalAlgo() { int

belongs[MAX], i, j, cno1, cno2;

elist.n = 0; for (i = 1; i < n; i++)

for (j = 0; j < i; j++) { if

(Graph[i][j] != 0) {

elist.data[elist.n].u = i;

elist.data[elist.n].v = j;

elist.data[elist.n].w = Graph[i][j];

elist.n++;

} } sort(); for (i = 0; i <

n; i++) belongs[i] = i; spanlist.n =

0; for (i = 0; i < elist.n; i++) {

cno1 = find(belongs, elist.data[i].u);

cno2 = find(belongs, elist.data[i].v);

if (cno1 != cno2) {

spanlist.data[spanlist.n] = elist.data[i];

spanlist.n = spanlist.n + 1;

applyUnion(belongs, cno1, cno2);

} int find(int belongs[], int

vertexno) { return

(belongs[vertexno]);
} void applyUnion(int belongs[], int c1,

int c2) {

int i; for (i = 0; i <

n; i++) if

(belongs[i] == c2)

belongs[i] = c1;

} void

sort() {

int i, j;

edge temp; for (i = 1; i < elist.n; i++)

for (j = 0; j < elist.n - 1; j++) if

(elist.data[j].w > elist.data[j + 1].w) {

temp = elist.data[j]; elist.data[j]

= elist.data[j + 1]; elist.data[j +

1] = temp; }

} void print() { int i, cost = 0; for (i = 0; i < spanlist.n; i++) {

printf("\n%d - %d : %d", spanlist.data[i].u, spanlist.data[i].v,

spanlist.data[i].w); cost = cost + spanlist.data[i].w;

printf("\nSpanning tree cost: %d", cost);

} int main() { int

i, j, total_cost; n

= 6;

Graph[0][0] = 0;

Graph[0][1] = 42;
Graph[0][2] = 41;

Graph[0][3] = 0;

Graph[0][4] = 0;

Graph[0][5] = 0;

Graph[0][6] = 0;

Graph[1][0] = 47;

Graph[1][1] = 0;

Graph[1][2] = 27;

Graph[1][3] = 0;

Graph[1][4] = 0;

Graph[1][5] = 0;

Graph[1][6] = 0;

Graph[2][0] = 46;

Graph[2][1] = 21;

Graph[2][2] = 0;

Graph[2][3] = 32;

Graph[2][4] = 41;

Graph[2][5] = 0;

Graph[2][6] = 0;

Graph[3][0] = 0;

Graph[3][1] = 0;

Graph[3][2] = 33;

Graph[3][3] = 0;

Graph[3][4] = 3;

Graph[3][5] = 0;
Graph[3][6] = 0;

Graph[4][0] = 0;

Graph[4][1] = 0;

Graph[4][2] = 44;

Graph[4][3] = 33;

Graph[4][4] = 0;

Graph[4][5] = 0; Graph[4][6] = 0;

Graph[5][0] = 0;

Graph[5][1] = 0;

Graph[5][2] = 8;

Graph[5][3] = 0;

Graph[5][4] = 16;

Graph[5][5] = 0;

Graph[5][6] = 0;

kruskalAlgo();

print(); }

OUTPUT:
5-2:8

5 - 4 : 16

2 - 1 : 21

3 - 2 : 33

2 - 0 : 46

Spanning tree cost: 124


EXPERIMENT NO : 10
Implement Dijkstra’s algorithm to find shortest path in the graph.
AIM: Implement Dijkstra’s algorithm to find shortest path in the graph.
DESCRIPTION:
Like Prim’s MST, generate a SPT (shortest path tree) with a given source as a root. Maintain
two sets, one set contains vertices included in the shortest-path tree, other set includes
vertices not yet included in the shortest-path tree. At every step of the algorithm, find a vertex
that is in the other set (set not yet included) and has a minimum distance from the source.
Follow the steps below to solve the problem:
• Create a set sptSet (shortest path tree set) that keeps track of vertices included in
the shortest path tree, i.e., whose minimum distance from the source is calculated
and finalized. Initially, this set is empty.
• Assign a distance value to all vertices in the input graph. Initialize all distance
values as INFINITE. Assign the distance value as 0 for the source vertex so that it
is picked first.
• While sptSet doesn’t include all vertices
• Pick a vertex u that is not there in sptSet and has a minimum distance value.
• Include u to sptSet.
• Then update the distance value of all adjacent vertices of u.
• To update the distance values, iterate through all adjacent vertices.
• For every adjacent vertex v, if the sum of the distance value of u (from source)
and weight of edge u-v, is less than the distance value of v, then update the
distance value of v.
PROGRAM:
#include <limits.h>
#include <stdbool.h>
#include <stdio.h> #define V 9 int
minDistance(int dist[], bool sptSet[]) {
int min = INT_MAX, min_index; for
(int v = 0; v < V; v++) if (sptSet[v]
== false && dist[v] <= min) min
= dist[v], min_index = v; return
min_index;
}
void printSolution(int dist[]) {
printf("Vertex \t\t Distance from
Source\n"); for (int i = 0; i < V; i++)
printf("%d \t\t\t\t %d\n", i, dist[i]);
}
void dijkstra(int graph[V][V], int
src) { int dist[V]; bool
sptSet[V]; for (int i = 0; i < V;
i++)
dist[i] = INT_MAX, sptSet[i] = false;
dist[src] = 0;

for (int count = 0; count < V - 1;


count++) { int u = minDistance(dist,
sptSet); sptSet[u] = true; for (int
v = 0; v < V; v++)

if (!sptSet[v] && graph[u][v] && dist[u] !=


INT_MAX && dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
printSolution(dist);
} int main() { int
graph[V][V] = {
{0, 4, 0, 0, 0, 7, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 22, 0},
{0, 8, 0, 5, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{8, 0, 0, 9, 0, 10, 0, 0, 0},
{1, 0, 4, 3, 10, 0, 2, 0, 0},
{0, 0, 2, 0, 0, 2, 0, 1, 6},
{8, 11, 0, 3, 0, 0, 1, 0,
7}, {9, 0, 2, 0, 5, 0, 6,
7, 0}}; dijkstra(graph, 0);
return 0;
}
OUTPUT:
Vertex Distance from Source
0 0
1 4
2 11
3 10
4 17
5 7
6 9
7 8
8 1
EXPERIMENT NO : 11
Implement pattern matching using Boyer-Moore algorithm.
AIM: Implement pattern matching using Boyer-Moore algorithm.
DESCRIPTION:
Knuth-Morris and Pratt introduce a linear time algorithm for the string matching problem. A
matching time of O (n) is achieved by avoiding comparison with an element of 'S' that have
previously been involved in comparison with some element of the pattern 'p' to be matched.
i.e., backtracking on the string 'S' never occurs

Components of KMP Algorithm:

1. The Prefix Function (Π): The Prefix Function, Π for a pattern encapsulates knowledge
about how the pattern matches against the shift of itself. This information can be used to
avoid a useless shift of the pattern 'p.' In other words, this enables avoiding backtracking
of the string 'S.' 2. The KMP Matcher: With string 'S,' pattern 'p' and prefix function 'Π'
as inputs, find the occurrence of 'p' in 'S' and returns the number of shifts of 'p' after
which occurrences are found.

PROGRAM:
#include<stdio.h>

#include<string.h>

#include<stdlib.h>

void computeLPSArray(char *pat, int M, int

*lps); void KMPSearch(char *pat, char *txt) {

int M = strlen(pat); int N = strlen(txt); int

*lps = (int *) malloc(sizeof(int) * M); int j

= 0;

computeLPSArray(pat, M, lps);

int i = 0; while (i < N) { if (pat[j] ==

txt[i]) { j++; i++; } if (j ==

M) { printf("Found pattern at index %d

\n", i - j); j = lps[j - 1];

}
else if (i < N && pat[j] != txt[i])

{ if (j != 0)

j = lps[j - 1];

else i=i+

1; } } free(lps); }

void computeLPSArray(char *pat, int M, int *lps) {

int len = 0; int i;

lps[0] = 0; i = 1;

while (i < M) { if

(pat[i] == pat[len]) {

len++; lps[i] =

len; i++; }

else { if (len !=

0) { len =

lps[len - 1]; } else

{ lps[i] = 0;

i++; } }

} int

main() {

char *txt =

"HIIHOWAREYOUWHATAREYOUDOING"; char

*pat = "WHATARE"; KMPSearch(pat, txt); return

0;

OUTPUT:
Found pattern at index 12
EXPERIMENT NO : 12
Implement Knuth-Morris-Pratt algorithm for pattern matching.

AIM: Implement Knuth-Morris-Pratt algorithm for pattern


matching.

Boyer Moore algorithm also preprocesses the pattern.

Boyer Moore is a combination of the following two approaches.

1. Bad Character Heuristic


2. Good Suffix Heuristic
Both of the above heuristics can also be used independently to search a pattern in a text. Let
us first understand how two independent approaches work together in the Boyer Moore
algorithm. If we take a look at the Naive algorithm, it slides the pattern over the text one by
one. KMP algorithm does preprocessing over the pattern so that the pattern can be shifted
by more than one. The Boyer Moore algorithm does preprocessing for the same reason. It
processes the pattern and creates different arrays for each of the two heuristics. At every
step, it slides the pattern by the max of the slides suggested by each of the two heuristics. So
it uses greatest offset suggested by the two heuristics at every step.

PROGRAM:
# include <limits.h>

# include <string.h>

# include <stdio.h>

# define NO_OF_CHARS 256

int max (int a, int b) { return (a > b)? a: b;

} void badCharHeuristic( char *str, int

size, int

badchar[NO_OF_CHARS])

int i;

for (i = 0; i < NO_OF_CHARS; i++)

badchar[i] = -1; for

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

badchar[(int) str[i]] = i;
}

void search( char *txt, char *pat)

{ int m =

strlen(pat); int n

= strlen(txt);

int badchar[NO_OF_CHARS];

badCharHeuristic(pat, m, badchar); int s = 0;

while(s <= (n - m))

{ int j = m-1; while(j >=

0 && pat[j] == txt[s+j])

j--;

if (j < 0)

printf("\n pattern occurs at shift = %d",

s); s += (s+m < n)? m-

badchar[txt[s+m]] : 1;

} else s += max(1, j

- badchar[txt[s+j]]);

} int main() { char txt[] =

"HIMYSELFDINISHA"; char

pat[] = "MY"; search(txt, pat);

return 0; }

OUTPUT:
pattern occurs at shift = 2

You might also like