jjzjj

c++ - 将递归置换生成器转换为迭代

coder 2024-02-20 原文

我在将这个用于显示给定整数集的所有排列的递归算法转换为迭代算法时遇到了一些困难。

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);
        }
    }
}

这是我目前的尝试,它是完全错误的,但如果不对问题使用 native 迭代算法,我看不出有任何方法可以更正它。我的一半尝试让我“弹出”多于“推送”(当我尝试访问空堆栈中的元素时导致错误),而另一半我“推送”多于“弹出”(无限循环)。

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);
        }
    }
}

最佳答案

您遇到的挑战是函数调用和循环结构混杂在一起。很难理清这些。

首先让我们从用递归替换所有流程操作的控制开始。

// 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);
    }
}

接下来让我们添加更多状态,以便我们在 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);
    }
}

既然我们已经完成了这项工作,我们就拥有了一种可以直接将其转换为迭代版本的形式。这是转换

void recursiveForm (params, recursiveState) {
    topHalf...
    if (cond) {
        recursiveForm(...)
    }
    bottomHalf...
}

成为

void iterativeForm(params) {
    initializeStacks...
    pushStacks...
    topHalf...
    while (stacks not empty) {
        if (cond) {
            pushStacks...
            topHalf...
        }
        else {
            bottomHalf...
            popStacks...
        }
    }
}

因此应用该模式我们得到类似的东西:

// 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());
            }
        }
    }
}

(警告,所有代码都未经测试,甚至可能无法编译。但这个想法是正确的。而且它绝对是相同的算法。)

关于c++ - 将递归置换生成器转换为迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6716847/

有关c++ - 将递归置换生成器转换为迭代的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  8. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  9. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  10. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

随机推荐