C++ Implementations of Core Algorithms: DP, Graph, Sort

Essential Algorithms Implemented in C++

Longest Common Subsequence (LCS)

The Longest Common Subsequence (LCS) problem is solved here using Dynamic Programming. It calculates the length and reconstructs the actual subsequence of two input strings.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm> // For max function

using namespace std;

int main() {
    string X, Y;
    cout << "Enter first string: ";
    cin >> X;
    cout << "Enter second string: ";
    cin >> Y;

    int m = X.size(), n = Y.size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (X[i - 1] == Y[j - 1])
                dp[i][j] = dp[i - 1][j - 1] + 1;
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
    }

    int len = dp[m][n];
    string lcs = "";
    int i = m, j = n;
    while (i > 0 && j > 0) {
        if (X[i - 1] == Y[j - 1]) {
            lcs = X[i - 1] + lcs;
            i--; j--;
        } else if (dp[i - 1][j] > dp[i][j - 1])
            i--;
        else
            j--;
    }

    cout << "\nLongest Common Subsequence: " << lcs;
    cout << "\nLength of LCS: " << len << endl;

    return 0;
}

Dijkstra’s Shortest Path Algorithm

This implementation finds the shortest path from a source vertex to all other vertices in a weighted graph using a priority queue.

#include <iostream>
#include <vector>
#include <queue>
#include <limits>

using namespace std;

int main(){
    int n, m;
    cout << "Enter vertices and edges: ";
    cin >> n >> m;

    vector<vector<pair<int, int>>> g(n);
    cout << "Enter edges (u v w):\n";
    for(int i = 0; i < m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        g[u - 1].push_back({v - 1, w});
    }

    int s;
    cout << "Enter source vertex: ";
    cin >> s;
    s--;

    const int INF = 1e9;
    vector<int> d(n, INF), par(n, -1);
    d[s] = 0;

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    pq.push({0, s});

    while(!pq.empty()){
        auto [du, u] = pq.top();
        pq.pop();
        if(du != d[u]) continue;

        for(auto [v, w] : g[u])
            if(d[v] > du + w){
                d[v] = du + w;
                par[v] = u;
                pq.push({d[v], v});
            }
    }

    for(int i = 0; i < n; i++){
        cout << "Vertex " << i + 1 << ": ";
        if(d[i] == INF){ 
            cout << "No path\n";
            continue;
        }
        cout << "Dist=" << d[i] << " Path: ";
        vector<int> p;
        for(int v = i; v != -1; v = par[v]) p.push_back(v);
        for(int j = p.size() - 1; j >= 0; j--)
            cout << p[j] + 1 << (j ? "->" : "");
        cout << "\n";
    }
}

Fractional Knapsack Problem (Greedy Approach)

This solution uses a Greedy approach, sorting items based on their profit-to-weight ratio using Heap Sort to maximize the total profit within the knapsack capacity.

#include <iostream>
#include <algorithm> // For swap

using namespace std;

struct ITEM {
    int id;
    float profit, weight, ratio;
};

void heapify(ITEM a[], int n, int i) {
    int largest = i, l = 2 * i + 1, r = 2 * i + 2;
    if (l < n && a[l].ratio > a[largest].ratio)
        largest = l;
    if (r < n && a[r].ratio > a[largest].ratio)
        largest = r;
    if (largest != i) {
        swap(a[i], a[largest]);
        heapify(a, n, largest);
    }
}

void heapSort(ITEM a[], int n) {
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(a, n, i);
    for (int i = n - 1; i > 0; i--) {
        swap(a[0], a[i]);
        heapify(a, i, 0);
    }
}

int main() {
    int n;
    cout << "Enter number of items: ";
    cin >> n;
    ITEM *a = new ITEM[n];
    
    for (int i = 0; i < n; i++) {
        cout << "Enter profit and weight of item " << i + 1 << ": ";
        cin >> a[i].profit >> a[i].weight;
        a[i].id = i + 1;
        a[i].ratio = a[i].profit / a[i].weight;
    }
    
    float capacity;
    cout << "Enter capacity of knapsack: ";
    cin >> capacity;

    heapSort(a, n); // Sort by ratio ascending
    
    float totalProfit = 0, cap = capacity;
    cout << "\nItems taken:\n";
    
    // Iterate from highest ratio (end of ascending sorted array)
    for (int i = n - 1; i >= 0 && cap > 0; i--) {
        if (a[i].weight <= cap) {
            cap -= a[i].weight;
            totalProfit += a[i].profit;
            cout << "Item " << a[i].id << " fully taken.\n";
        } else {
            totalProfit += a[i].profit * (cap / a[i].weight);
            cout << "Item " << a[i].id << " partially taken.\n";
            cap = 0;
        }
    }
    
    cout << "\nMaximum Profit: " << totalProfit << endl;
    delete[] a;
    return 0;
}

Matrix Chain Multiplication (Dynamic Programming)

This algorithm determines the optimal parenthesization of a sequence of matrices to minimize the total number of scalar multiplications required.

#include <iostream>
#include <climits> // For INT_MAX

using namespace std;

int main() {
    int n;
    cout << "Enter number of matrices: ";
    cin >> n;
    
    int p[n + 1];
    cout << "Enter dimensions (n+1 numbers): ";
    for (int i = 0; i <= n; i++) cin >> p[i];

    int m[n + 1][n + 1];
    for (int i = 1; i <= n; i++) m[i][i] = 0;

    for (int L = 2; L <= n; L++) {
        for (int i = 1; i <= n - L + 1; i++) {
            int j = i + L - 1;
            m[i][j] = INT_MAX;
            for (int k = i; k < j; k++) {
                int cost = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
                if (cost < m[i][j]) m[i][j] = cost;
            }
        }
    }

    cout << "Minimum number of multiplications: " << m[1][n] << endl;
    return 0;
}

Prim’s Algorithm for Minimum Spanning Tree (MST)

Prim’s algorithm is a Greedy algorithm used to find a Minimum Spanning Tree for a weighted undirected graph.

#include <iostream>
#include <climits>
using namespace std;

int main() {
    int n;
    cout << "Enter number of vertices: ";
    cin >> n;

    int graph[20][20];
    cout << "Enter adjacency matrix (use 0 for no edge):\n";
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> graph[i][j];

    int cost = 0, selected[20] = {0};
    selected[0] = 1;
    cout << "\nEdges in MST:\n";

    for (int edges = 0; edges < n - 1; edges++) {
        int min = INT_MAX, u = -1, v = -1;
        for (int i = 0; i < n; i++) {
            if (selected[i]) {
                for (int j = 0; j < n; j++) {
                    if (!selected[j] && graph[i][j] && graph[i][j] < min) {
                        min = graph[i][j];
                        u = i;
                        v = j;
                    }
                }
            }
        }
        selected[v] = 1;
        cost += min;
        cout << u + 1 << " - " << v + 1 << " : " << min << endl;
    }

    cout << "Total cost of MST: " << cost << endl;
    return 0;
}

Quicksort Implementation

Quicksort is an efficient, comparison-based sorting algorithm that uses a Divide and Conquer strategy.

#include <iostream>
#include <algorithm> // For swap

using namespace std;

int partition(int a[], int low, int high) {
    int pivot = a[high];
    int i = low - 1;

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

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

int main() {
    int n;
    cout << "Enter number of elements: ";
    cin >> n;
    int a[n];

    cout << "Enter elements: ";
    for (int i = 0; i < n; i++) cin >> a[i];

    quickSort(a, 0, n - 1);

    cout << "Sorted array: ";
    for (int i = 0; i < n; i++) cout << a[i] << " ";
    cout << endl;
    return 0;
}

Kruskal’s Algorithm for Minimum Spanning Tree (MST)

Kruskal’s algorithm uses a Greedy approach combined with a Disjoint Set Union (DSU) structure to find the MST by iteratively adding the cheapest safe edge.

#include <iostream>
#include <algorithm>
using namespace std;

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

int find(int parent[], int i) {
    if (parent[i] == i) return i;
    return parent[i] = find(parent, parent[i]);
}

void unite(int parent[], int rank[], int x, int y) {
    x = find(parent, x);
    y = find(parent, y);
    if (x != y) {
        if (rank[x] < rank[y]) parent[x] = y;
        else if (rank[x] > rank[y]) parent[y] = x;
        else { parent[y] = x; rank[x]++; }
    }
}

int main() {
    int n, e;
    cout << "Enter number of vertices: ";
    cin >> n;
    cout << "Enter number of edges: ";
    cin >> e;

    Edge edges[e];
    cout << "Enter edges (u v weight):\n";
    for (int i = 0; i < e; i++)
        cin >> edges[i].u >> edges[i].v >> edges[i].w;

    sort(edges, edges + e, [](Edge a, Edge b) { return a.w < b.w; });

    int parent[n + 1], rank[n + 1];
    for (int i = 1; i <= n; i++) {
        parent[i] = i;
        rank[i] = 0;
    }

    int cost = 0;
    cout << "\nEdges in MST:\n";
    for (int i = 0; i < e; i++) {
        int x = find(parent, edges[i].u);
        int y = find(parent, edges[i].v);
        if (x != y) {
            cout << edges[i].u << " - " << edges[i].v << " : " << edges[i].w << endl;
            cost += edges[i].w;
            unite(parent, rank, x, y);
        }
    }

    cout << "Total cost of MST: " << cost << endl;
    return 0;
}

Floyd-Warshall All-Pairs Shortest Path

The Floyd-Warshall algorithm uses Dynamic Programming to find the shortest paths between all pairs of vertices in a weighted graph.

#include <iostream>
#include <climits> // For INT_MAX

using namespace std;

int main() {
    int n;
    cout << "Enter number of vertices: ";
    cin >> n;

    int dist[20][20];
    cout << "Enter adjacency matrix (use " << INT_MAX << " for no edge):\n";
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> dist[i][j];

    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX &&
                    dist[i][k] + dist[k][j] < dist[i][j])
                    dist[i][j] = dist[i][k] + dist[k][j];

    cout << "\nShortest distance matrix:\n";
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            if (dist[i][j] == INT_MAX) cout << "INF ";
            else cout << dist[i][j] << " ";
        cout << endl;
    }
    return 0;
}