我试着想一下迭代这个函数。这似乎有可能,但我目前找不到这样做的方法。那么甚至有可能证明这个函数不能以任何方式迭代吗?迭代的意思是根本不使用递归函数调用。
//我喜欢这个新的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());
}
}
答案 0 :(得分:3)
我认为你问的是这个递归函数是尾递归。尾递归函数可以很容易地重写为循环,并且不需要堆栈来跟踪多个局部变量帧。此函数不尾递归;实际上,每次迭代可能多次调用自身的任何递归函数都不可能是尾递归。
非尾递归的递归函数仍然可以迭代编写,但是你需要某种堆栈才能跟踪计算的状态,这样你就可以在解决嵌套的子问题后回到它。使用的空间量至少与嵌套深度成比例。
当然,一个非尾递归的函数有时可以被重写,以便它是尾递归的。在某些情况下,您需要完全更改所使用的算法才能实现此目的。
答案 1 :(得分:1)
这个功能当然可以迭代。事实上,标准库中有一个函数可以迭代地执行: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
是如何做到的,但很高兴有一个可能的实现描述here。