Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在递归函数中初始化变量_Java_Variables_Recursion_Linked List_Initialization - Fatal编程技术网

Java 在递归函数中初始化变量

Java 在递归函数中初始化变量,java,variables,recursion,linked-list,initialization,Java,Variables,Recursion,Linked List,Initialization,我正在做一个递归函数,它必须没有参数才能得到链表的长度 public int lengthHelper() { if (first == null) { return 0; } else { first = first.next; return 1 + length(); } } 问题是,通过使用first=first.next,我将首先破坏,首先是我的标题。所以我想先在函数中复制(而不是我丑陋的包装器脚本),但递归会让这

我正在做一个递归函数,它必须没有参数才能得到链表的长度

public int lengthHelper() {
    if (first == null) {
        return 0;
    } else {
        first = first.next;
        return 1 + length();
    }
}
问题是,通过使用first=first.next,我将首先破坏,首先是我的标题。所以我想先在函数中复制(而不是我丑陋的包装器脚本),但递归会让这变得很麻烦。你知道怎么做吗

顺便说一句,这是我想删除的包装:

public int length() {
    Node temp = copy(first);
    int output = this.lengthHelper();
    first = copy(temp);
    return output;
}

我之所以有这些限制,是因为这是一个基于任务的个人挑战。递归+包装器已经足够了,但从那以后我一直在思考是否有可能以更干净的方式解决它。

没有干净的方式来解决这个问题。我建议这样做:

public int length() {
    return computeLength(this.first);
}
private int computeLength(Node node) {
    if (node == null) return 0;
    return 1 + computeLength(node.next);
}

做这件事没有干净的方法。我建议这样做:

public int length() {
    return computeLength(this.first);
}
private int computeLength(Node node) {
    if (node == null) return 0;
    return 1 + computeLength(node.next);
}

这是一个相当人为的要求。:)但是,如何先将
存储在本地堆栈帧中,然后在返回之前恢复它呢

这听起来像是一个家庭作业问题,所以也许我不应该说出完整的答案。但基本上是这样的:

  • 创建一个局部变量来存储
    first的当前值
  • 首先更新
    ,从而打破列表(如您所指出的)
  • 向下递归,并将该递归的结果保存在第二个局部变量中
  • 使用第一个局部变量还原第一个
  • 从第二个局部变量返回结果

  • 要获得额外的积分,请尝试这样做,如果您在过程中碰巧遇到异常(例如堆栈溢出),则不会打破列表。提示:
    try finally

    这是一个非常人为的要求。:)但是,如何先将
    存储在本地堆栈帧中,然后在返回之前恢复它呢

    这听起来像是一个家庭作业问题,所以也许我不应该说出完整的答案。但基本上是这样的:

    • 创建一个局部变量来存储
      first的当前值
    • 首先更新
      ,从而打破列表(如您所指出的)
    • 向下递归,并将该递归的结果保存在第二个局部变量中
    • 使用第一个局部变量还原第一个
  • 从第二个局部变量返回结果

  • 要获得额外的积分,请尝试这样做,如果您在过程中碰巧遇到异常(例如堆栈溢出),则不会打破列表。提示:
    try finally

    如果我正确理解
    首先
    是递归数据结构
    节点
    ,并且在非递归容器类
    列表
    (例如)中,您需要定义递归方法(不带参数)

    然后,解决方案是在
    List
    中使用一个方法,该方法生成一个新的尾部/剩余部分列表,而不使用
    first
    。下面我假设一个构造函数有一个节点

    class Node { }
    public class List {
        Node first;
    
        public int length() {
            if (first == null) {
                return 0;
            } else {
                List tail = new List(first.next);
                return 1 + tail.length();
            }
        }
    

    如果我正确理解了
    首先
    是递归数据结构
    节点
    ,并且在非递归容器类
    列表
    (例如)中,您需要定义一个递归方法(不带参数)

    然后,解决方案是在
    List
    中使用一个方法,该方法生成一个新的尾部/剩余部分列表,而不使用
    first
    。下面我假设一个构造函数有一个节点

    class Node { }
    public class List {
        Node first;
    
        public int length() {
            if (first == null) {
                return 0;
            } else {
                List tail = new List(first.next);
                return 1 + tail.length();
            }
        }
    


    递归方法是否必须是无参数的?我是否正确地假设
    first
    是列表的开头,并且是一个私有实例变量?是和是。不允许使用参数,第一个是我的headIs
    length
    可能应该是list类的一个方法?递归方法是否必须是无参数的?我是否正确地假设
    first
    是列表的头并且是一个私有实例变量?是和是。不允许使用参数,首先是我的headIs
    length
    可能应该是list类的一个方法?这仍然是相同的问题,但比我做的要干净得多。可能会满足于它,除非有人有一个尤里卡时刻。我认为没有某种形式的参数是不可能的。通过使用类变量存储递归状态(在您的示例中是“第一个”对象),您只需冒着在其他地方破坏它的风险。我可以问你为什么要这样做吗?这仍然是一个问题,但它比我做的要干净得多。可能会满足于它,除非有人有一个尤里卡时刻。我认为没有某种形式的参数是不可能的。通过使用类变量存储递归状态(在您的示例中是“第一个”对象),您只需冒着在其他地方破坏它的风险。我可以问一下你为什么要这样做吗?太棒了,我看起来就是这样。老实说,这是一个家庭作业问题。不过,我的教授对难看的包装解决方案很满意。在那之后,我无法停止思考是否有办法将其移除。个人挑战,如果你愿意的话。太棒了,正是我所期待的。老实说,这是一个家庭作业问题。不过,我的教授对难看的包装解决方案很满意。在那之后,我无法停止思考是否有办法将其移除。这实际上与我下面的答案非常相似,主要的两个区别是:(1)不破坏列表,然后修复列表;(2)临时变量在我的堆栈上,在这个解决方案中位于堆中(
    newlist
    )。它们的相似之处在于,在这两种情况下,您都在创建一个尾部列表(在我的示例中,通过将
    this
    修改为它自己的尾部),获取它的长度,然后丢弃它(在我的示例中,通过还原“this”,让
    list tail
    超出范围)。@yshavit是的,我看到您也喜欢算法和数据结构+1是的。:)我比我更喜欢你的解决方案,尽管它会搅动更多的对象。它的代码更少,线程安全,在出现错误时不会有破坏列表的风险,并且保持每个列表不变。最后一部分实际上让事情变得更糟