c# – 递归函数堆栈无处不在地共享一个变量

c# – 递归函数堆栈无处不在地共享一个变量,第1张

概述我试图制作一个程序,使用回溯在迷宫中找到哈密顿路径.它应该返回编号为迷宫的迷宫上的路径.问题是当一个堆栈倒退时,其中一个变量(它是迷宫的表示)从调用继承,而其他变量(即使它们以相同的方式被声明),也不会(这很好).我尝试了几个解决方法,包括通过创建一个单独的类来实例化,我包含了调试消息.这是代码,有一些注释可以提供帮助. using System;namespace ConsoleAppli 我试图制作一个程序,使用回溯在迷宫中找到哈密顿路径.它应该返回编号为迷宫的迷宫上的路径.问题是当一个堆栈倒退时,其中一个变量(它是迷宫的表示)从调用继承,而其他变量(即使它们以相同的方式被声明),也不会(这很好).我尝试了几个解决方法,包括通过创建一个单独的类来实例化,我包含了调试消息.这是代码,有一些注释可以提供帮助.

using System;namespace ConsoleApplication1{    //I made a separate class for the function    class btr    {        public short[,] mz = new short[,] { };//trIEd to pull the variable out of the function,no success         public voID bt(int i,int j,int l)        {            bool ok;            ok = true;            Console.Writeline("in" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //deBUG message for entering            if (i > 0 && mz[i - 1,j] == 0)            {                ok = false;                mz[i,j] = 1; // 1 aka go up                var x = new btr { };                //my attempt to avoID the problem by instantiating the function,no success...                x.mz = mz;                x.bt(i - 1,j,l);                //When this function exits the mz variable is copIEd to this one. Same for all the ifs below            }            if (j > 0 && mz[i,j - 1] == 0)            {                ok = false;                mz[i,j] = 2; //2 aka go left                var x = new btr { };                x.mz = mz;                x.bt(i,j - 1,l);            }            if (i < l && mz[i + 1,j] = 3;//3 aka go down                 var x = new btr { };                x.mz = mz;                x.bt(i + 1,l);            }            if (j < l && mz[i,j + 1] == 0)            {                ok = false;                mz[i,j] = 4;//4 aka go right                 var x = new btr { };                x.mz = mz;                x.bt(i,j + 1,l);            }            Console.Writeline("out" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n');  //deBUG message for exiting            if (ok) //this is for printing the solution when it is found            {                mz[i,j] = 8;// 8 aka the end                foreach (int x in mz)                {                    if (x == 0) { ok = false; break; }                }                if (ok)                    Console.Writeline("result" + '\n' + Program.print(mz,l));            }        }    }    class Program    {//this is just for preparing the first call     static short[,] test = new short[2,2] { { 0,0},{ 0,0} };    static voID Main(string[] args)    {        var x= new btr { };        x.mz = test;        x.bt(0,1);    }    public static string print(short[,] vr,int l)//casts my array into a string that can be printed    {        string s = "";        for (int i = 0; i <= l; i++)        {            for (int j = 0; j <= l; j++)            {                s += vr[i,j];            }            s += '\n';        }        return s;    }}

}

我作为测试给出了没有任何障碍的2×2迷宫(由测试声明全0表示)并且它应该输出2个解决方案,它只输出一个并且解决方案被“注入”到堆栈中.这是输出:

in0000i0j0in3000i1j0in3040i1j1in3041i0j1out3041i0j1result3841out3841i1j1out3841i1j0out3841i0j0

正如您所看到的,当函数退出迷宫时仍然是38 41而不是逐渐回落到00 00,因此可以计算出更多的解决方案.我和j不受影响.

解决方法 我同意在处理递归时不变性是一种有用的技术,特别是在需要反向跟踪的情况下.也就是说,它可以在处理数组时产生不必要的开销,特别是如果它们很大.

在您的场景中,因为您在进行递归调用之前知道要修改的数组的哪个元素,所以您可以在递归调用返回后简单地重置该值.从某种意义上说,您正在利用调用堆栈来保留状态 – 在这种情况下,修改了数组元素的i和j – 并使用它来恢复递归调用后的状态.

这看起来像这样:

public voID bt(int i,int l){    bool ok;    ok = true;    Console.Writeline("in" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n'); //deBUG message for entering    if (i > 0 && mz[i - 1,j] == 0)    {        ok = false;        mz[i,j] = 1; // 1 aka go up        bt(i - 1,l);        mz[i,j] = 0;        //When this function exits the mz variable is copIEd to this one. Same for all the ifs below    }    if (j > 0 && mz[i,j - 1] == 0)    {        ok = false;        mz[i,j] = 2; //2 aka go left        bt(i,j] = 0;    }    if (i < l && mz[i + 1,j] = 3;//3 aka go down         bt(i + 1,j] = 0;    }    if (j < l && mz[i,j + 1] == 0)    {        ok = false;        mz[i,j] = 4;//4 aka go right         bt(i,j] = 0;    }    Console.Writeline("out" + '\n' + Program.print(mz,l) + 'i' + i + 'j' + j + '\n');  //deBUG message for exiting    if (ok) //this is for printing the solution when it is found    {        mz[i,j] = 8;// 8 aka the end        foreach (int x in mz)        {            if (x == 0) { ok = false; break; }        }        if (ok)            Console.Writeline("result" + '\n' + Program.print(mz,l));    }}

注意mz [i,j] = 0;每次通话后.

如果您愿意,甚至可以将mz变量放回方法参数列表中.您只处理数组的单个实例,因此将它保留为类字段还是方法参数并不重要.

总结

以上是内存溢出为你收集整理的c# – 递归函数堆栈无处不在地共享一个变量全部内容,希望文章能够帮你解决c# – 递归函数堆栈无处不在地共享一个变量所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1232929.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存