C 满足动态条件时退出递归函数

C 满足动态条件时退出递归函数,c,c++,algorithm,if-statement,recursion,C,C++,Algorithm,If Statement,Recursion,从以下位置使用函数: 如何做到这一点(停止展开递归并返回函数调用方) 尝试: if (i < 0 || quit_now == 1) return; if(i

从以下位置使用函数:

如何做到这一点(停止展开递归并返回函数调用方)


尝试:

if (i < 0 || quit_now == 1) return;
if(i<0 | | quit|u now==1)返回;
只是似乎阻止了执行,永远不会结束


PS-我甚至对旧的方法感兴趣。

一个简单的解决方案是,考虑到您的函数当前没有返回值,使用它来指示是否满足终止条件。然后,如果结果为真,您可以使用它立即退出所有递归调用

不确定我是否在这里正确捕获了您的预期逻辑,但直观的方法是这样的:

int magic(char* str, int i, int changesLeft) {
    int result;
    if (changesLeft == 0) {
            printf("%s\n", str);
            return voices(str);
    }
    if (i < 0) return 0;

    // flip current bit
    str[i] = str[i] == '0' ? '1' : '0';
    result = magic(str, i-1, changesLeft-1);

    if( !result ) {
        // or don't flip it (flip it again to undo)
        str[i] = str[i] == '0' ? '1' : '0';
        result = magic(str, i-1, changesLeft);
    }

    return result;
}
void foo(bool & ret) {
  // doStuff...
  if (ret) return;
  foo(ret);
  // doStuff...
  if (ret) return;
  foo(ret);
}
int main()
{
    hamming("0000", 2);
    /* output:
       1100
       1010
       1001
       0110
       0101
       0011
    */
}
int-magic(char*str,int-i,int-changesLeft){
int结果;
如果(changesLeft==0){
printf(“%s\n”,str);
回音;
}
如果(i<0)返回0;
//反向电流位
str[i]=str[i]='0'?'1':'0';
结果=魔术(str,i-1,changesLeft-1);
如果(!结果){
//或不翻转(再次翻转以撤消)
str[i]=str[i]='0'?'1':'0';
结果=魔术(str,i-1,changesLeft);
}
返回结果;
}

函数在两个位置递归调用自身。所以在每一个地方,你都需要检查你的退出条件。帕迪给出的答案详细说明了这一点

立即展开堆栈的另一种方法是使用
setjmp
longjmp
,它们可以用作非本地
goto

jmp_buf magic_buf;

void magic_int(char* str, int i, int changesLeft) {
        if (changesLeft == 0) {
                printf("%s\n", str);
                if (voices(str)) {
                    longjmp(magic_buf, 1);
                }
                return;
        }
        if (i < 0) return;
        // flip current bit
        str[i] = str[i] == '0' ? '1' : '0';
        magic_int(str, i-1, changesLeft-1);
        // or don't flip it (flip it again to undo)
        str[i] = str[i] == '0' ? '1' : '0';
        magic_int(str, i-1, changesLeft);
}

void magic(char* str, int i, int changesLeft) {
    if (!setjmp(magic_buf)) {
        magic(str, i, changesLeft);
    }
}

用最简单的形式来说,你可以这样做:

int magic(char* str, int i, int changesLeft) {
    int result;
    if (changesLeft == 0) {
            printf("%s\n", str);
            return voices(str);
    }
    if (i < 0) return 0;

    // flip current bit
    str[i] = str[i] == '0' ? '1' : '0';
    result = magic(str, i-1, changesLeft-1);

    if( !result ) {
        // or don't flip it (flip it again to undo)
        str[i] = str[i] == '0' ? '1' : '0';
        result = magic(str, i-1, changesLeft);
    }

    return result;
}
void foo(bool & ret) {
  // doStuff...
  if (ret) return;
  foo(ret);
  // doStuff...
  if (ret) return;
  foo(ret);
}
int main()
{
    hamming("0000", 2);
    /* output:
       1100
       1010
       1001
       0110
       0101
       0011
    */
}
然后启动递归:

bool ret = false;
foo(ret);
在您的情况下,您可以通过

if (!changesLeft) {
  printf("%s\n", str);
  ret = true;
  return;
}
设置为true将使您脱离整个调用树



您也可以在C中完成,只需使用指针而不是引用。

这是一个非递归变量。基本上,它会生成所有递增序列
0您是否尝试过goto:而不是return?@hbagdi the black sheep?:O我从来没有碰过它,但如果你发布一个证明它可以派上用场的答案,我愿意……我现在已经21岁了!!!=)/我没听清楚那是在胡扯:/Don't。他们在操纵你,或者你可以考虑一个非递归的实现。也许我应该试着写一个(或者如果你已经有了,请随意发布它作为答案)!:)而
result
应在
printf(“%s\n”,str)之后立即获取其值,就像我想的那样,对吗?是的,在每个调用方中,因为在
printf
之后返回1。堆栈上的每个调用方在得到非零结果时都停止进行递归调用。他们都会返回结果,然后一路返回。另一个好处是,第一个调用方将知道操作是否满足其终止条件。因此函数本身不必具有
printf
。你可以说:
if(magic(str,0,x))printf(“OK:%s\n”,str);else printf(“无答案”)哦,对不起,我只是注意到我没有处理
声音
的事情。复制/粘贴和惰性阅读。。。。我已经更新了。这些婴儿标准C/C++和C++是两种不同的语言。在C++中使用显式跳转是非常令人沮丧的。特别是对于像递归的普通终止这样简单的事情。如果编译器想要优化返回,它可以自由决定跳转。在一般情况下,程序员不应该关心这些细节。我认为这是一个有用的答案,它提供了对更多系统级方法的洞察。知道这些事情是很好的,但是要谨慎使用它们。@帕迪添加了一个包含异常的C++解决方案。我认为你的解决方案会遇到与PADE相同的问题,请看我的更新。这实际上类似于我在C中如何处理“异常处理”——这是非常艰巨的。但是,如果你想要干净和适当的堆栈展开,那就是最好的方法。longjmp将呼啸而过所有需要在堆栈框架上发生的事情,而您将度过一段糟糕的时光。只有在您没有任何事情要处理的情况下才可以接受-没有释放、没有取消初始化等等。请注意,在线程之间访问
ret
的真实值时,可能会出现内存排序问题和争用条件,一个合适的解决方案可能包括使用原子线程,但这看起来不像是一个多线程的场景。多线程场景中的竞争条件保护不言而喻。Alex,很抱歉在这么长时间后发表评论,但是向量
a
应该保留位必须反转的索引。因此,如果
a
包含当前索引
i
,我们将打印
1
,而不是
0
,反之亦然。否则,我们将按原样打印位(请参见
其他
-部分)。谢谢AlexD,我对该算法非常感兴趣,并试图分析其时间复杂度,如@gsamaras哦,对不起,如果我知道它是针对
O
-复杂度的,我会更准确,并按照ruakh的建议删除干运行!我对保罗的评论加了一句。
int main()
{
    hamming("0000", 2);
    /* output:
       1100
       1010
       1001
       0110
       0101
       0011
    */
}