Ads Graphs
Ads Graphs
a. Vertex insertions
b. Vertex deletions
c. Finding vertex
d. Edge addition and deletion.
#include <stdio.h> #include <stdlib.h>
// Structure for a node in the adjacency list
struct Node { int vertex; struct Node* next; };
// Structure for an undirected graph
struct Graph { int numVertices;
struct Node** adjacencyList; };
// Function to create a new node
struct Node* createNode(int vertex) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE); }
newNode->vertex = vertex;
newNode->next = NULL;
return newNode; }
// Function to create a graph with a given number of vertices
struct Graph* createGraph(int numVertices) {
struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph));
if (graph == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE); }
graph->numVertices = numVertices;
graph->adjacencyList = (struct Node**)malloc(numVertices * sizeof(struct
Node*));
if (graph->adjacencyList == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE); }
for (int i = 0; i < numVertices; ++i) {
graph->adjacencyList[i] = NULL; }
return graph; }
// Function to add an edge between two vertices
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from source to destination
struct Node* newNode = createNode(dest);
newNode->next = graph->adjacencyList[src];
graph->adjacencyList[src] = newNode;
// Add edge from destination to source (since it's an undirected graph)
newNode = createNode(src);
newNode->next = graph->adjacencyList[dest];
graph->adjacencyList[dest] = newNode; }
// Function to delete an edge between two vertices
void deleteEdge(struct Graph* graph, int src, int dest) {
// Delete edge from source to destination
struct Node* current = graph->adjacencyList[src];
struct Node* prev = NULL;
while (current != NULL && current->vertex != dest) {
prev = current;
current = current->next; }
if (current == NULL) {
printf("Edge (%d, %d) not found.\n", src, dest);
return;}
if (prev == NULL) {
graph->adjacencyList[src] = current->next;
} else {
prev->next = current->next; }
free(current);
// Delete edge from destination to source
current = graph->adjacencyList[dest];
prev = NULL;
while (current != NULL && current->vertex != src) {
prev = current;
current = current->next; }
if (prev == NULL) {
graph->adjacencyList[dest] = current->next;
} else {
prev->next = current->next; }
free(current); }
// Function to insert a new vertex into the graph
struct Graph* insertVertex(struct Graph* graph) {
int newVertex = graph->numVertices;
++graph->numVertices;
struct Node** newAdjList = (struct Node**)realloc(graph->adjacencyList,
graph->numVertices * sizeof(struct Node*));
if (newAdjList == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE);}
// Initialize the adjacency list for the new vertex
newAdjList[newVertex] = NULL
// Update the graph with the new adjacency list
graph->adjacencyList = newAdjList;
return graph; }
// Function to delete a vertex from the graph
struct Graph* deleteVertex(struct Graph* graph, int vertex) {
if (vertex < 0 || vertex >= graph->numVertices) {
printf("Vertex %d not found.\n", vertex);
return graph; }
// Delete edges connected to the vertex
struct Node* current = graph->adjacencyList[vertex];
while (current != NULL) {
int connectedVertex = current->vertex;
deleteEdge(graph, vertex, connectedVertex);
current = current->next; }
// Free memory for the adjacency list of the deleted vertex
free(graph->adjacencyList[vertex]);
// Move the adjacency lists of vertices after the deleted vertex one position
backward
for (int i = vertex; i < graph->numVertices - 1; ++i) {
graph->adjacencyList[i] = graph->adjacencyList[i + 1]; }
// Decrement the number of vertices in the graph
--graph->numVertices;
// Resize the adjacency list array
struct Node** newAdjList = (struct Node**)realloc(graph->adjacencyList,
graph->numVertices * sizeof(struct Node*));
if (newAdjList == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
// Update the graph with the resized adjacency list
graph->adjacencyList = newAdjList;
// Update the adjacency lists of vertices after the deleted vertex to reflect the
new indices
for (int i = 0; i < graph->numVertices; ++i) {
current = graph->adjacencyList[i];
while (current != NULL) {
if (current->vertex > vertex) {
current->vertex -= 1; }
current = current->next; } }
return graph; }
// Function to find a vertex in the graph
void findVertex(struct Graph* graph, int vertex) {
if (vertex < 0 || vertex >= graph->numVertices) {
printf("Vertex %d not found.\n", vertex);
} else {
printf("Vertex %d found.\n", vertex); } }
// Function to print the adjacency list representation of the graph
void printGraph(struct Graph* graph) {
printf("Graph (Adjacency List):\n");
for (int i = 0; i < graph->numVertices; ++i) {
struct Node* current = graph->adjacencyList[i];
printf("%d: ", i);
while (current != NULL) {
printf("%d ", current->vertex);
current = current->next;
}
printf("\n");
}
}
int main() {
struct Graph* graph = createGraph(0);
int choice, src, dest, vertex;
do {
printf("\nGraph Operations:\n");
printf("1. Add Edge\n");
printf("2. Delete Edge\n");
printf("3. Insert Vertex\n");
printf("4. Delete Vertex\n");
printf("5. Find Vertex\n");
printf("6. Display Graph\n");
printf("7. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter source and destination vertices for the new edge: ");
scanf("%d %d", &src, &dest);
addEdge(graph, src, dest);
break;
case 2:
printf("Enter source and destination vertices for the edge to delete: ");
scanf("%d %d", &src, &dest);
deleteEdge(graph, src, dest);
break;
case 3:
graph = insertVertex(graph);
printf("Vertex inserted.\n");
break;
case 4:
printf("Enter the vertex to delete: ");
scanf("%d", &vertex);
graph = deleteVertex(graph, vertex);
printf("Vertex deleted.\n");
break;
case 5:
printf("Enter the vertex to find: ");
scanf("%d", &vertex);
findVertex(graph, vertex);
break;
case 6:
printGraph(graph);
break;
case 7:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
} while (choice != 7);
return 0;
}
Experiment 7:
Write a program to perform
a. Linear Probing
#include <stdio.h>
#define SIZE 1
// Function to initialize the hash table
void initializeTable(int table[], int size) {
for (int i = 0; i < size; i++) {
table[i] = -1; // -1 indicates an empty slot
}
}
// Function to display the hash table
void displayTable(int table[], int size) {
printf("Hash Table:\n");
for (int i = 0; i < size; i++) {
if (table[i] != -1) {
printf("Index %d: %d\n", i, table[i]);
} else {
printf("Index %d: Empty\n", i);
}
}
}
// Function to perform linear probing and insert an element into the hash table
void linearProbeInsert(int table[], int size, int key) {
int index = key % size
while (table[index] != -1) {
index = (index + 1) % size; // Linear probing
}
table[index] = key;
}
// Function to perform linear probing and search for an element in the hash table
int linearProbeSearch(int table[], int size, int key) {
int index = key % size;
while (table[index] != -1) {
if (table[index] == key) {
return index; // Element found at this index
}
index = (index + 1) % size; // Linear probing
}
return -1; // Element not found
}
int main() {
int hashTable[SIZE];
initializeTable(hashTable, SIZE);
int choice, key, index;
do {
printf("\nLinear Probing Hash Table Operations:\n");
printf("1. Insert Element\n");
printf("2. Search Element\n");
printf("3. Display Hash Table\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the key to insert: ");
scanf("%d", &key);
linearProbeInsert(hashTable, SIZE, key);
break;
case 2:
printf("Enter the key to search: ");
scanf("%d", &key);
index = linearProbeSearch(hashTable, SIZE, key);
if (index != -1) {
printf("Element found at index %d.\n", index);
} else {
printf("Element not found in the hash table.\n");
}
break;
case 3:
displayTable(hashTable, SIZE);
break;
case 4:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
} while (choice != 4);
return 0;
}
OUTPUT:
Linear Probing Hash Table Operations1. Insert Element2. Search Element3.
Display Hash Table4. Exit Enter your choice: 1 Enter the key to insert: 95
Linear Probing Hash Table Operations: 1. Insert Element 2. Search Element 3.
Display Hash Table 4. Exit Enter your choice: 1Enter the key to insert: 45
Linear Probing Hash Table Operations: 1. Insert Element2. Search Element3.
Display Hash Table4. ExiEnter your choice: Enter the key to search: 65
Element not found in the hash tableLinear Probing Hash Table Operations1.
Insert Element2. Search Element3. Display Hash Table4. ExitEnter your choice:
3Hash Table:Index 0: EmptyIndex 1: EmptyIndex 2: EmptyIndex 3:
EmptyIndex 4: EmptyIndex 5: 95Index 6: 45Index 7: EmptyIndex 8: Empty
Index 9: EmptLinear Probing Hash Table Operations:1. Insert Elemen2. Search
Elemen3. Display Hash Table4. Exit
Enter your choice: 4Exiting the program
b. Random Probing
#include <stdio.h>
#include <stdlib.h>
#include <time.h
#define SIZE 10
// Structure to represent a hash table
struct HashTable {
int keys[SIZE];
int values[SIZE];
};
// Function to initialize the hash table
void initializeHashTable(struct HashTable* table) {
for (int i = 0; i < SIZE; ++i) {
table->keys[i] = -1; // -1 indicates an empty slot
}
}
// Function to perform random probing and insert a key-value pair into the
hash table
void insert(struct HashTable* table, int key, int value) {
int index = key % SIZE;
if (table->keys[index] == -1) {
// Slot is empty, insert the key-value pair
table->keys[index] = key;
table->values[index] = value;
} else {
// Collision occurred, perform random probing
int originalIndex = index;
int probeCount = 0;
do {
// Generate a random offset for probing
int offset = rand() % SIZE;
// Update the index using the random offset
index = (originalIndex + offset) % SIZE
// Check if the new index is empty
if (table->keys[index] == -1) {
// Slot is empty, insert the key-value pair
table->keys[index] = key;
table->values[index] = value;
return;
}
// Increment the probe count
probeCount++;
} while (probeCount < SIZE)
// Unable to find an empty slot after probing, hash table is full
printf("Unable to insert key %d, hash table is full.\n", key);
}
}
// Function to display the contents of the hash table
void displayHashTable(struct HashTable* table) {
printf("Hash Table:\n");
for (int i = 0; i < SIZE; ++i) {
if (table->keys[i] != -1) {
printf("Index %d: Key %d, Value %d\n", i, table->keys[i], table-
>values[i]);
}
}
}
int main() {
struct HashTable hashTable;
initializeHashTable(&hashTable);
srand(time(NULL)); // Seed for random probin
int key, value;
int choice;
do {
printf("\nRandom Probing Hash Table Operations:\n");
printf("1. Insert Key-Value Pair\n");
printf("2. Display Hash Table\n");
printf("3. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter key: ");
scanf("%d", &key);
printf("Enter value: ");
scanf("%d", &value);
insert(&hashTable, key, value);
break;
case 2:
displayHashTable(&hashTable);
break;
case 3:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
return 0;
}
c. Double Hashing
#include <stdio.h>
#include <stdlib.h>
#define TABLE_SIZE 10
// Structure for a hash table entry
struct HashEntry {
int key;
int value;
};
// Structure for the hash table
struct HashTable {
struct HashEntry* table[TABLE_SIZE];
};
// Function to initialize the hash table
void initializeHashTable(struct HashTable* hashtable) {
for (int i = 0; i < TABLE_SIZE; ++i) {
hashtable->table[i] = NULL;
}