294 lines
7.1 KiB
C++
294 lines
7.1 KiB
C++
#include "PmergeMe.hpp"
|
|
|
|
PmergeMe::PmergeMe()
|
|
{
|
|
}
|
|
|
|
PmergeMe::PmergeMe(const PmergeMe &other)
|
|
{
|
|
this->_vec = other._vec;
|
|
this->_deq = other._deq;
|
|
}
|
|
|
|
PmergeMe &PmergeMe::operator=(const PmergeMe &other)
|
|
{
|
|
this->_vec = other._vec;
|
|
this->_deq = other._deq;
|
|
return (*this);
|
|
}
|
|
|
|
PmergeMe::~PmergeMe()
|
|
{
|
|
}
|
|
|
|
void PmergeMe::printDeque() const
|
|
{
|
|
for (std::deque<int>::const_iterator it = _deq.begin(); it != _deq.end(); ++it)
|
|
std::cout << *it << " ";
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
void PmergeMe::printVector() const
|
|
{
|
|
for (std::vector<int>::const_iterator it = _vec.begin(); it != _vec.end(); ++it)
|
|
std::cout << *it << " ";
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
void PmergeMe::parseInput(int ac, char **av)
|
|
{
|
|
std::string token;
|
|
int n;
|
|
|
|
for (int i = 1; i < ac; i++) {
|
|
std::istringstream ss(av[i]);
|
|
while (ss >> token)
|
|
{
|
|
std::istringstream iss(token);
|
|
if (!(iss >> n) || !iss.eof() || n < 0)
|
|
throw std::runtime_error("Error");
|
|
if (std::find(_vec.begin(), _vec.end(), n) != _vec.end())
|
|
throw std::runtime_error("Error");
|
|
_vec.push_back(n);
|
|
_deq.push_back(n);
|
|
}
|
|
}
|
|
if (_vec.empty())
|
|
throw std::runtime_error("Error");
|
|
}
|
|
|
|
void PmergeMe::run(int ac, char **av)
|
|
{
|
|
std::cout << std::fixed << std::setprecision(5);
|
|
parseInput(ac, av);
|
|
std::cout << "Before: ";
|
|
printVector();
|
|
sortVector();
|
|
sortDeque();
|
|
std::cout << "After: ";
|
|
printVector();
|
|
std::cout << "Time to process a range of " << _vec.size() << " elements with std::vector : " << _vecTime << " us" << std::endl;
|
|
std::cout << "Time to process a range of " << _deq.size() << " elements with std::deque : " << _deqTime << " us" << std::endl;
|
|
}
|
|
|
|
void PmergeMe::sortVector()
|
|
{
|
|
clock_t start = clock();
|
|
_vec = fordJohnsonVec(_vec);
|
|
clock_t end = clock();
|
|
_vecTime = (double)(end - start) * 1e6 / CLOCKS_PER_SEC;
|
|
}
|
|
|
|
std::vector<std::pair<int, int> > makePairs(std::vector<int> v)
|
|
{
|
|
std::vector<std::pair<int, int> > pairs;
|
|
for (size_t i = 0; i + 1 < v.size(); i += 2)
|
|
{
|
|
int a = v[i];
|
|
int b = v[i + 1];
|
|
if (a >= b)
|
|
pairs.push_back(std::make_pair(a, b));
|
|
else
|
|
pairs.push_back(std::make_pair(b, a));
|
|
}
|
|
return pairs;
|
|
}
|
|
|
|
std::vector<std::pair<int, int> > reorderPairs(std::vector<std::pair<int, int> > pairs, std::vector<int> winners)
|
|
{
|
|
std::vector<std::pair<int, int> > reordered;
|
|
for (size_t i = 0; i < winners.size(); i++)
|
|
{
|
|
for (size_t j = 0; j < pairs.size(); j++)
|
|
{
|
|
if (pairs[j].first == winners[i])
|
|
{
|
|
reordered.push_back(pairs[j]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return reordered;
|
|
}
|
|
|
|
std::vector<size_t> generateInsertionOrder(std::vector<int> pend)
|
|
{
|
|
std::vector<size_t> order;
|
|
std::vector<size_t> jacob;
|
|
jacob.push_back(0);
|
|
jacob.push_back(1);
|
|
while (jacob.back() <= pend.size())
|
|
jacob.push_back(jacob.back() + 2 * jacob[jacob.size() - 2]);
|
|
for (size_t k = 3; k < jacob.size(); k++)
|
|
{
|
|
size_t high = jacob[k] - 2;
|
|
if (high >= pend.size())
|
|
high = pend.size() - 1;
|
|
size_t low = jacob[k - 1] - 1;
|
|
for (size_t idx = high + 1; idx > low; idx--)
|
|
order.push_back(idx - 1);
|
|
}
|
|
return order;
|
|
}
|
|
|
|
std::vector<int> PmergeMe::fordJohnsonVec(std::vector<int> v)
|
|
{
|
|
if (v.size() <= 1)
|
|
return v;
|
|
|
|
std::vector<std::pair<int, int> > pairs = makePairs(v);
|
|
int straggler = 0;
|
|
bool hasStraggler = false;
|
|
if (v.size() % 2 != 0)
|
|
{
|
|
straggler = v.back();
|
|
hasStraggler = true;
|
|
}
|
|
|
|
std::vector<int> winners;
|
|
for (size_t i = 0; i < pairs.size(); i++)
|
|
winners.push_back(pairs[i].first);
|
|
winners = fordJohnsonVec(winners);
|
|
pairs = reorderPairs(pairs, winners);
|
|
|
|
std::vector<int> mainChain;
|
|
mainChain.push_back(pairs[0].second);
|
|
for (size_t i = 0; i < pairs.size(); i++)
|
|
{
|
|
mainChain.push_back(pairs[i].first);
|
|
}
|
|
|
|
std::vector<int> pend;
|
|
for (size_t i = 1; i < pairs.size(); i++)
|
|
{
|
|
pend.push_back(pairs[i].second);
|
|
}
|
|
|
|
std::vector<size_t> order = generateInsertionOrder(pend);
|
|
for (size_t i = 0; i < order.size(); i++)
|
|
{
|
|
int value = pend[order[i]];
|
|
int aiValue = pairs[order[i] + 1].first;
|
|
std::vector<int>::iterator aiPos = std::find(mainChain.begin(), mainChain.end(), aiValue);
|
|
std::vector<int>::iterator insertPos = std::upper_bound(mainChain.begin(), aiPos, value);
|
|
mainChain.insert(insertPos, value);
|
|
}
|
|
|
|
if (hasStraggler)
|
|
{
|
|
std::vector<int>::iterator insertPos = std::upper_bound(mainChain.begin(), mainChain.end(), straggler);
|
|
mainChain.insert(insertPos, straggler);
|
|
}
|
|
return mainChain;
|
|
}
|
|
|
|
void PmergeMe::sortDeque()
|
|
{
|
|
clock_t start = clock();
|
|
_deq = fordJohnsonDeque(_deq);
|
|
clock_t end = clock();
|
|
_deqTime = (double)(end - start) * 1e6 / CLOCKS_PER_SEC;
|
|
}
|
|
|
|
std::deque<std::pair<int, int> > makePairs(std::deque<int> d)
|
|
{
|
|
std::deque<std::pair<int, int> > pairs;
|
|
for (size_t i = 0; i + 1 < d.size(); i += 2)
|
|
{
|
|
int a = d[i];
|
|
int b = d[i + 1];
|
|
if (a >= b)
|
|
pairs.push_back(std::make_pair(a, b));
|
|
else
|
|
pairs.push_back(std::make_pair(b, a));
|
|
}
|
|
return pairs;
|
|
}
|
|
|
|
std::deque<std::pair<int, int> > reorderPairs(std::deque<std::pair<int, int> > pairs, std::deque<int> winners)
|
|
{
|
|
std::deque<std::pair<int, int> > reordered;
|
|
for (size_t i = 0; i < winners.size(); i++)
|
|
{
|
|
for (size_t j = 0; j < pairs.size(); j++)
|
|
{
|
|
if (pairs[j].first == winners[i])
|
|
{
|
|
reordered.push_back(pairs[j]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return reordered;
|
|
}
|
|
|
|
std::deque<size_t> generateInsertionOrder(std::deque<int> pend)
|
|
{
|
|
std::deque<size_t> order;
|
|
std::deque<size_t> jacob;
|
|
jacob.push_back(0);
|
|
jacob.push_back(1);
|
|
while (jacob.back() <= pend.size())
|
|
jacob.push_back(jacob.back() + 2 * jacob[jacob.size() - 2]);
|
|
for (size_t k = 3; k < jacob.size(); k++)
|
|
{
|
|
size_t high = jacob[k] - 2;
|
|
if (high >= pend.size())
|
|
high = pend.size() - 1;
|
|
size_t low = jacob[k - 1] - 1;
|
|
for (size_t idx = high + 1; idx > low; idx--)
|
|
order.push_back(idx - 1);
|
|
}
|
|
return order;
|
|
}
|
|
|
|
std::deque<int> PmergeMe::fordJohnsonDeque(std::deque<int> d)
|
|
{
|
|
if (d.size() <= 1)
|
|
return d;
|
|
|
|
std::deque<std::pair<int, int> > pairs = makePairs(d);
|
|
int straggler = 0;
|
|
bool hasStraggler = false;
|
|
if (d.size() % 2 != 0)
|
|
{
|
|
straggler = d.back();
|
|
hasStraggler = true;
|
|
}
|
|
|
|
std::deque<int> winners;
|
|
for (size_t i = 0; i < pairs.size(); i++)
|
|
winners.push_back(pairs[i].first);
|
|
winners = fordJohnsonDeque(winners);
|
|
pairs = reorderPairs(pairs, winners);
|
|
|
|
std::deque<int> mainChain;
|
|
mainChain.push_back(pairs[0].second);
|
|
for (size_t i = 0; i < pairs.size(); i++)
|
|
{
|
|
mainChain.push_back(pairs[i].first);
|
|
}
|
|
|
|
std::deque<int> pend;
|
|
for (size_t i = 1; i < pairs.size(); i++)
|
|
{
|
|
pend.push_back(pairs[i].second);
|
|
}
|
|
|
|
std::deque<size_t> order = generateInsertionOrder(pend);
|
|
for (size_t i = 0; i < order.size(); i++)
|
|
{
|
|
int value = pend[order[i]];
|
|
int aiValue = pairs[order[i] + 1].first;
|
|
std::deque<int>::iterator aiPos = std::find(mainChain.begin(), mainChain.end(), aiValue);
|
|
std::deque<int>::iterator insertPos = std::upper_bound(mainChain.begin(), aiPos, value);
|
|
mainChain.insert(insertPos, value);
|
|
}
|
|
|
|
if (hasStraggler)
|
|
{
|
|
std::deque<int>::iterator insertPos = std::upper_bound(mainChain.begin(), mainChain.end(), straggler);
|
|
mainChain.insert(insertPos, straggler);
|
|
}
|
|
return mainChain;
|
|
} |