如何在递归期间将所有先前帧(较高帧)中的值传递到较低帧

时间:2016-07-10 20:36:25

标签: java arrays recursion pass-by-reference pass-by-value

为了简化问题,让我们考虑打印数组的所有排列,而不重复。因此,如果{1,2,3}是数组,则输出将是以下

1 2 3 
1 3 2 
2 1 3 
2 3 1 
3 1 2 
3 2 1 
count == 6

如何将已经属于数组的所有元素的计数传递给较低的帧。我的意思是,在递归的前两帧中,我的堆栈中有元素1和2。我需要告诉下面的框架,它可以使用除1和2之外的所有元素,因为它已经被使用了。

请参阅下面的代码,我将所有遇到元素的数组作为下面框架函数调用的一部分传递给我。但是我还必须在同一帧中为其他递归调用保存和恢复数组的元素,因为Java不会在每个帧中保存数组的副本,并且传递引用会导致数组被覆盖。

import java.util.Arrays;

public class SendfromHigherFrameToLowerFrame {
    static int count = 0;

    public static void main(String[] args) {
        int[] a = {1,2,3};

        int[] stack = new int[3];
        fun(a, stack, 0);

        System.out.println("count == "+count);
    }

    static void fun(int[] a, int[] stack, int frame)
    {
        if(a.length == frame)
        {
            count++;
            print(stack);
            return;
        }

        for(int i = 0;i<a.length;i++)
        {
            //save stack
            int[] temp = new int[stack.length];
            save(stack, temp);
            if(isValid(stack, a[i]) == true)
            {
                stack[frame] = a[i];
                fun(a, stack, frame+1);
                //restore stack
                restore(temp, stack);
            }
        }
    }

    static void save(int[] source, int[] destination)
    {
        for(int i = 0;i<source.length;i++)
            destination[i] = source[i];
    }

    static void restore(int[] source, int[] destination)
    {
        for(int i = 0;i<source.length;i++)
            destination[i] = source[i];
    }

    static boolean isValid(int[] a, int key)
    {
        for(int i = 0;i<a.length;i++)
        {
            if(a[i] == key)
                return false;
        }
        return true;
    }

    static void print(int[] a)
    {
        for(int x : a)
            System.out.print(x + " ");
        System.out.println();
    }
}

请建议改进​​代码,或者更简单地传递元素。

PS:请注意,生成排列不是我原来的问题,我知道有更简单的方法可以做到这一点,它只是为了传达我的问题。

2 个答案:

答案 0 :(得分:1)

由于无法通过Java中的引用继续传递原语,因此您不能简单地创建int,并将其传递给调用堆栈。这个问题有三种解决方法:

  • 使用可变类,例如单个intAtomicInteger的数组。然而,这种方法与数组和可变类的滥用有关。
  • 按照您的方式创建实例变量或静态变量。这远非理想,因为你的递归函数变得不可重入,因此测试起来要困难得多。
  • 从方法返回修改后的值,并将其添加/赋值给递归方法内的局部变量,以作为自己的返回值传递。这种方法很好,但它只能容纳一个返回值,并且在编写代码时要求您非常小心。

以下是如何修改函数以实现上述最后一种方法:

static int fun(int[] a, int[] stack, int frame) {
    if(a.length == frame) {
        print(stack);
        return 1;
    }
    int res = 0;
    for(int i = 0;i<a.length;i++) {
        //save stack
        int[] temp = new int[stack.length];
        save(stack, temp);
        if(isValid(stack, a[i]) == true) {
            stack[frame] = a[i];
            res += fun(a, stack, frame+1);
            //restore stack
            restore(temp, stack);
        }
    }
    return res;
}

Demo.

注意:不言而喻,您的练习无需执行任何操作,因为count始终等于stack.length

答案 1 :(得分:-1)

我不想回答帧中的传递值,但我有一种简单的排列方式。

void Calc(String a, String b){


    if (a.equals("")) {
        System.out.println(a);
        return;
    } else {
        for (int i = 0; i < a.length(); i++) {
            Calc(removeFirst(a, i), b + a.charAt(i));
        }

    }

    public static void main(String[] args){
        Calc("123", "");
    }

古德勒克

米拉德