I assume that without libraries to the merger. Otherwise, you have to write an own linked list (this may be forward, or normal list). Rest the same. Easy example (for two lists):
#include <list>
#include <iostream>
using namespace std;
int main(void)
{
list<int> a = { 1, 3, 5, 7, 9}, b = { 2, 4 , 6, 8, 9, 10}, c; //c is out
for(auto it1 = begin(a), it2 = begin(b); it1 != end(a) || it2 != end(b);)
if(it1 != end(a) && (it2 == end(b) || *it1 < *it2)) {
c.push_back(*it1);
++it1;
}
else {
c.push_back(*it2);
++it2;
}
for(auto x : c)
cout<<x<<' ';
cout<<'\n';
}
Result:
1 2 3 4 5 6 7 8 9 9 10
Attention! You must compile with the flag -std=c++11 (or other to c++11). For example:
g++ -std=c++11 -Wall -pedantic -Wextra -O2 d.cpp -o program.out
The complexity: Θ(n)
Memory: Θ(n)
It's not hard to see, that each element is evaluated exactly once in O(1), we have n elements, so it's Θ(n).
Memory complexity is obvious. It is worth mentioning that if the two lists are no longer needed, it can be done without additional allocations (const memory).
The algorithm itself has been described so many times that it is not point to write once more.
In main problem we have lots of sequences, but the idea is the same. Here you have enriched example:
int main(void)
{
vector<vector<int> > in{{ 1, 3, 5, 7, 9}, { 2, 4 , 6, 8, 9, 10}, {2,5,7,12,10,11,18}};
vector<int> out;
typedef tuple<int, vector<int>::iterator, vector<int>::iterator> element;
priority_queue<element, vector<element>, greater<element> > least;
for(auto& x : in) //Adding iterators to the beginning of (no empty) lists
if(!x.empty()) //and other parts of the element (value and end of vector)
least.emplace(x.front(),begin(x),end(x));
while(!least.empty()) { //Solving
auto temp = least.top(); least.pop();
out.push_back(get<0>(temp)); //Add the smallest at the end of out
++get<1>(temp);
if(get<1>(temp) != get<2>(temp)){//If this is not the end
get<0>(temp) = *get<1>(temp);
least.push(temp); //Update queue
}
}
for(const auto& x : out) //Print solution
cout<<x<<' ';
cout<<'\n';
}
The complexity: Θ(n log k)
Memory: Θ(n)
Pop and insert operations are in O(log k), we perform them n times, so it's O(n log k).
Memory is still obvious, we have always k elements in priority_queue, and O(n) in out sequence.