refs #338 Topological sorting algorithm, to be used for sorting CLogPattern.

This commit is contained in:
Mathew Sutcliffe
2014-10-13 20:24:40 +01:00
parent 755d1afe0d
commit 24485f6331
4 changed files with 150 additions and 0 deletions

View File

@@ -14,6 +14,7 @@
#include "samplesjson.h" #include "samplesjson.h"
#include "samplesvariant.h" #include "samplesvariant.h"
#include "samplesperformance.h" #include "samplesperformance.h"
#include "samplesalgorithm.h"
#include "blackmisc/blackmiscfreefunctions.h" #include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/pqallquantities.h" #include "blackmisc/pqallquantities.h"
@@ -40,6 +41,7 @@ int main(int argc, char *argv[])
qDebug() << "4 .. Metadata"; qDebug() << "4 .. Metadata";
qDebug() << "5 .. Variant"; qDebug() << "5 .. Variant";
qDebug() << "6 .. Performance"; qDebug() << "6 .. Performance";
qDebug() << "7 .. Algorithms";
qDebug() << "-----"; qDebug() << "-----";
qDebug() << "x .. Bye"; qDebug() << "x .. Bye";
QTextStream qtin(stdin); QTextStream qtin(stdin);
@@ -51,6 +53,7 @@ int main(int argc, char *argv[])
else if (s.startsWith("4")) { CSamplesMetadata::samples(); } else if (s.startsWith("4")) { CSamplesMetadata::samples(); }
else if (s.startsWith("5")) { CSamplesVariant::samples(); } else if (s.startsWith("5")) { CSamplesVariant::samples(); }
else if (s.startsWith("6")) { CSamplesPerformance::samples(); } else if (s.startsWith("6")) { CSamplesPerformance::samples(); }
else if (s.startsWith("7")) { CSamplesAlgorithm::samples(); }
else if (s.startsWith("x")) { break; } else if (s.startsWith("x")) { break; }
} }
while (true); while (true);

View File

@@ -0,0 +1,42 @@
/* Copyright (C) 2014
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "samplesalgorithm.h"
#include "blackmisc/algorithm.h"
#include <QDebug>
#include <QString>
namespace BlackMiscTest
{
/*
* Samples
*/
int CSamplesAlgorithm::samples()
{
QStringList src { "a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3" };
std::random_shuffle(src.begin(), src.end());
qDebug() << src;
qDebug() << "topologicallySortedInsert";
QStringList dst;
int count = 0;
auto cmp = [ & ](const QString &a, const QString &b) { count++; return a[0] == b[0] && a[1] < b[1]; };
for (const auto &s : src) { BlackMisc::topologicallySortedInsert(dst, s, cmp); }
qDebug() << count << "comparisons";
qDebug() << dst;
qDebug() << "topologicalSort";
count = 0;
BlackMisc::topologicalSort(dst.begin(), dst.end(), cmp);
qDebug() << count << "comparisons";
qDebug() << dst;
return 0;
}
} // namespace

View File

@@ -0,0 +1,26 @@
/* Copyright (C) 2014
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISCTEST_SAMPLESALGORITHM_H
#define BLACKMISCTEST_SAMPLESALGORITHM_H
namespace BlackMiscTest
{
//! Samples for our algorithms
class CSamplesAlgorithm
{
public:
//! Run the samples
static int samples();
};
} // namespace
#endif

79
src/blackmisc/algorithm.h Normal file
View File

@@ -0,0 +1,79 @@
/* Copyright (C) 2014
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_ALGORITHM_H
#define BLACKMISC_ALGORITHM_H
#include <QtGlobal>
#include <algorithm>
#include <iterator>
namespace BlackMisc
{
/*!
* Topological sorting algorithm.
*
* \param begin Begin iterator of the range to sort.
* \param end End iterator of the range to sort.
* \param comparator A binary function which defines a less-than relation between elements of the range.
* The ordering it induces must be a partial ordering, which is a more relaxed requirement
* than the strict weak ordering required by most standard sorting algorithms.
*
* \see https://en.wikipedia.org/wiki/Topological_sorting
* \see https://en.wikipedia.org/wiki/Partial_ordering
*/
template <typename I, typename F>
void topologicalSort(I begin, I end, F comparator)
{
using value_type = typename std::iterator_traits<I>::value_type;
auto part = begin;
while (part != end)
{
auto newPart = std::partition(part, end, [ = ](const value_type &a)
{
return std::none_of(part, end, [ =, &a ](const value_type &b)
{
return comparator(b, a);
});
});
Q_ASSERT_X(newPart != part, "BlackMisc::topologicalSort", "Cyclic less-than relation detected (not a partial ordering)");
part = newPart;
}
}
/*!
* Insert an element into a sequential container while preserving the topological ordering of the container.
*
* \param container A sequential container.
* \param value The value to insert.
* \param comparator A binary function which defines a less-than relation between elements of the container.
* The ordering it induces must be a partial ordering, which is a more relaxed requirement
* than the strict weak ordering required by most standard sorting algorithms.
*
* \see https://en.wikipedia.org/wiki/Topological_sorting
* \see https://en.wikipedia.org/wiki/Partial_ordering
*/
template <typename C, typename T, typename F>
void topologicallySortedInsert(C &container, T &&value, F comparator)
{
using value_type = typename C::value_type;
using reverse = std::reverse_iterator<typename C::iterator>;
auto rit = std::find_if(reverse(container.end()), reverse(container.begin()), [ =, &value ](const value_type &lhs)
{
return comparator(lhs, value);
});
Q_ASSERT_X(std::none_of(rit, reverse(container.begin()), [ =, &value ](const value_type &rhs) { return comparator(value, rhs); }),
"BlackMisc::topologicallySortedInsert", "Cyclic less-than relation detected (not a partial ordering)");
container.insert(rit.base(), std::forward<T>(value));
}
}
#endif