如何做这个java递归

时间:2010-09-22 01:40:43

标签: java recursion

我有这段代码:

static int countStu = 0;

public static int countStudent(Node<Student> lst) {
    // pre : true
    // post : res = number of students in list
    if (lst != null) {
        countStu++;
        countStudent(lst.getNext());      
    }
    return countStu;
}

这种方法存在的问题是我必须在countStu方法之外声明countStudent(),这在我想要两次调用countStudent()的情况下效果不佳,它会使返回价值翻倍。如何解决此问题并能够无限次地调用countStudent()并获得正确的结果?

6 个答案:

答案 0 :(得分:5)

代替return((lst == null)? 0 : (1 + countStudent(lst.getNext())))

答案 1 :(得分:1)

变化:

if(lst!=null){
countStu++;
countStudent(lst.getNext());      
}

    return countStu;

return lst==null ? 0 : (1+countStudent(lst.getNext()));

答案 2 :(得分:0)

假设这是你的功课,你真的必须在外面声明countStu(你不应该在任何正常的代码中),你可以简单地将值包装在某个类中。添加set + get访问器并将该对象作为第二个参数传递给该函数。然后使用它,而不是全局/静态变量。

或者根本不使用变量并返回结果+ 1.不确定规则是否允许这样做。

答案 3 :(得分:0)

通常,当您尝试执行类似的操作时,尝试以某种方式删除显式状态处理。

例如,如果你必须计算函数f(x)= G(f(x-1)),你可以将G表示为无状态方法,并遵循以下模式:

public static ResultType G(ResultType input) {
  // compute G stateless
}

public static ResultType F(int x) {
   return G(F(x - 1));
}

这样你就不会有像现有代码那样的副作用。与您现在正在进行的操作相比,缺点通常较小(整体使用相同的堆栈深度)。

重要的是确保G和F实现是无状态的(不使用在方法体范围之外声明的变量)。

答案 4 :(得分:0)

在静态字段中保持递归状态不是线程安全的。而是将值保存在堆栈中。

我给你一个递归的例子,这个例子可能会导致StackOverflowError冒险,只有6k节点的默认堆以及不受此影响的循环版本。

public class SO3765757 {
  public static int countNodeRecursive(Node<?> node) {
    if(node == null) {
       debug("node is null");
       return 0;
    }
    int count = 1 + countNodeRecursive(node.getNext());
    debug(count + " = " + node.toString());
    return count;
  }

  public static int countNodeLoop(Node<?> node) {
    int count = 0;
    for(Node<?> currentNode = node; currentNode != null; currentNode = currentNode.getNext()) {
      count += 1;
      debug(count + " = " + currentNode.toString());
    }
    return count;
  }

  public static void main(String[] args) {
    int count = 10;
    if(args.length > 0) {
      try {
        count = Integer.parseInt(args[0]);
      } catch(NumberFormatException e) {
      }
    }
    Node<Student> node = getNodeTest(count);
    System.out.println("Loop count      = " + countNodeLoop(node));
    try {
      System.out.println("Recursive count = " + countNodeRecursive(node));
    } catch(StackOverflowError e) {
      System.out.println("Recursive count caused " + e.getClass().getName());
    }
  }

  private static void debug(String msg) {
    System.out.println("DEBUG:" + msg);
  }

  private static <T> Node<T> getNodeTest(int count) {
     Node<T> prevNode = null;
     for(int i=0;i<count;i++) {
       Node<T> node;
       if(prevNode == null) {
          node = new NodeImpl<T>();
       } else {
          node = new NodeImpl<T>(prevNode);
       }
       prevNode = node;
     }
     return prevNode;
  }

  private static interface Node<T> {
    Node<T> getNext();
  }

  private static class NodeImpl<T> implements Node<T> {
    private final Node<T> next;

    public NodeImpl() {
       this.next = null;
    }

    public NodeImpl(Node<T> next) {
       this.next = next;
    }

    public Node<T> getNext() {
       return next;
    }
  }

  private static interface Student {
  }
}

答案 5 :(得分:0)

countStudent(lst.getNext());

如果lst.getNext()为null,为什么我需要再次调用它。在调用递归之前进行预计算,有不同的类型。当你从main方法调用这个方法countStudent时,在递归开始之前检查lst值是否为null。

  

public static int   countStudent(Node lst){

    countStu++;  
    Node<Student> _tmp;
    _tmp = lst.getNext();
    if (_tmp != null )
        countStudent(lst.getNext());          
     return countStu;        }