Algorithms: Prim’s, Kruskal’s, Dijkstra’s, Quick Sort, Merge Sort, Knapsack

Prim’s Algorithm

C Implementation

#include <stdio.h>
#include <limits.h>
#include <stdbool.h>

#define V 5 // Number of vertices

int findMinVertex(int key[], bool mstSet[]) {
    int min = INT_MAX, minIndex;
    for (int v = 0; v < V; v++)
        if (!mstSet[v] && key[v] < min) {
            min = key[v];
            minIndex = v;
        }
    return minIndex;
}

void primMST(int graph[V][V]) {
    int parent[V], key[V];
    bool mstSet[V] = {false};
    for (int i = 0; i < V; i++)
        key[i] = INT_MAX;
    key[0] = 0;
    parent[0] = -1;
    for (int count = 0; count < V - 1; count++) {
        int u = findMinVertex(key, mstSet);
        mstSet[u] = true;
        for (int v = 0; v < V; v++)
            if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v]) {
                parent[v] = u;
                key[v] = graph[u][v];
            }
    }
    printf("Edge \tWeight\n");
    for (int i = 1; i < V; i++)
        printf("%d - %d \t%d\n", parent[i], i, graph[i][parent[i]]);
}

int main() {
    int graph[V][V] = {
        {0, 2, 0, 6, 0},
        {2, 0, 3, 8, 5},
        {0, 3, 0, 0, 7},
        {6, 8, 0, 0, 9},
        {0, 5, 7, 9, 0}
    };
    primMST(graph);
    return 0;
}

Algorithm Steps

  1. Initialization:
    • key[]: Minimum weight edge to MST. Initialized to infinity, except key[0] = 0.
    • parent[]: Parent of each vertex in MST. Initialized to -1.
    • mstSet[]: Tracks vertices in MST. Initialized to false.
  2. MST Construction:
    • Repeat V-1 times:
    • Select vertex u with smallest key[] not in mstSet[].
    • Add u to mstSet[].
    • Update key[] and parent[] of adjacent vertices of u if a shorter path is found.
  3. Output: Print the MST edges and weights.

Kruskal’s Algorithm

C Implementation

#include <stdio.h>
#include <stdlib.h>

#define V 5 // Number of vertices
#define E 7 // Number of edges

typedef struct {
    int u, v, w;
} Edge;

Edge edges[E], mst[V - 1];

int cmp(const void *a, const void *b) {
    return ((Edge *)a)->w - ((Edge *)b)->w;
}

int find(int p[], int i) {
    return (p[i] == i) ? i : (p[i] = find(p, p[i]));
}

void kruskal() {
    int p[V], c = 0;
    for (int i = 0; i < V; i++) p[i] = i;
    qsort(edges, E, sizeof(Edge), cmp);
    for (int i = 0; i < E && c < V - 1; i++) {
        int u = find(p, edges[i].u);
        int v = find(p, edges[i].v);
        if (u != v) {
            mst[c++] = edges[i];
            p[u] = v;
        }
    }
    printf("Edge \tWeight\n");
    for (int i = 0; i < c; i++)
        printf("%d - %d \t%d\n", mst[i].u, mst[i].v, mst[i].w);
}

int main() {
    edges[0] = (Edge){0, 1, 2};
    edges[1] = (Edge){0, 3, 6};
    edges[2] = (Edge){1, 3, 8};
    edges[3] = (Edge){1, 2, 3};
    edges[4] = (Edge){1, 4, 5};
    edges[5] = (Edge){2, 4, 7};
    edges[6] = (Edge){3, 4, 9};
    kruskal();
    return 0;
}

Algorithm Steps

  1. Input: Graph represented as a list of edges with vertices and weights.
  2. Sort Edges: Sort edges by weight in non-decreasing order.
  3. Initialize Subsets: Each vertex starts as its own subset (parent of itself).
  4. Add Edges to MST:
    • Iterate through sorted edges.
    • If edge connects vertices in different subsets, add it to MST and merge subsets.
    • Stop when MST has V-1 edges.
  5. Output: Print MST edges and weights.

Dijkstra’s Algorithm

C Implementation

#include <stdio.h>
#include <limits.h>
#include <stdbool.h>

#define V 5 // Number of vertices
#define INF INT_MAX

int findMinDist(int dist[], bool sptSet[]) {
    int min = INF, minIndex;
    for (int v = 0; v < V; v++)
        if (!sptSet[v] && dist[v] <= min) {
            min = dist[v];
            minIndex = v;
        }
    return minIndex;
}

void dijkstra(int graph[V][V], int src) {
    int dist[V];
    bool sptSet[V] = {false};
    for (int i = 0; i < V; i++)
        dist[i] = INF;
    dist[src] = 0;
    for (int count = 0; count < V - 1; count++) {
        int u = findMinDist(dist, sptSet);
        sptSet[u] = true;
        for (int v = 0; v < V; v++)
            if (!sptSet[v] && graph[u][v] && dist[u] != INF &&
                dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v];
    }
    printf("Vertex \tDistance from Source\n");
    for (int i = 0; i < V; i++)
        printf("%d \t%d\n", i, dist[i]);
}

int main() {
    int graph[V][V] = {
        {0, 10, 0, 0, 5},
        {0, 0, 1, 0, 2},
        {0, 0, 0, 4, 0},
        {7, 0, 6, 0, 0},
        {0, 3, 9, 2, 0}
    };
    int src = 0;
    dijkstra(graph, src);
    return 0;
}

Algorithm Steps

  1. Input: Graph as adjacency matrix, source vertex src.
  2. Initialization:
    • dist[]: Shortest distance from src. Initialized to infinity, except dist[src] = 0.
    • sptSet[]: Tracks finalized shortest paths. Initialized to false.
  3. Shortest Path Calculation:
    • Repeat V-1 times:
    • Find vertex u with smallest dist[] not in sptSet[].
    • Add u to sptSet[].
    • Update dist[] of adjacent vertices if a shorter path is found through u.
  4. Output: Print shortest distances from source to all vertices.

Quick Sort

C Implementation

#include <stdio.h>

#define swap(x, y) { int temp = x; x = y; y = temp; }

int partition(int arr[], int low, int high) {
    int pivot = arr[high], i = low - 1;
    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot)
            swap(arr[++i], arr[j]);
    }
    swap(arr[i + 1], arr[high]);
    return i + 1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    printf("Sorted array: ");
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    return 0;
}

Algorithm Steps

  1. Input: Array arr[], indices low and high.
  2. Partition:
    • Choose pivot (last element).
    • Place elements smaller than pivot before it, and larger elements after it.
    • Return pivot’s index.
  3. Recursion: Recursively sort subarrays before and after pivot.
  4. Base Case: Subarray with 0 or 1 element is sorted.
  5. Output: Sorted array.

Merge Sort

C Implementation

#include <stdio.h>

void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1, n2 = r - m;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) L[i] = arr[l + i];
    for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j];
    int i = 0, j = 0, k = l;
    while (i < n1 && j < n2)
        arr[k++] = (L[i] <= R[j]) ? L[i++] : R[j++];
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

void mergeSort(int arr[], int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int n = sizeof(arr) / sizeof(arr[0]);
    mergeSort(arr, 0, n - 1);
    printf("Sorted array: ");
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    return 0;
}

Algorithm Steps

  1. Input: Array arr[], indices l and r.
  2. Divide: Divide array into two halves recursively.
  3. Merge: Merge sorted halves into a single sorted array.
  4. Base Case: Subarray with one element is sorted.
  5. Output: Sorted array.

Knapsack Problem

C Implementation

#include <stdio.h>

#define MAX_ITEMS 100
#define MAX_CAPACITY 100

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

int knapSack(int W, int wt[], int val[], int n) {
    int dp[n + 1][W + 1];
    for (int i = 0; i <= n; ++i) {
        for (int w = 0; w <= W; ++w) {
            if (i == 0 || w == 0)
                dp[i][w] = 0;
            else if (wt[i - 1] <= w)
                dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]);
            else
                dp[i][w] = dp[i - 1][w];
        }
    }
    return dp[n][W];
}

int main() {
    int values[] = {3, 4, 5, 6};
    int weight[] = {2, 3, 4, 5};
    int W = 8;
    int n = sizeof(values) / sizeof(values[0]);
    printf("Maximum value that can be put in knapsack: %d\n", knapSack(W, weight, values, n));
    return 0;
}

Algorithm Steps

  1. Input: values[], weight[], capacity W, number of items n.
  2. Initialize DP Table: dp[n+1][W+1], base cases dp[0][w] = 0 and dp[i][0] = 0.
  3. Iterate: For each item and weight, calculate maximum value by either including or excluding the item.
  4. Output: dp[n][W] contains the maximum knapsack value.
  5. Return: Print the maximum value.