diff --git a/Graphs/Makefile b/Graphs/Makefile new file mode 100644 index 0000000..070cef6 --- /dev/null +++ b/Graphs/Makefile @@ -0,0 +1,44 @@ +CC=gcc +CFLAGS=-Wall -Werror -std=c99 +all: BFS Bellman-Ford DFS Dijkstra Floyd-Warshall bfsQueue dfsRecursive euler hamiltonian strongly_connected_components topologicalSort transitiveClosure + + +BFS: BFS.c + $(CC) -o BFS BFS.c +Bellman-Ford: Bellman-Ford.c + $(CC) -o Bellman-Ford Bellman-Ford.c +DFS: DFS.c + $(CC) -o DFS DFS.c +Dijkstra: Dijkstra.c + $(CC) -o Dijkstra Dijkstra.c +Floyd-Warshall: Floyd-Warshall.c + $(CC) -o Floyd-Warshall Floyd-Warshall.c +Graph.o: Graph.c Graph.h + $(CC) $(CFLAGS) -c Graph.c +bfsQueue: Graph.o queue.o bfsQueue.o + $(CC) Graph.o queue.o bfsQueue.o -o bfsQueue +bfsQueue.o: bfsQueue.c + $(CC) $(CFLAGS) -c bfsQueue.c +dfsRecursive: Graph.o queue.o dfsRecursive.o + $(CC) Graph.o queue.o dfsRecursive.o -o dfsRecursive +dfsRecursive.o: dfsRecursive.c + $(CC) -c dfsRecursive.c +euler: Graph.o euler.o + $(CC) Graph.o euler.o -o euler +euler.o: euler.c + $(CC) $(CFLAGS) -c euler.c +hamiltonian: Graph.o hamiltonian.o + $(CC) Graph.o hamiltonian.o -o hamiltonian +hamiltonian.o: hamiltonian.c + $(CC) $(CFLAGS) -c hamiltonian.c +queue.o: queue.c queue.h + $(CC) $(CFLAGS) -c queue.c +strongly_connected_components: strongly_connected_components.c + $(CC) -o strongly_connected_components strongly_connected_components.c +topologicalSort: topologicalSort.c + $(CC) -o topologicalSort topologicalSort.c +transitiveClosure: transitiveClosure.c + $(CC) -o transitiveClosure transitiveClosure.c + +By Vishal Kumar +Github: vishaaal diff --git a/Graphs/bellman_ford.c b/Graphs/bellman_ford.c new file mode 100644 index 0000000..9cd4179 --- /dev/null +++ b/Graphs/bellman_ford.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include + +// Structure for storing edge +struct Edge +{ + int src, dst, weight; +}; + +// Structure for storing a graph +struct Graph +{ + int vertexNum; + int edgeNum; + struct Edge *edges; +}; + +// Constructs a graph with V vertices and E edges +void createGraph(struct Graph *G, int V, int E) +{ + G->vertexNum = V; + G->edgeNum = E; + G->edges = (struct Edge *)malloc(E * sizeof(struct Edge)); +} + +// Adds the given edge to the graph +void addEdge(struct Graph *G, int src, int dst, int weight) +{ + static int ind; + struct Edge newEdge; + newEdge.src = src; + newEdge.dst = dst; + newEdge.weight = weight; + G->edges[ind++] = newEdge; +} + +// Utility function to find minimum distance vertex in mdist +int minDistance(int mdist[], int vset[], int V) +{ + int minVal = INT_MAX, minInd; + for (int i = 0; i < V; i++) + if (vset[i] == 0 && mdist[i] < minVal) + { + minVal = mdist[i]; + minInd = i; + } + + return minInd; +} + +// Utility function to print distances +void print(int dist[], int V) +{ + printf("\nVertex Distance\n"); + for (int i = 0; i < V; i++) + { + if (dist[i] != INT_MAX) + printf("%d\t%d\n", i, dist[i]); + else + printf("%d\tINF", i); + } +} + +// The main function that finds the shortest path from given source +// to all other vertices using Bellman-Ford.It also detects negative +// weight cycle +void BellmanFord(struct Graph *graph, int src) +{ + int V = graph->vertexNum; + int E = graph->edgeNum; + int dist[V]; + + // Initialize distances array as INF for all except source + // Intialize source as zero + for (int i = 0; i < V; i++) dist[i] = INT_MAX; + dist[src] = 0; + + // Calculate shortest path distance from source to all edges + // A path can contain maximum (|V|-1) edges + for (int i = 0; i <= V - 1; i++) + for (int j = 0; j < E; j++) + { + int u = graph->edges[j].src; + int v = graph->edges[j].dst; + int w = graph->edges[j].weight; + + if (dist[u] != INT_MAX && dist[u] + w < dist[v]) + dist[v] = dist[u] + w; + } + + // Iterate inner loop once more to check for negative cycle + for (int j = 0; j < E; j++) + { + int u = graph->edges[j].src; + int v = graph->edges[j].dst; + int w = graph->edges[j].weight; + + if (dist[u] != INT_MAX && dist[u] + w < dist[v]) + { + printf( + "Graph contains negative weight cycle. Hence, shortest " + "distance not guaranteed."); + return; + } + } + + print(dist, V); + + return; +} + +// Driver Function +int main() +{ + int V, E, gsrc; + int src, dst, weight; + struct Graph G; + printf("Enter number of vertices: "); + scanf("%d", &V); + printf("Enter number of edges: "); + scanf("%d", &E); + createGraph(&G, V, E); + for (int i = 0; i < E; i++) + { + printf("\nEdge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + printf("Enter weight: "); + scanf("%d", &weight); + addEdge(&G, src, dst, weight); + } + printf("\nEnter source:"); + scanf("%d", &gsrc); + BellmanFord(&G, gsrc); + + return 0; +} diff --git a/Graphs/bfs.c b/Graphs/bfs.c new file mode 100644 index 0000000..e53831b --- /dev/null +++ b/Graphs/bfs.c @@ -0,0 +1,195 @@ +#include +#include +#define SIZE 40 +// Assume max size of graph is 40 nodes +struct queue +{ + int items[SIZE]; + int front; + int rear; +}; + +// Some declarations +struct queue *createQueue(); +void enqueue(struct queue *q, int); +int dequeue(struct queue *q); +void display(struct queue *q); +int isEmpty(struct queue *q); +int pollQueue(struct queue *q); + +// Structure to create a graph node +struct node +{ + int vertex; + struct node *next; +}; + +struct node *createNode(int); + +// Graph data structure +struct Graph +{ + int numVertices; + struct node **adjLists; + int *visited; +}; +struct Graph *createGraph(int vertices); +void addEdge(struct Graph *graph, int src, int dest); +void printGraph(struct Graph *graph); +void bfs(struct Graph *graph, int startVertex); + +int main() +{ + int vertices, edges, source, i, src, dst; + printf("Enter the number of vertices\n"); + scanf("%d", &vertices); + struct Graph *graph = createGraph(vertices); + printf("Enter the number of edges\n"); + scanf("%d", &edges); + for (i = 0; i < edges; i++) + { + printf("Edge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + addEdge(graph, src, dst); + } + printf("Enter source of bfs\n"); + scanf("%d", &source); + bfs(graph, source); + + // Uncomment below part to get a ready-made example + /*struct Graph* graph = createGraph(6); + addEdge(graph, 0, 1); + addEdge(graph, 0, 2); + addEdge(graph, 1, 2); + addEdge(graph, 1, 4); + addEdge(graph, 1, 3); + addEdge(graph, 2, 4); + addEdge(graph, 3, 4); + bfs(graph,0);*/ + + return 0; +} +void bfs(struct Graph *graph, int startVertex) +{ + struct queue *q = createQueue(); + + // Add to visited list and put in queue + graph->visited[startVertex] = 1; + enqueue(q, startVertex); + printf("Breadth first traversal from vertex %d is:\n", startVertex); + + // Iterate while queue not empty + while (!isEmpty(q)) + { + printf("%d ", pollQueue(q)); + int currentVertex = dequeue(q); + + struct node *temp = graph->adjLists[currentVertex]; + // Add all unvisited neighbours of current vertex to queue to be printed + // next + while (temp) + { + int adjVertex = temp->vertex; + // Only add if neighbour is unvisited + if (graph->visited[adjVertex] == 0) + { + graph->visited[adjVertex] = 1; + enqueue(q, adjVertex); + } + temp = temp->next; + } + } +} +// Memory for a graph node +struct node *createNode(int v) +{ + struct node *newNode = malloc(sizeof(struct node)); + newNode->vertex = v; + newNode->next = NULL; + return newNode; +} +// Allocates memory for graph data structure, in adjacency list format +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; +} +// Adds bidirectional edge to graph +void addEdge(struct Graph *graph, int src, int dest) +{ + // Add edge from src to dest + struct node *newNode = createNode(dest); + newNode->next = graph->adjLists[src]; + graph->adjLists[src] = newNode; + + // Add edge from dest to src; comment it out for directed graph + newNode = createNode(src); + newNode->next = graph->adjLists[dest]; + graph->adjLists[dest] = newNode; +} +// Allocates memory for our queue data structure +struct queue *createQueue() +{ + struct queue *q = malloc(sizeof(struct queue)); + q->front = -1; + q->rear = -1; + return q; +} +// Checks for empty queue +int isEmpty(struct queue *q) +{ + if (q->rear == -1) + return 1; + else + return 0; +} +// Inserts item at start of queue +void enqueue(struct queue *q, int value) +{ + if (q->rear == SIZE - 1) + printf("\nQueue is Full!!"); + else + { + if (q->front == -1) + q->front = 0; + q->rear++; + q->items[q->rear] = value; + } +} +// Returns item at front of queue and removes it from queue +int dequeue(struct queue *q) +{ + int item; + if (isEmpty(q)) + { + printf("Queue is empty"); + item = -1; + } + else + { + item = q->items[q->front]; + q->front++; + if (q->front > q->rear) + { + q->front = q->rear = -1; + } + } + return item; +} + +// Returns element at front of queue +int pollQueue(struct queue *q) { return q->items[q->front]; } diff --git a/Graphs/bfs_queue.c b/Graphs/bfs_queue.c new file mode 100644 index 0000000..5612381 --- /dev/null +++ b/Graphs/bfs_queue.c @@ -0,0 +1,124 @@ +#include +#include +#include "Graph.h" +#include "queue.h" + +#define MAX_NODES 1000 + +int visited[MAX_NODES]; // array to store visiting order + // indexed by vertex 0..nV-1 + +bool findPathBFS(Graph g, int nV, Vertex src, Vertex dest) +{ + Vertex v; + for (v = 0; v < nV; v++) visited[v] = -1; + + visited[src] = src; + queue Q = newQueue(); + QueueEnqueue(Q, src); + while (!QueueIsEmpty(Q)) + { + v = QueueDequeue(Q); + Vertex w; + for (w = 0; w < nV; w++) + if (adjacent(g, v, w) && visited[w] == -1) + { + visited[w] = v; + if (w == dest) + return true; + else + QueueEnqueue(Q, w); + } + } + return false; +} + +int main(void) +{ + int V = 10; + Graph g = newGraph(V); + + Edge e; + e.v = 0; + e.w = 1; + insertEdge(g, e); + e.v = 0; + e.w = 2; + insertEdge(g, e); + e.v = 0; + e.w = 5; + insertEdge(g, e); + e.v = 1; + e.w = 5; + insertEdge(g, e); + e.v = 2; + e.w = 3; + insertEdge(g, e); + e.v = 3; + e.w = 4; + insertEdge(g, e); + e.v = 3; + e.w = 5; + insertEdge(g, e); + e.v = 3; + e.w = 8; + insertEdge(g, e); + e.v = 4; + e.w = 5; + insertEdge(g, e); + e.v = 4; + e.w = 7; + insertEdge(g, e); + e.v = 4; + e.w = 8; + insertEdge(g, e); + e.v = 5; + e.w = 6; + insertEdge(g, e); + e.v = 7; + e.w = 8; + insertEdge(g, e); + e.v = 7; + e.w = 9; + insertEdge(g, e); + e.v = 8; + e.w = 9; + insertEdge(g, e); + + int src = 0, dest = 6; + if (findPathBFS(g, V, src, dest)) + { + Vertex v = dest; + while (v != src) + { + printf("%d - ", v); + v = visited[v]; + } + printf("%d\n", src); + } + return 0; +} + +// By +// .----------------. .----------------. .----------------. +// .-----------------. .----------------. .----------------. +// | .--------------. || .--------------. || .--------------. || +// .--------------. | | .--------------. || .--------------. | | | _________ | +// || | _____ _____ | || | __ | || | ____ _____ | | | | ____ ____ +// | || | ____ | | | | | _ _ | | || ||_ _||_ _|| || | / \ +// | || ||_ \|_ _| | | | | |_ || _| | || | .' `. | | | | |_/ | | +// \_| | || | | | | | | || | / /\ \ | || | | \ | | | | | | | +// |__| | | || | / .--. \ | | | | | | | || | | ' ' | | || | +// / ____ \ | || | | |\ \| | | | | | | __ | | || | | | | | | | +// | | _| |_ | || | \ `--' / | || | _/ / \ \_ | || | _| |_\ |_ +// | | | | _| | | |_ | || | \ `--' / | | | | |_____| | || | `.__.' +// | || ||____| |____|| || ||_____|\____| | | | | |____||____| | || | `.____.' +// | | | | | || | | || | | || | | | | | +// | || | | | | '--------------' || '--------------' || +// '--------------' || '--------------' | | '--------------' || '--------------' +// | +// '----------------' '----------------' '----------------' +// '----------------' '----------------' '----------------' + +// Email : z5261243@unsw.edu.au +// hhoanhtuann@gmail.com diff --git a/Graphs/dfs.c b/Graphs/dfs.c new file mode 100644 index 0000000..f711075 --- /dev/null +++ b/Graphs/dfs.c @@ -0,0 +1,134 @@ +#include +#include + +// A vertex of the graph +struct node +{ + int vertex; + struct node *next; +}; +// Some declarations +struct node *createNode(int v); +struct Graph +{ + int numVertices; + int *visited; + struct node * + *adjLists; // we need int** to store a two dimensional array. Similary, + // we need struct node** to store an array of Linked lists +}; +struct Graph *createGraph(int); +void addEdge(struct Graph *, int, int); +void printGraph(struct Graph *); +void dfs(struct Graph *, int); + +int main() +{ + int vertices, edges, source, i, src, dst; + printf("Enter the number of vertices\n"); + scanf("%d", &vertices); + struct Graph *graph = createGraph(vertices); + printf("Enter the number of edges\n"); + scanf("%d", &edges); + for (i = 0; i < edges; i++) + { + printf("Edge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + addEdge(graph, src, dst); + } + printf("Enter source of DFS\n"); + scanf("%d", &source); + printf("DFS from %d is:\n", source); + dfs(graph, source); + printf("\n"); + + // Uncomment below part to get a ready-made example + /*struct Graph* graph = createGraph(4); + addEdge(graph, 0, 1); + addEdge(graph, 0, 2); + addEdge(graph, 1, 2); + addEdge(graph, 2, 3); + printf("DFS from 0 is:\n"); + dfs(graph,0); + printf("\n");*/ + + return 0; +} +// Recursive dfs approach +void dfs(struct Graph *graph, int vertex) +{ + struct node *adjList = graph->adjLists[vertex]; + struct node *temp = adjList; + + // Add vertex to visited list and print it + graph->visited[vertex] = 1; + printf("%d ", vertex); + + // Recursively call the dfs function on all unvisited neighbours + while (temp != NULL) + { + int connectedVertex = temp->vertex; + if (graph->visited[connectedVertex] == 0) + { + dfs(graph, connectedVertex); + } + temp = temp->next; + } +} +// Allocate memory for a node +struct node *createNode(int v) +{ + struct node *newNode = malloc(sizeof(struct node)); + newNode->vertex = v; + newNode->next = NULL; + return newNode; +} +// Allocate memory for the entire graph structure +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; +} +// Creates a bidirectional graph +void addEdge(struct Graph *graph, int src, int dest) +{ + // Add edge from src to dest + struct node *newNode = createNode(dest); + newNode->next = graph->adjLists[src]; + graph->adjLists[src] = newNode; + + // Add edge from dest to src + newNode = createNode(src); + newNode->next = graph->adjLists[dest]; + graph->adjLists[dest] = newNode; +} +// Utility function to see state of graph at a given time +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"); + } +} diff --git a/Graphs/dfs_recursive.c b/Graphs/dfs_recursive.c new file mode 100644 index 0000000..d62f0c1 --- /dev/null +++ b/Graphs/dfs_recursive.c @@ -0,0 +1,103 @@ +#include +#include +#include "Graph.h" + +#define MAX_NODES 1000 + +int visited[MAX_NODES]; // array to store visiting order + // indexed by vertex 0..nV-1 + +bool dfsPathCheck(Graph g, int nV, Vertex v, Vertex dest) +{ + Vertex w; + for (w = 0; w < nV; w++) + if (adjacent(g, v, w) && visited[w] == -1) + { + visited[w] = v; + if (w == dest) + return true; + else if (dfsPathCheck(g, nV, w, dest)) + return true; + } + return false; +} + +bool findPathDFS(Graph g, int nV, Vertex src, Vertex dest) +{ + Vertex v; + for (v = 0; v < nV; v++) visited[v] = -1; + visited[src] = src; + return dfsPathCheck(g, nV, src, dest); +} + +int main(void) +{ + int V = 6; + Graph g = newGraph(V); + + Edge e; + e.v = 0; + e.w = 1; + insertEdge(g, e); + e.v = 0; + e.w = 4; + insertEdge(g, e); + e.v = 0; + e.w = 5; + insertEdge(g, e); + e.v = 5; + e.w = 4; + insertEdge(g, e); + e.v = 4; + e.w = 2; + insertEdge(g, e); + e.v = 4; + e.w = 3; + insertEdge(g, e); + e.v = 5; + e.w = 3; + insertEdge(g, e); + e.v = 1; + e.w = 2; + insertEdge(g, e); + e.v = 3; + e.w = 2; + insertEdge(g, e); + + int src = 0, dest = 5; + if (findPathDFS(g, V, src, dest)) + { + Vertex v = dest; + while (v != src) + { + printf("%d - ", v); + v = visited[v]; + } + printf("%d\n", src); + } + return 0; +} + +// By +// .----------------. .----------------. .----------------. +// .-----------------. .----------------. .----------------. +// | .--------------. || .--------------. || .--------------. || +// .--------------. | | .--------------. || .--------------. | | | _________ | +// || | _____ _____ | || | __ | || | ____ _____ | | | | ____ ____ +// | || | ____ | | | | | _ _ | | || ||_ _||_ _|| || | / \ +// | || ||_ \|_ _| | | | | |_ || _| | || | .' `. | | | | |_/ | | +// \_| | || | | | | | | || | / /\ \ | || | | \ | | | | | | | +// |__| | | || | / .--. \ | | | | | | | || | | ' ' | | || | +// / ____ \ | || | | |\ \| | | | | | | __ | | || | | | | | | | +// | | _| |_ | || | \ `--' / | || | _/ / \ \_ | || | _| |_\ |_ +// | | | | _| | | |_ | || | \ `--' / | | | | |_____| | || | `.__.' +// | || ||____| |____|| || ||_____|\____| | | | | |____||____| | || | `.____.' +// | | | | | || | | || | | || | | | | | +// | || | | | | '--------------' || '--------------' || +// '--------------' || '--------------' | | '--------------' || '--------------' +// | +// '----------------' '----------------' '----------------' +// '----------------' '----------------' '----------------' + +// Email : z5261243@unsw.edu.au +// hhoanhtuann@gmail.com diff --git a/Graphs/dijkstra.c b/Graphs/dijkstra.c new file mode 100644 index 0000000..b1faa47 --- /dev/null +++ b/Graphs/dijkstra.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +// Structure for storing a graph +struct Graph +{ + int vertexNum; + int **edges; +}; + +// Constructs a graph with V vertices and E edges +void createGraph(struct Graph *G, int V) +{ + G->vertexNum = V; + G->edges = (int **)malloc(V * sizeof(int *)); + for (int i = 0; i < V; i++) + { + G->edges[i] = (int *)malloc(V * sizeof(int)); + for (int j = 0; j < V; j++) G->edges[i][j] = INT_MAX; + G->edges[i][i] = 0; + } +} + +// Adds the given edge to the graph +void addEdge(struct Graph *G, int src, int dst, int weight) +{ + G->edges[src][dst] = weight; +} + +// Utility function to find minimum distance vertex in mdist +int minDistance(int mdist[], int vset[], int V) +{ + int minVal = INT_MAX, minInd; + for (int i = 0; i < V; i++) + if (vset[i] == 0 && mdist[i] < minVal) + { + minVal = mdist[i]; + minInd = i; + } + + return minInd; +} + +// Utility function to print distances +void print(int dist[], int V) +{ + printf("\nVertex Distance\n"); + for (int i = 0; i < V; i++) + { + if (dist[i] != INT_MAX) + printf("%d\t%d\n", i, dist[i]); + else + printf("%d\tINF", i); + } +} + +// The main function that finds the shortest path from given source +// to all other vertices using Dijkstra's Algorithm.It doesn't work on negative +// weights +void Dijkstra(struct Graph *graph, int src) +{ + int V = graph->vertexNum; + int mdist[V]; // Stores updated distances to vertex + int vset[V]; // vset[i] is true if the vertex i included + // in the shortest path tree + + // Initialise mdist and vset. Set distance of source as zero + for (int i = 0; i < V; i++) mdist[i] = INT_MAX, vset[i] = 0; + + mdist[src] = 0; + + // iterate to find shortest path + for (int count = 0; count < V - 1; count++) + { + int u = minDistance(mdist, vset, V); + vset[u] = 1; + + for (int v = 0; v < V; v++) + { + if (!vset[v] && graph->edges[u][v] != INT_MAX && + mdist[u] + graph->edges[u][v] < mdist[v]) + mdist[v] = mdist[u] + graph->edges[u][v]; + } + } + + print(mdist, V); + + return; +} + +// Driver Function +int main() +{ + int V, E, gsrc; + int src, dst, weight; + struct Graph G; + printf("Enter number of vertices: "); + scanf("%d", &V); + printf("Enter number of edges: "); + scanf("%d", &E); + createGraph(&G, V); + for (int i = 0; i < E; i++) + { + printf("\nEdge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + printf("Enter weight: "); + scanf("%d", &weight); + addEdge(&G, src, dst, weight); + } + printf("\nEnter source:"); + scanf("%d", &gsrc); + Dijkstra(&G, gsrc); + + return 0; +} diff --git a/Graphs/euler.c b/Graphs/euler.c new file mode 100644 index 0000000..32cfc2d --- /dev/null +++ b/Graphs/euler.c @@ -0,0 +1,95 @@ +#include +#include +#include "Graph.h" + +// Return the number of vertices that v is +// connected to +int degree(Graph g, int nV, Vertex v) +{ + int deg = 0; + Vertex w; + for (w = 0; w < nV; w++) + if (adjacent(g, v, w)) + deg++; + return deg; +} + +// If start from vertex v, decide if the +// graph has euler path +bool hasEulerPath(Graph g, int nV, Vertex v, Vertex w) +{ + if (v != w) + { + if (degree(g, nV, v) % 2 == 0 || degree(g, nV, w) % 2 == 0) + return false; + } + else if (degree(g, nV, v) % 2 != 0) + { + return false; + } + Vertex x; + for (x = 0; x < nV; x++) + if (x != v && x != w && degree(g, nV, x) % 2 != 0) + return false; + return true; +} + +int main(void) +{ + Edge e; + int n; + + printf("Enter the number of vertices: "); + scanf("%d", &n); + Graph g = newGraph(n); + + Vertex src, dest; + printf("Enter source node: "); + scanf("%d", &src); + printf("Enter destination node: "); + scanf("%d", &dest); + + printf("Enter an edge (from): "); + while (scanf("%d", &e.v) == 1) + { + printf("Enter an edge (to): "); + scanf("%d", &e.w); + insertEdge(g, e); + printf("Enter an edge (from): "); + } + printf("Finished.\n"); + + printf("The graph has "); + if (hasEulerPath(g, n, src, dest)) + printf("an"); + else + printf("no"); + printf(" Euler path from %d to %d.\n", src, dest); + + freeGraph(g); + return 0; +} + +// By +// .----------------. .----------------. .----------------. +// .-----------------. .----------------. .----------------. +// | .--------------. || .--------------. || .--------------. || +// .--------------. | | .--------------. || .--------------. | | | _________ | +// || | _____ _____ | || | __ | || | ____ _____ | | | | ____ ____ +// | || | ____ | | | | | _ _ | | || ||_ _||_ _|| || | / \ +// | || ||_ \|_ _| | | | | |_ || _| | || | .' `. | | | | |_/ | | +// \_| | || | | | | | | || | / /\ \ | || | | \ | | | | | | | +// |__| | | || | / .--. \ | | | | | | | || | | ' ' | | || | +// / ____ \ | || | | |\ \| | | | | | | __ | | || | | | | | | | +// | | _| |_ | || | \ `--' / | || | _/ / \ \_ | || | _| |_\ |_ +// | | | | _| | | |_ | || | \ `--' / | | | | |_____| | || | `.__.' +// | || ||____| |____|| || ||_____|\____| | | | | |____||____| | || | `.____.' +// | | | | | || | | || | | || | | | | | +// | || | | | | '--------------' || '--------------' || +// '--------------' || '--------------' | | '--------------' || '--------------' +// | +// '----------------' '----------------' '----------------' +// '----------------' '----------------' '----------------' + +// Email : z5261243@unsw.edu.au +// hhoanhtuann@gmail.com diff --git a/Graphs/floyd_warshall.c b/Graphs/floyd_warshall.c new file mode 100644 index 0000000..19a86a0 --- /dev/null +++ b/Graphs/floyd_warshall.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +// Structure for storing a graph +struct Graph +{ + int vertexNum; + int **edges; +}; + +// Constructs a graph with V vertices and E edges +void createGraph(struct Graph *G, int V) +{ + G->vertexNum = V; + G->edges = (int **)malloc(V * sizeof(int *)); + for (int i = 0; i < V; i++) + { + G->edges[i] = (int *)malloc(V * sizeof(int)); + for (int j = 0; j < V; j++) G->edges[i][j] = INT_MAX; + G->edges[i][i] = 0; + } +} + +// Adds the given edge to the graph +void addEdge(struct Graph *G, int src, int dst, int weight) +{ + G->edges[src][dst] = weight; +} + +// Utility function to print distances +void print(int dist[], int V) +{ + printf("\nThe Distance matrix for Floyd - Warshall\n"); + for (int i = 0; i < V; i++) + { + for (int j = 0; j < V; j++) + { + if (dist[i * V + j] != INT_MAX) + printf("%d\t", dist[i * V + j]); + else + printf("INF\t"); + } + printf("\n"); + } +} + +// The main function that finds the shortest path from a vertex +// to all other vertices using Floyd-Warshall Algorithm. +void FloydWarshall(struct Graph *graph) +{ + int V = graph->vertexNum; + int dist[V][V]; + + // Initialise distance array + for (int i = 0; i < V; i++) + for (int j = 0; j < V; j++) dist[i][j] = graph->edges[i][j]; + + // Calculate distances + for (int k = 0; k < V; k++) + // Choose an intermediate vertex + + for (int i = 0; i < V; i++) + // Choose a source vertex for given intermediate + + for (int j = 0; j < V; j++) + // Choose a destination vertex for above source vertex + + if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX && + dist[i][k] + dist[k][j] < dist[i][j]) + // If the distance through intermediate vertex is less than + // direct edge then update value in distance array + dist[i][j] = dist[i][k] + dist[k][j]; + + // Convert 2d array to 1d array for print + int dist1d[V * V]; + for (int i = 0; i < V; i++) + for (int j = 0; j < V; j++) dist1d[i * V + j] = dist[i][j]; + + print(dist1d, V); +} + +// Driver Function +int main() +{ + int V, E; + int src, dst, weight; + struct Graph G; + printf("Enter number of vertices: "); + scanf("%d", &V); + printf("Enter number of edges: "); + scanf("%d", &E); + createGraph(&G, V); + for (int i = 0; i < E; i++) + { + printf("\nEdge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + printf("Enter weight: "); + scanf("%d", &weight); + addEdge(&G, src, dst, weight); + } + FloydWarshall(&G); + + return 0; +} diff --git a/Graphs/graph.c b/Graphs/graph.c new file mode 100644 index 0000000..f4c69fa --- /dev/null +++ b/Graphs/graph.c @@ -0,0 +1,117 @@ +// Graph ADT +// Adjacency Matrix Representation +#include "Graph.h" +#include +#include +#include + +typedef struct GraphRep +{ + int **edges; // adjacency matrix + int nV; // #vertices + int nE; // #edges +} GraphRep; + +Graph newGraph(int V) +{ + assert(V >= 0); + int i; + + Graph g = malloc(sizeof(GraphRep)); + assert(g != NULL); + g->nV = V; + g->nE = 0; + + // allocate memory for each row + g->edges = malloc(V * sizeof(int *)); + assert(g->edges != NULL); + // allocate memory for each column and initialise with 0 + for (i = 0; i < V; i++) + { + g->edges[i] = calloc(V, sizeof(int)); + assert(g->edges[i] != NULL); + } + + return g; +} + +// check if vertex is valid in a graph +bool validV(Graph g, Vertex v) { return (g != NULL && v >= 0 && v < g->nV); } + +void insertEdge(Graph g, Edge e) +{ + assert(g != NULL && validV(g, e.v) && validV(g, e.w)); + + if (!g->edges[e.v][e.w]) + { // edge e not in graph + g->edges[e.v][e.w] = 1; + g->edges[e.w][e.v] = 1; + g->nE++; + } +} + +void removeEdge(Graph g, Edge e) +{ + assert(g != NULL && validV(g, e.v) && validV(g, e.w)); + + if (g->edges[e.v][e.w]) + { // edge e in graph + g->edges[e.v][e.w] = 0; + g->edges[e.w][e.v] = 0; + g->nE--; + } +} + +bool adjacent(Graph g, Vertex v, Vertex w) +{ + assert(g != NULL && validV(g, v) && validV(g, w)); + + return (g->edges[v][w] != 0); +} + +void showGraph(Graph g) +{ + assert(g != NULL); + int i, j; + + printf("Number of vertices: %d\n", g->nV); + printf("Number of edges: %d\n", g->nE); + for (i = 0; i < g->nV; i++) + for (j = i + 1; j < g->nV; j++) + if (g->edges[i][j]) + printf("Edge %d - %d\n", i, j); +} + +void freeGraph(Graph g) +{ + assert(g != NULL); + + int i; + for (i = 0; i < g->nV; i++) free(g->edges[i]); + free(g->edges); + free(g); +} + +// By +// .----------------. .----------------. .----------------. +// .-----------------. .----------------. .----------------. +// | .--------------. || .--------------. || .--------------. || +// .--------------. | | .--------------. || .--------------. | | | _________ | +// || | _____ _____ | || | __ | || | ____ _____ | | | | ____ ____ +// | || | ____ | | | | | _ _ | | || ||_ _||_ _|| || | / \ +// | || ||_ \|_ _| | | | | |_ || _| | || | .' `. | | | | |_/ | | +// \_| | || | | | | | | || | / /\ \ | || | | \ | | | | | | | +// |__| | | || | / .--. \ | | | | | | | || | | ' ' | | || | +// / ____ \ | || | | |\ \| | | | | | | __ | | || | | | | | | | +// | | _| |_ | || | \ `--' / | || | _/ / \ \_ | || | _| |_\ |_ +// | | | | _| | | |_ | || | \ `--' / | | | | |_____| | || | `.__.' +// | || ||____| |____|| || ||_____|\____| | | | | |____||____| | || | `.____.' +// | | | | | || | | || | | || | | | | | +// | || | | | | '--------------' || '--------------' || +// '--------------' || '--------------' | | '--------------' || '--------------' +// | +// '----------------' '----------------' '----------------' +// '----------------' '----------------' '----------------' + +// Email : z5261243@unsw.edu.au +// hhoanhtuann@gmail.com diff --git a/Graphs/graph.h b/Graphs/graph.h new file mode 100644 index 0000000..23faea8 --- /dev/null +++ b/Graphs/graph.h @@ -0,0 +1,45 @@ +// Graph ADT interface ... COMP2521 +#include + +typedef struct GraphRep *Graph; + +// vertices are ints +typedef int Vertex; + +// edges are pairs of vertices (end-points) +typedef struct Edge +{ + Vertex v; + Vertex w; +} Edge; + +Graph newGraph(int); +void insertEdge(Graph, Edge); +void removeEdge(Graph, Edge); +bool adjacent(Graph, Vertex, Vertex); +void showGraph(Graph); +void freeGraph(Graph); + +// By +// .----------------. .----------------. .----------------. +// .-----------------. .----------------. .----------------. +// | .--------------. || .--------------. || .--------------. || +// .--------------. | | .--------------. || .--------------. | | | _________ | +// || | _____ _____ | || | __ | || | ____ _____ | | | | ____ ____ +// | || | ____ | | | | | _ _ | | || ||_ _||_ _|| || | / \ +// | || ||_ \|_ _| | | | | |_ || _| | || | .' `. | | | | |_/ | | +// \_| | || | | | | | | || | / /\ \ | || | | \ | | | | | | | +// |__| | | || | / .--. \ | | | | | | | || | | ' ' | | || | +// / ____ \ | || | | |\ \| | | | | | | __ | | || | | | | | | | +// | | _| |_ | || | \ `--' / | || | _/ / \ \_ | || | _| |_\ |_ +// | | | | _| | | |_ | || | \ `--' / | | | | |_____| | || | `.__.' +// | || ||____| |____|| || ||_____|\____| | | | | |____||____| | || | `.____.' +// | | | | | || | | || | | || | | | | | +// | || | | | | '--------------' || '--------------' || +// '--------------' || '--------------' | | '--------------' || '--------------' +// | +// '----------------' '----------------' '----------------' +// '----------------' '----------------' '----------------' + +// Email : z5261243@unsw.edu.au +// hhoanhtuann@gmail.com diff --git a/Graphs/hamiltonian.c b/Graphs/hamiltonian.c new file mode 100644 index 0000000..29500ff --- /dev/null +++ b/Graphs/hamiltonian.c @@ -0,0 +1,80 @@ +#include +#include +#include "Graph.h" + +#define MAX_NODES 1000 + +bool visited[MAX_NODES]; + +bool hamiltonR(Graph g, int nV, Vertex v, Vertex dest, int d) +{ + // v = current vertex considered + // dest = destination vertex + // d = distance "remaining" until path found + + Vertex w; + if (v == dest) + { + return (d == 0); + } + else + { + visited[v] = true; + for (w = 0; w < nV; w++) + { + if (adjacent(g, v, w) && !visited[w]) + { + if (hamiltonR(g, nV, w, dest, d - 1)) + { + return true; + } + } + } + } + visited[v] = false; + return false; +} + +bool hasHamiltonianPath(Graph g, int nV, Vertex src, Vertex dest) +{ + Vertex v; + for (v = 0; v < nV; v++) visited[v] = false; + return hamiltonR(g, nV, src, dest, nV - 1); +} + +int main(void) +{ + Edge e; + int n; + + printf("Enter the number of vertices: "); + scanf("%d", &n); + Graph g = newGraph(n); + + Vertex src, dest; + printf("Enter source node: "); + scanf("%d", &src); + printf("Enter destination node: "); + scanf("%d", &dest); + + printf("Enter an edge (from): "); + while (scanf("%d", &e.v) == 1) + { + printf("Enter an edge (to): "); + scanf("%d", &e.w); + insertEdge(g, e); + printf("Enter an edge (from): "); + } + printf("Finished.\n"); + + printf("The graph has "); + if (hasHamiltonianPath(g, n, src, dest)) + printf("a"); + else + printf("no"); + printf(" Hamiltonian path from %d to %d.\n", src, dest); + + freeGraph(g); + return 0; +} + diff --git a/Graphs/kruskal.c b/Graphs/kruskal.c new file mode 100644 index 0000000..49d1c54 --- /dev/null +++ b/Graphs/kruskal.c @@ -0,0 +1,187 @@ +// C program for Kruskal's algorithm to find Minimum Spanning Tree +// of a given connected, undirected and weighted graph +#include +#include +#include + +// a structure to represent a weighted edge in graph +struct Edge +{ + int src, dest, weight; +}; + +// a structure to represent a connected, undirected +// and weighted graph +struct Graph +{ + // V-> Number of vertices, E-> Number of edges + int V, E; + + // graph is represented as an array of edges. + // Since the graph is undirected, the edge + // from src to dest is also edge from dest + // to src. Both are counted as 1 edge here. + struct Edge *edge; +}; + +// Creates a graph with V vertices and E edges +struct Graph *createGraph(int V, int E) +{ + struct Graph *graph = new Graph(); + graph->V = V; + graph->E = E; + + graph->edge = new Edge[E]; + + return graph; +} + +// A structure to represent a subset for union-find +struct subset +{ + int parent; + int rank; +}; + +// A utility function to find set of an element i +// (uses path compression technique) +int find(struct subset subsets[], int i) +{ + // find root and make root as parent of i + // (path compression) + if (subsets[i].parent != i) + subsets[i].parent = find(subsets, subsets[i].parent); + + return subsets[i].parent; +} + +// A function that does union of two sets of x and y +// (uses union by rank) +void Union(struct subset subsets[], int x, int y) +{ + int xroot = find(subsets, x); + int yroot = find(subsets, y); + + // Attach smaller rank tree under root of high + // rank tree (Union by Rank) + if (subsets[xroot].rank < subsets[yroot].rank) + subsets[xroot].parent = yroot; + else if (subsets[xroot].rank > subsets[yroot].rank) + subsets[yroot].parent = xroot; + + // If ranks are same, then make one as root and + // increment its rank by one + else + { + subsets[yroot].parent = xroot; + subsets[xroot].rank++; + } +} + +// Compare two edges according to their weights. +// Used in qsort() for sorting an array of edges +int myComp(const void *a, const void *b) +{ + struct Edge *a1 = (struct Edge *)a; + struct Edge *b1 = (struct Edge *)b; + return a1->weight > b1->weight; +} + +// The main function to construct MST using Kruskal's algorithm +void KruskalMST(struct Graph *graph) +{ + int V = graph->V; + struct Edge result[V]; // Tnis will store the resultant MST + int e = 0; // An index variable, used for result[] + int i = 0; // An index variable, used for sorted edges + + // Step 1: Sort all the edges in non-decreasing + // order of their weight. If we are not allowed to + // change the given graph, we can create a copy of + // array of edges + qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp); + + // Allocate memory for creating V ssubsets + struct subset *subsets = (struct subset *)malloc(V * sizeof(struct subset)); + + // Create V subsets with single elements + for (int v = 0; v < V; ++v) + { + subsets[v].parent = v; + subsets[v].rank = 0; + } + + // Number of edges to be taken is equal to V-1 + while (e < V - 1 && i < graph->E) + { + // Step 2: Pick the smallest edge. And increment + // the index for next iteration + struct Edge next_edge = graph->edge[i++]; + + int x = find(subsets, next_edge.src); + int y = find(subsets, next_edge.dest); + + // If including this edge does't cause cycle, + // include it in result and increment the index + // of result for next edge + if (x != y) + { + result[e++] = next_edge; + Union(subsets, x, y); + } + // Else discard the next_edge + } + + // print the contents of result[] to display the + // built MST + printf("Following are the edges in the constructed MST\n"); + for (i = 0; i < e; ++i) + printf("%d -- %d == %d\n", result[i].src, result[i].dest, + result[i].weight); + return; +} + +// Driver program to test above functions +int main() +{ + /* Let us create following weighted graph + 10 + 0--------1 + | \ | + 6| 5\ |15 + | \ | + 2--------3 + 4 */ + int V = 4; // Number of vertices in graph + int E = 5; // Number of edges in graph + struct Graph *graph = createGraph(V, E); + + // add edge 0-1 + graph->edge[0].src = 0; + graph->edge[0].dest = 1; + graph->edge[0].weight = 10; + + // add edge 0-2 + graph->edge[1].src = 0; + graph->edge[1].dest = 2; + graph->edge[1].weight = 6; + + // add edge 0-3 + graph->edge[2].src = 0; + graph->edge[2].dest = 3; + graph->edge[2].weight = 5; + + // add edge 1-3 + graph->edge[3].src = 1; + graph->edge[3].dest = 3; + graph->edge[3].weight = 15; + + // add edge 2-3 + graph->edge[4].src = 2; + graph->edge[4].dest = 3; + graph->edge[4].weight = 4; + + KruskalMST(graph); + + return 0; +} diff --git a/Graphs/queue.c b/Graphs/queue.c new file mode 100644 index 0000000..186889b --- /dev/null +++ b/Graphs/queue.c @@ -0,0 +1,81 @@ +// Queue ADT implementation ... COMP2521 + +#include "queue.h" +#include +#include + +typedef struct node +{ + int data; + struct node *next; +} NodeT; + +typedef struct QueueRep +{ + int length; + NodeT *head; + NodeT *tail; +} QueueRep; + +// set up empty queue +queue newQueue() +{ + queue Q = malloc(sizeof(QueueRep)); + Q->length = 0; + Q->head = NULL; + Q->tail = NULL; + return Q; +} + +// remove unwanted queue +void dropQueue(queue Q) +{ + NodeT *curr = Q->head; + while (curr != NULL) + { + NodeT *temp = curr->next; + free(curr); + curr = temp; + } + free(Q); +} + +// check whether queue is empty +int QueueIsEmpty(queue Q) { return (Q->length == 0); } + +// insert an int at end of queue +void QueueEnqueue(queue Q, int v) +{ + NodeT *new = malloc(sizeof(NodeT)); + assert(new != NULL); + new->data = v; + new->next = NULL; + if (Q->tail != NULL) + { + Q->tail->next = new; + Q->tail = new; + } + else + { + Q->head = new; + Q->tail = new; + } + Q->length++; +} + +// remove int from front of queue +int QueueDequeue(queue Q) +{ + assert(Q->length > 0); + NodeT *p = Q->head; + Q->head = Q->head->next; + if (Q->head == NULL) + { + Q->tail = NULL; + } + Q->length--; + int d = p->data; + free(p); + return d; +} + diff --git a/Graphs/queue.h b/Graphs/queue.h new file mode 100644 index 0000000..e6638c2 --- /dev/null +++ b/Graphs/queue.h @@ -0,0 +1,10 @@ +// Queue ADT header file ... COMP2521 + +typedef struct QueueRep *queue; + +queue newQueue(); // set up empty queue +void dropQueue(queue); // remove unwanted queue +int QueueIsEmpty(queue); // check whether queue is empty +void QueueEnqueue(queue, int); // insert an int at end of queue +int QueueDequeue(queue); // remove int from front of queue + diff --git a/Graphs/strongly_connected_components.c b/Graphs/strongly_connected_components.c new file mode 100644 index 0000000..652ecf2 --- /dev/null +++ b/Graphs/strongly_connected_components.c @@ -0,0 +1,223 @@ +#include +#include +#define MAX_SIZE 40 // Assume 40 nodes at max in graph +#define INT_MIN 0 +// A vertex of the graph +struct node +{ + int vertex; + struct node *next; +}; +// Some declarations +struct node *createNode(int v); +struct Graph +{ + int numVertices; + int *visited; + struct node * + *adjLists; // we need int** to store a two dimensional array. Similary, + // we need struct node** to store an array of Linked lists +}; +// Structure to create a stack, necessary for topological sorting +struct Stack +{ + int arr[MAX_SIZE]; + int top; +}; +struct Graph *createGraph(int); +void addEdge(struct Graph *, int, int); +void printGraph(struct Graph *); +struct Graph *transpose(struct Graph *); +void fillOrder(int, struct Graph *, struct Stack *); +void scc(struct Graph *); +void dfs(struct Graph *, int); +struct Stack *createStack(); +void push(struct Stack *, int); +int pop(struct Stack *); + +int main() +{ + int vertices, edges, i, src, dst; + printf("Enter the number of vertices\n"); + scanf("%d", &vertices); + struct Graph *graph = createGraph(vertices); + printf("Enter the number of edges\n"); + scanf("%d", &edges); + for (i = 0; i < edges; i++) + { + printf("Edge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + addEdge(graph, src, dst); + } + printf("The strongly connected conponents are:\n"); + scc(graph); + printf("\n"); + + // Uncomment below part to get a ready-made example + /*struct Graph* graph2 = createGraph(4); + addEdge(graph2, 0, 1); + addEdge(graph2, 1, 2); + addEdge(graph2, 2, 0); + addEdge(graph2, 2, 3); + printf("The strongly connected components are:\n"); + scc(graph2); + printf("\n");*/ + return 0; +} +// Creates a topological sorting of the graph +void fillOrder(int vertex, struct Graph *graph, struct Stack *stack) +{ + graph->visited[vertex] = 1; + struct node *adjList = graph->adjLists[vertex]; + struct node *temp = adjList; + // First add all dependents (that is, children) to stack + while (temp != NULL) + { + int connectedVertex = temp->vertex; + if (graph->visited[connectedVertex] == 0) + { + fillOrder(connectedVertex, graph, stack); + } + temp = temp->next; + } + // and then add itself + push(stack, vertex); +} +// Transpose the adjacency list +struct Graph *transpose(struct Graph *g) +{ + struct Graph *graph = + createGraph(g->numVertices); // Number of vertices is same + int i = 0; + for (i = 0; i < g->numVertices; i++) + { + struct node *temp = g->adjLists[i]; + while (temp != NULL) + { + addEdge(graph, temp->vertex, i); // Reverse all edges + temp = temp->next; + } + } + return graph; +} +// Recursive dfs aproach +void dfs(struct Graph *graph, int vertex) +{ + struct node *adjList = graph->adjLists[vertex]; + struct node *temp = adjList; + + // Add vertex to visited list and print it + graph->visited[vertex] = 1; + printf("%d ", vertex); + + // Recursively call the dfs function on all unvisited neighbours + while (temp != NULL) + { + int connectedVertex = temp->vertex; + if (graph->visited[connectedVertex] == 0) + { + dfs(graph, connectedVertex); + } + temp = temp->next; + } +} + +// Strongly connected components +void scc(struct Graph *graph) +{ + // Step I: Create a topological sort of the graph and store it in a stack + struct Stack *stack = createStack(); + int i = 0; + for (i = 0; i < graph->numVertices; i++) + { + // Execute topological sort on all elements + if (graph->visited[i] == 0) + { + fillOrder(i, graph, stack); + } + } + // Step 2: Get the transpose graph + struct Graph *graphT = transpose(graph); + // Step 3: Perform a simple dfs by popping nodes from stack + while (stack->top != -1) + { + int v = pop(stack); + if (graphT->visited[v] == 0) + { + dfs(graphT, v); + printf("\n"); + } + } +} + +// Allocate memory for a node +struct node *createNode(int v) +{ + struct node *newNode = malloc(sizeof(struct node)); + newNode->vertex = v; + newNode->next = NULL; + return newNode; +} +// Allocate memory for the entire graph structure +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; +} +// Creates a unidirectional graph +void addEdge(struct Graph *graph, int src, int dest) +{ + // Add edge from src to dest + struct node *newNode = createNode(dest); + newNode->next = graph->adjLists[src]; + graph->adjLists[src] = newNode; +} +// Utility function to see state of graph at a given time +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"); + } +} +// Creates a stack +struct Stack *createStack() +{ + struct Stack *stack = malloc(sizeof(struct Stack)); + stack->top = -1; + return stack; +} +// Pushes element into stack +void push(struct Stack *stack, int element) +{ + stack->arr[++stack->top] = + element; // Increment then add, as we start from -1 +} +// Removes element from stack, or returns INT_MIN if stack empty +int pop(struct Stack *stack) +{ + if (stack->top == -1) + return INT_MIN; + else + return stack->arr[stack->top--]; +} diff --git a/Graphs/topological_sort.c b/Graphs/topological_sort.c new file mode 100644 index 0000000..a9909ca --- /dev/null +++ b/Graphs/topological_sort.c @@ -0,0 +1,170 @@ +#include +#include +#define MAX_SIZE 40 // Assume 40 nodes at max in graph +#define INT_MIN 0 +// A vertex of the graph +struct node +{ + int vertex; + struct node *next; +}; +// Some declarations +struct node *createNode(int v); +struct Graph +{ + int numVertices; + int *visited; + struct node * + *adjLists; // we need int** to store a two dimensional array. Similary, + // we need struct node** to store an array of Linked lists +}; +// Structure to create a stack, necessary for topological sorting +struct Stack +{ + int arr[MAX_SIZE]; + int top; +}; +struct Graph *createGraph(int); +void addEdge(struct Graph *, int, int); +void printGraph(struct Graph *); +void topologicalSortHelper(int, struct Graph *, struct Stack *); +void topologicalSort(struct Graph *); +struct Stack *createStack(); +void push(struct Stack *, int); +int pop(struct Stack *); + +int main() +{ + int vertices, edges, i, src, dst; + printf("Enter the number of vertices\n"); + scanf("%d", &vertices); + struct Graph *graph = createGraph(vertices); + printf("Enter the number of edges\n"); + scanf("%d", &edges); + for (i = 0; i < edges; i++) + { + printf("Edge %d \nEnter source: ", i + 1); + scanf("%d", &src); + printf("Enter destination: "); + scanf("%d", &dst); + addEdge(graph, src, dst); + } + printf("One topological sort order is:\n"); + topologicalSort(graph); + printf("\n"); + + // Uncomment below part to get a ready-made example + /*struct Graph* graph2 = createGraph(4); + addEdge(graph2, 0, 1); + addEdge(graph2, 0, 2); + addEdge(graph2, 1, 2); + addEdge(graph2, 2, 3); + printf("One topological sort is:\n"); + topologicalSort(graph2); + printf("\n");*/ + return 0; +} + +void topologicalSortHelper(int vertex, struct Graph *graph, struct Stack *stack) +{ + graph->visited[vertex] = 1; + struct node *adjList = graph->adjLists[vertex]; + struct node *temp = adjList; + // First add all dependents (that is, children) to stack + while (temp != NULL) + { + int connectedVertex = temp->vertex; + if (graph->visited[connectedVertex] == 0) + { + topologicalSortHelper(connectedVertex, graph, stack); + } + temp = temp->next; + } + // and then add itself + push(stack, vertex); +} + +// Recursive topologial sort approach +void topologicalSort(struct Graph *graph) +{ + struct Stack *stack = createStack(); + int i = 0; + for (i = 0; i < graph->numVertices; i++) + { + // Execute topological sort on all elements + if (graph->visited[i] == 0) + { + topologicalSortHelper(i, graph, stack); + } + } + while (stack->top != -1) printf("%d ", pop(stack)); +} +// Allocate memory for a node +struct node *createNode(int v) +{ + struct node *newNode = malloc(sizeof(struct node)); + newNode->vertex = v; + newNode->next = NULL; + return newNode; +} +// Allocate memory for the entire graph structure +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; +} +// Creates a unidirectional graph +void addEdge(struct Graph *graph, int src, int dest) +{ + // Add edge from src to dest + struct node *newNode = createNode(dest); + newNode->next = graph->adjLists[src]; + graph->adjLists[src] = newNode; +} +// Utility function to see state of graph at a given time +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"); + } +} +// Creates a stack +struct Stack *createStack() +{ + struct Stack *stack = malloc(sizeof(struct Stack)); + stack->top = -1; + return stack; +} +// Pushes element into stack +void push(struct Stack *stack, int element) +{ + stack->arr[++stack->top] = + element; // Increment then add, as we start from -1 +} +// Removes element from stack, or returns INT_MIN if stack empty +int pop(struct Stack *stack) +{ + if (stack->top == -1) + return INT_MIN; + else + return stack->arr[stack->top--]; +} diff --git a/Graphs/transitive_closure.c b/Graphs/transitive_closure.c new file mode 100644 index 0000000..e7e15c6 --- /dev/null +++ b/Graphs/transitive_closure.c @@ -0,0 +1,37 @@ +#include +#include + +#define NODES 4 + +int digraph[NODES][NODES] = { + {0, 1, 1, 1}, {1, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}; +int tc[NODES][NODES]; + +void warshall() +{ + int i, s, t; + for (s = 0; s < NODES; s++) + for (t = 0; t < NODES; t++) tc[s][t] = digraph[s][t]; + + for (i = 0; i < NODES; i++) + for (s = 0; s < NODES; s++) + for (t = 0; t < NODES; t++) + if (tc[s][i] && tc[i][t]) + tc[s][t] = 1; +} + +int main(void) +{ + warshall(); + int i, j; + for (i = 0; i < NODES; i++) + { + for (j = 0; j < NODES; j++) + { + printf("%d ", tc[i][j]); + } + putchar('\n'); + } + return 0; +} + diff --git a/Greedy Approach/djikstra.c b/Greedy Approach/djikstra.c new file mode 100644 index 0000000..e9d1c63 --- /dev/null +++ b/Greedy Approach/djikstra.c @@ -0,0 +1,87 @@ +#include +#include + +#define MAX 20 +#define INF 999 + +int mat[MAX][MAX]; +int V; + +int dist[MAX]; + +int q[MAX]; +int qp = 0; + +void enqueue(int v) { q[qp++] = v; } + +int cf(void *a, void *b) +{ + int *x = (int *)a; + int *y = (int *)b; + return *y - *x; +} + +int dequeue() +{ + qsort(q, qp, sizeof(int), cf); + return q[--qp]; +} + +int queue_has_something() { return (qp > 0); } + +int visited[MAX]; +int vp = 0; + +void dijkstra(int s) +{ + dist[s] = 0; + int i; + for (i = 0; i < V; ++i) + { + if (i != s) + { + dist[i] = INF; + } + enqueue(i); + } + while (queue_has_something()) + { + int u = dequeue(); + visited[vp++] = u; + for (i = 0; i < V; ++i) + { + if (mat[u][i]) + { + if (dist[i] > dist[u] + mat[u][i]) + { + dist[i] = dist[u] + mat[u][i]; + } + } + } + } +} + +int main(int argc, char const *argv[]) +{ + printf("Enter the number of vertices: "); + scanf(" %d", &V); + printf("Enter the adj matrix: "); + int i, j; + for (i = 0; i < V; ++i) + { + for (j = 0; j < V; ++j) + { + scanf(" %d", &mat[i][j]); + } + } + + dijkstra(0); + + printf("\nNode\tDist\n"); + for (i = 0; i < V; ++i) + { + printf("%d\t%d\n", i, dist[i]); + } + + return 0; +} diff --git a/Greedy Approach/prim.c b/Greedy Approach/prim.c new file mode 100644 index 0000000..6085c44 --- /dev/null +++ b/Greedy Approach/prim.c @@ -0,0 +1,195 @@ + + * + * To test - run './prim -test' + * prim() will find the MST of the following adj. matrix: + * + * 0 1 2 3 + * 1 0 4 6 + * 2 4 0 5 + * 3 6 5 0 + * + * The minimum spanning tree for the above weighted connected graph is given by the following adj matrix: + * + * 0 1 2 3 + * 1 0 0 0 + * 2 0 0 0 + * 3 0 0 0 + * + * + * The following [link](https://visualgo.net/en/mst) provides a visual representation of graphs that can be used to test/verify the algorithm for different adj + * matrices and their weighted, connected graphs. + */ + +#include /// for IO operations +#include /// for string comparison +#include /// for assert() +#include /// for uint16_t + +#define MAX 20 +#define INF 999 + +/** + * @brief Finds index of minimum element in edge list for an arbitrary vertex + * @param arr graph row + * @param N number of elements in arr + * @returns index of minimum element in arr + */ +uint16_t minimum(uint16_t arr[], uint16_t N) +{ + uint16_t index = 0; + uint16_t min = INF; + + for (uint16_t i = 0; i < N; i++) + { + if (arr[i] < min) + { + min = arr[i]; + index = i; + } + } + return index; +} + +/** + * @brief Used to find MST of user-generated adj matrix G + * @returns void + */ +void prim(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V) +{ + uint16_t u, v; + uint16_t E_t[MAX], path[MAX]; + uint16_t V_t[MAX], no_of_edges; + + E_t[0] = 0; // edges for current vertex + V_t[0] = 1; // list of visited vertices + + for (uint16_t i = 1; i < V; i++) + { + E_t[i] = G[i][0]; + path[i] = 0; + V_t[i] = 0; + } + + no_of_edges = V - 1; + + while (no_of_edges > 0) + { + u = minimum(E_t, V); + while (V_t[u] == 1) + { + E_t[u] = INF; + u = minimum(E_t, V); + } + + v = path[u]; + MST[v][u] = E_t[u]; + MST[u][v] = E_t[u]; + no_of_edges--; + V_t[u] = 1; + + for (uint16_t i = 1; i < V; i++) + { + if (V_t[i] == 0 && G[u][i] < E_t[i]) + { + E_t[i] = G[u][i]; + path[i] = v; + } + } + } +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void test(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V) +{ + + uint16_t test[4][4] = {{0,1,2,3},{1,0,4,6},{2,4,0,5},{3,6,5,0}}; + uint16_t solution[4][4] = {{0,1,2,3},{1,0,0,0},{2,0,0,0},{3,0,0,0}}; + + V = 4; + + for(uint16_t i = 0; i < V; ++i) + { + for(uint16_t j = 0; j < V; ++j) + { + G[i][j] = test[i][j]; + } + } + + prim(&(*G),&(*MST),V); + + for(uint16_t i = 0; i < V; ++i) + { + for(uint16_t j = 0; j < V; ++j) + { + assert(MST[i][j] == solution[i][j]); + } + } +} + +/** + * @brief Function user_graph(); + * gets user input adj. matrix and finds MST of that graph + * @returns void + */ +void user_graph(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V) +{ + printf("Enter the number of vertices: "); + scanf(" %hd", &V); + + assert(V <= MAX); + + printf("Enter the adj matrix\n"); + uint16_t i, j; + for (i = 0; i < V; ++i) + { + for (j = 0; j < V; ++j) + { + printf("G[%d][%d]: ", i, j); + scanf(" %hd", &G[i][j]); + if (G[i][j] == 0) + G[i][j] = INF; + } + } + + prim(&(*G),&(*MST),V); + + printf("minimum spanning tree:\n"); + for (i = 0; i < V; ++i) + { + printf("\n"); + for (j = 0; j < V; ++j) + { + printf("%d\t", MST[i][j]); + } + } +} + + +/** + * @brief Main function + * @param argc commandline argument count (ignored) + * @param argv commandline array of arguments (ignored) + * @returns 0 on exit + */ +int main(int argc, char const *argv[]) +{ + + uint16_t G[MAX][MAX]; ///< weighted, connected graph G + uint16_t MST[MAX][MAX]; ///< adj matrix to hold minimum spanning tree of G + uint16_t V; ///< number of vertices in V in G + + + if(argc == 2 && strcmp(argv[1],"-test") == 0) + { + test(&(*G),&(*MST),V); + } + else + { + user_graph(&(*G),&(*MST),V); + } + + return 0; +}