gpt4 book ai didi

c++ - 如何根据值的某些转换值对范围进行排序?

转载 作者:搜寻专家 更新时间:2023-10-31 02:03:19 24 4
gpt4 key购买 nike

arr 是某种类型Tfunc(const &T) 某种计算量大的函数的数组。要根据 func(T) 的值对 arr 进行排序,我们可以天真地编写。

std::sort(arr.begin(), arr.end(), [](const T& a, const T&b) {
return func(a) < func(b);
}

然而,这将平均调用 func O(nlogn) 次。显然,我们只需要 n 次调用。有什么惯用且简洁的方法可以做到这一点吗?

我知道以下两种解决方案,但我想找到一个更好的。

  • Tfunc 的返回值打包到结构中并对其进行排序。这在计算上是最优的,但它还在排序之前对初始数组进行了一次完整复制,然后又进行了一次完整复制以将值放回 arr

  • 创建第二个数组并对数组进行并行排序。据我所知,没有惯用的方法可以以这种方式对两个数组进行排序。这可以通过编写自定义迭代器和交换函数来完成。这已经足够好了,但它还需要比理想情况更多的样板代码。

理想的解决方案是基于 STL 的,样板代码越少越好,但欢迎所有贡献。

最佳答案

第一个非通用解决方案

您需要的是函数结果的内存。如果你的函数 fun 没有副作用并且在 std::sort 中使用它我推断它不会我会想到这样的事情:

#include <unordered_map>

template<class T, class U>
class caller{
public:
const U &call(const T& t) const{
auto found = memoized.find(t);
if (found != memoized.end())
return found->second;

return memoized.insert(std::make_pair(t, fun(t))).first->second;
}
private:
mutable std::unordered_map<T, U> memoized;
};

它的用法是这样的:

caller<T, decltype(func(std::declval<T>()))> c;
std::sort(arr.begin(), arr.end(), [](const T& a, const T&b) {
return c.call(a) < c.call(b);
}

更通用的解决方案

在制作完第一个解决方案后,我玩了一下,制作了一个更通用、符合 C++17 的解决方案。它应该适用于每个采用一个可复制和可散列参数的函数。看一看:

#include <unordered_map>

int fii(int){
return 0;
}

template<class T, auto fun>
class memoizer{
public:
const auto &call(const T& t) const{
auto found = memoized.find(t);
if (found != memoized.end())
return found->second;

return memoized.insert(std::make_pair(t, fun(t)))
.first->second;
}
private:
mutable std::unordered_map<T, decltype(fun(T()))> memoized;
};

auto memoized_fii = memoizer<int, fii>{};

关于c++ - 如何根据值的某些转换值对范围进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55668347/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com