ajn*_*ral 4 c++ algorithm recursion permutation
我在转换这个递归算法时遇到了一些困难,该算法用于将给定整数集的所有排列显示为迭代整数.
void getPermutationsR(int v[], int n, int i)
{
if (i == n)
{
//Display contents of v
}
else
{
for (int j=i; j<n; j++)
{
swap (v, i, j);
getPermutationsR(v, n, i+1);
swap (v, i, j);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我目前的尝试,这是完全错误的,但我没有看到任何方法来纠正它,而不使用本机迭代算法的问题.我的一半尝试让我'弹出'超过'推'(当我试图访问空堆栈中的元素时导致错误)而另一半我'推''超过'弹出'(无限循环).
void getPermutationsI(int v[], int n, int i)
{
stack<int> iStack;
stack<int> jStack;
iStack.push(i);
jStack.push(i);
while(iStack.size() > 0)
{
if (iStack.top() == n)
{
jStack.pop();
iStack.pop();
//Display contents of v
}
else
{
for (int j = iStack.top(); j < n; j++)
{
//swap
//something to do with jStack
}
//swap
iStack.push(i+1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您遇到的挑战是您已经混合了函数调用和循环结构.很难解开那些.
首先让我们开始用递归替换所有流操作控制.
// You'll want to start with getPermutionsR(v, n, 0, 0)
void getPermutationsR(int v[], int n, int i, int j)
{
if (i == n)
{
//Display contents of v
}
else if (j == n) {
// By doing nothing, we break out of the loop
}
else
{
// This was your recursive call inside of the loop.
// Note that I'm sending you to to the first loop iteration here.
swap (v, i, j);
getPermutationsR(v, n, i+1, i+1);
swap (v, i, j);
// And the next loop iteration
getPermutationsR(v, n, i, j+1);
}
}
Run Code Online (Sandbox Code Playgroud)
接下来让我们添加更多状态,这样我们在if条件中只有一个递归调用.
// You'll want to start with getPermutionsR(v, n, 0, 0, 1)
void getPermutationsR(int v[], int n, int i, int j, bool firstCall)
{
if (i == n)
{
//Display contents of v
}
int x = i;
int y = j+1;
if (firstCall) {
swap (v, i, j);
x = i+1;
y = i+1;
}
// My one recursive call. Note that i=n implies j=n.
if (j < n) {
getPermutationsR(v, n, x, y, !firstCall);
}
if (firstCall) {
swap (v, i, j);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们已经完成了这个,我们将它以一种形式,我们可以以一种简单的方式将其转换为迭代版本.这是转型
void recursiveForm (params, recursiveState) {
topHalf...
if (cond) {
recursiveForm(...)
}
bottomHalf...
}
Run Code Online (Sandbox Code Playgroud)
变
void iterativeForm(params) {
initializeStacks...
pushStacks...
topHalf...
while (stacks not empty) {
if (cond) {
pushStacks...
topHalf...
}
else {
bottomHalf...
popStacks...
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以应用这种模式我们得到类似的东西:
// You'll want to start with getPermutionsR(v, n, 0, 0, 1)
void getPermutationsI(int v[], int n)
{
stack<int> iStack;
stack<int> jStack;
stack<bool> firstCallStack;
// pushStacks with initial value
iStack.push(0);
jStack.push(0);
firstCallStack.push(1);
// topHalf...
if (iStack.top() == n)
{
//Display contents of v
}
int x = iStack.top();
int y = jStack.top()+1;
if (firstCallStack.top()) {
swap (v, iStack.top(), jStack.top());
x = iStack.top()+1;
y = iStack.top()+1;
}
while iStack.size() > 0) {
// if (cond) {
if (jStack.top() < n) {
//pushStacks...
iStack.push(x);
jStack.push(y);
firstCallStack.push(!firstCallStack.top());
// topHalf...
if (iStack.top() == n)
{
//Display contents of v
}
x = iStack.top();
y = jStack.top()+1;
if (firstCallStack.top()) {
swap (v, iStack.top(), jStack.top());
x = iStack.top()+1;
y = iStack.top()+1;
}
}
else {
// bottomHalf...
if (firstCallStack.top()) {
swap (v, iStack.top(), jStack.top());
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(警告,所有代码都未经测试,甚至可能无法编译.但这个想法是正确的.它绝对是相同的算法.)