62 lines
1.6 KiB
Diff
62 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000000973
|
|
--- a/source/comparators/ByGivenOrder.h
|
|
+++ b/source/comparators/ByGivenOrder.h
|
|
@@ -16,8 +16,9 @@
|
|
|
|
#pragma once
|
|
|
|
-#include <algorithm>
|
|
+#include <cstddef>
|
|
+#include <unordered_map>
|
|
#include <vector>
|
|
|
|
|
|
|
|
@@ -26,18 +27,24 @@
|
|
template<class T>
|
|
class ByGivenOrder {
|
|
public:
|
|
- explicit ByGivenOrder(const std::vector<T> &order)
|
|
- : order(order)
|
|
- {}
|
|
+ explicit ByGivenOrder(const std::vector<T> &order)
|
|
+ {
|
|
+ // Pre-build a hash map from value to index for O(1) lookup.
|
|
+ // Original code used std::find() on the vector, which is O(N)
|
|
+ // per comparison, making any sort O(N^2 log N).
|
|
+ indexMap.reserve(order.size());
|
|
+ for(std::size_t i = 0; i < order.size(); ++i)
|
|
+ indexMap.emplace(order[i], i);
|
|
+ }
|
|
|
|
bool operator()(const T &a, const T &b) const
|
|
{
|
|
- const auto findA = std::find(order.begin(), order.end(), a);
|
|
- const auto findB = std::find(order.begin(), order.end(), b);
|
|
+ const auto findA = indexMap.find(a);
|
|
+ const auto findB = indexMap.find(b);
|
|
|
|
- if(findA == order.end() && findB == order.end())
|
|
+ if(findA == indexMap.end() && findB == indexMap.end())
|
|
{
|
|
// Neither a nor b is a known value. Fall back to default comparison.
|
|
return a < b;
|
|
@@ -45,12 +52,12 @@
|
|
else
|
|
{
|
|
// Whichever is first in the array is considered smaller.
|
|
- return findA < findB;
|
|
+ // Unknown values (end iterator) sort after all known values.
|
|
+ if(findA == indexMap.end())
|
|
+ return false;
|
|
+ if(findB == indexMap.end())
|
|
+ return true;
|
|
+ return findA->second < findB->second;
|
|
}
|
|
}
|
|
|
|
@@ -58,5 +65,5 @@
|
|
private:
|
|
- const std::vector<T> ℴ
|
|
+ std::unordered_map<T, std::size_t> indexMap;
|
|
};
|