C++;-为什么使用map实现fibonacci记忆这么慢? 我试图用记忆化方法在C++中实现斐波那契函数。我的实现工作正常,但速度非常慢为什么我的实现如此缓慢?我在javascript中看到过类似的实现,它们使用对象进行记忆,而且速度非常快是因为我使用了地图数据结构吗? #include <iostream> #include <map> unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int> memo = {}); int main(void) { for (unsigned short i = 0; i <= 50; i++) { std::cout << i << " " << fib(i) << std::endl; } }; unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int> memo) { if (memo.find(n) != memo.end()) { return memo.find(n)->second; } if (n <= 2) { return 1; } memo.insert( std::pair<unsigned short, unsigned int>( n, fib(n - 1, memo) + fib(n - 2, memo))); return memo.find(n)->second; } #包括 #包括 无符号int fib(无符号短n,std::map memo={}); 内部主(空) { 对于(无符号短i=0;i

C++;-为什么使用map实现fibonacci记忆这么慢? 我试图用记忆化方法在C++中实现斐波那契函数。我的实现工作正常,但速度非常慢为什么我的实现如此缓慢?我在javascript中看到过类似的实现,它们使用对象进行记忆,而且速度非常快是因为我使用了地图数据结构吗? #include <iostream> #include <map> unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int> memo = {}); int main(void) { for (unsigned short i = 0; i <= 50; i++) { std::cout << i << " " << fib(i) << std::endl; } }; unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int> memo) { if (memo.find(n) != memo.end()) { return memo.find(n)->second; } if (n <= 2) { return 1; } memo.insert( std::pair<unsigned short, unsigned int>( n, fib(n - 1, memo) + fib(n - 2, memo))); return memo.find(n)->second; } #包括 #包括 无符号int fib(无符号短n,std::map memo={}); 内部主(空) { 对于(无符号短i=0;i,c++,performance,data-structures,dynamic-programming,memoization,C++,Performance,Data Structures,Dynamic Programming,Memoization,这是一个手动维护“调用堆栈”的示例您是否理解按引用传递参数和按值传递参数之间的区别?您是否知道按值传递参数需要复制整个参数。您认为复制映射副本需要多长时间?由于递归调用的方式B实际上没有什么有用的东西会被记忆?注意,由于映射不是通过引用传递的,所以记忆根本不会发生,因此该算法的时间复杂度大致为阶乘。使用递归计算该序列是毫无意义的,令人不安的是,它似乎被用作学习记忆的示例。有有实际应用的更好的算法。从可用性的角度来看,与其要求调用方分配和传递memo,不如创建一个包含此结构的简单类作为私有成员。然

这是一个手动维护“调用堆栈”的示例您是否理解按引用传递参数和按值传递参数之间的区别?您是否知道按值传递参数需要复制整个参数。您认为复制映射副本需要多长时间?由于递归调用的方式B实际上没有什么有用的东西会被记忆?注意,由于映射不是通过引用传递的,所以记忆根本不会发生,因此该算法的时间复杂度大致为阶乘。使用递归计算该序列是毫无意义的,令人不安的是,它似乎被用作学习记忆的示例。有有实际应用的更好的算法。从可用性的角度来看,与其要求调用方分配和传递
memo
,不如创建一个包含此结构的简单类作为私有成员。然后,创建一个
get(unsigned short)
检索/计算值的成员函数。这样,当调用方不再需要“fibonacci”时,与备忘录相关的任何内存都会自动清理作为一个扩展,该方法可以是<代码> const 和备忘录结构>代码>可更改的。考虑<代码> STD::unordeDeMAP>代码>以获得更好的性能。或者,实际上,代码> STD::向量< /代码>将是理想的选择。@ HAZIQUMUHAMMADA:我不知道正在发生的事情。C++是一种基于价值的语言。执行此操作时,
a=b;
func(对象a);…对象b:func(b)实际的拷贝是通过复制的,不是引用的,也不是指派的。我假设你过去只使用基于引用的语言。这是JavaScript或Python和C++之间的主要区别。因此,在C++中赋值、传递或返回值时,必须小心。为什么要这样做?斐波那契序列是指你的键是连续的值。因此它们可以是
向量
deque
, std::map<unsigned short, unsigned int> memo)
unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int>* memo = nullptr);

unsigned int fib(unsigned short n, std::map<unsigned short, unsigned int>* pmemo)
{
  std::map<unsigned short, unsigned int> local;
  auto& memo = pmemo?*pmemo:local;
unsigned int fib(unsigned short n)
{
  std::map<unsigned short, unsigned int> memo = {
    {0u,0u},
    {1u,1u},
    {2u,1u},
  };
  std::vector<unsigned short> todo = {n};
  while (!todo.empty()) {
    // solved?
    if (memo.find(todo.back()) != memo.end())
    {
      todo.pop_back();
      continue;
    }

    unsigned short a = todo.back()-1;
    unsigned short b = todo.back()-2;
    auto ita = memo.find(a);
    auto itb = memo.find(b);

    // solved?
    if (ita != memo.end() && itb !=  memo.end())
    {
       memo.insert( {todo.back(), ita->second+itb->second} );
       todo.pop_back();
       continue;
    }
    todo.push_back(a);
    todo.push_back(b); // could skip this actually
  }
  return memo.find(n)->second;
}