Skip to main content

Merge K sorted lists

PROBLEM

Given an array of ‘K’ sorted LinkedLists, merge them into one sorted list.

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <algorithm>
#include <ranges>
#include <format>

template<typename T>
class ListMergerInterface {
public:
virtual std::list<T> merge(std::vector<std::list<T>>& lists) = 0;
virtual std::list<T> merge(std::vector<std::list<T>>&& lists) = 0;
};

template<typename T>
class ListMerger: private ListMergerInterface<T> {
template<typename U, typename Comp>
using MinHeap = std::priority_queue<U, std::vector<U>, Comp>;

public:
std::list<T> merge(std::vector<std::list<T>>&& lists) override {
return merge(lists);
}

std::list<T> merge(std::vector<std::list<T>>& lists) override {
using ListIterator = std::list<T>::const_iterator;

auto heapComp = [](auto const& a, auto const& b) { return *std::get<0>(a) > *std::get<0>(b); };
MinHeap<std::pair<ListIterator, int>, decltype(heapComp)> heap(heapComp);

std::ranges::for_each(lists | std::views::enumerate, [&](auto enumeratedList) {
auto [index, list] = enumeratedList;
heap.emplace(list.cbegin(), index);
});

std::list<T> mergedList;

while (!heap.empty()) {
auto [curIt, index] = heap.top();
heap.pop();

auto nextIt = std::next(curIt);
if (nextIt != lists[index].cend()) {
heap.emplace(nextIt, index);
}

mergedList.splice(mergedList.cend(), lists[index], curIt);
}

return mergedList;
}
};

int main() {
ListMerger<int> listMerger;
std::vector<std::list<int>> v = {std::list {1, 4, 7, 10}, std::list {3, 5, 6}, std::list {2, 8, 9}};
auto mergedList = listMerger.merge(v);

for (auto num : mergedList) {
std::cout << std::format("{} ", num);
}
}

// 1 2 3 4 5 6 7 8 9 10