这个递归函数不可能是迭代的吗?

Is this recursive function impossible to be iterative?

本文关键字:迭代 递归函数 不可能      更新时间:2023-10-16

我试着想了一下,使这个函数迭代。这似乎是可能的,但我目前找不到这样做的方法。那么,是否有可能证明这个函数不能以任何方式迭代呢?我所说的迭代是指根本不使用递归函数调用。

我喜欢这个新的auto关键词。

void every_permutation(const std::vector<int>& v, std::vector<std::vector<int>>& vs) {
    if (v.size() == 1) {
        vs.push_back(v);
        return;
    }
    for (auto i = v.begin(); i != v.end(); ++i) {
        std::vector<int> v_2;
        for (auto j = v.begin(); j != v.end(); ++j) {
            if (j != i) {
                v_2.push_back(*j);
            }
        }
        std::vector<std::vector<int>> vs_2;
        every_permutation(v_2, vs_2);
        for (auto j = vs_2.begin(); j != vs_2.end(); ++j) {
            j->push_back(*i);
        }
        vs.insert(vs.end(), vs_2.begin(), vs_2.end());
    }
}

我想你要问的是这个递归函数是否是尾递归的。尾递归函数可以很容易地重写为循环,并且不需要堆栈来跟踪局部变量的多个帧。此函数不是尾递归函数;事实上,任何每次迭代可能多次调用自己的递归函数都不可能是尾递归函数。

不是尾递归的递归函数仍然可以迭代编写,但你需要某种堆栈来跟踪计算的状态,以便在解决嵌套子问题后可以返回它。使用的空间量至少与嵌套深度成正比。

当然,有时可以重写不是尾递归的函数,使其成为尾递归函数。在某些情况下,您需要完全更改所使用的算法才能完成此操作。

这个函数当然可以是迭代的。实际上,标准库中有一个函数可以迭代地执行此操作:std::next_permutation 。你可以这样使用它:

                                     // v-- note: v is a copy here
void every_permutation(std::vector<int> v, std::vector<std::vector<int>>& vs) {
  // because we need to start with a sorted vector to get all permutations.
  std::sort(v.begin(), v.end());
  do {
    vs.push_back(v);
  } while(std::next_permutation(v.begin(), v.end()));
}

当然,这个片段并没有告诉你std::next_permutation是如何做到的,但令人高兴的是,这里描述了一个可能的实现。