如何实现功能" divide"在功能划分和解决Java算法?

时间:2018-01-14 18:01:39

标签: java algorithm lambda functional-programming quicksort

我正在尝试实现Quicksort算法的功能版本。 我的教授让我把它作为签名:

public static <T, R> List<T> myQuickSort(Function<List<T>, Boolean> trivial, 
        Function<List<T>, T> solve, Function<List<T>, R> divide, 
        Function<T, List<R>> combine, List<T> input)

我创建了一个名为Pair的辅助类,它是这样的:

public class Pair {

List<Integer> first; 
List<Integer> second; 

Pair(List<Integer> f, List<Integer> s) {
    first = f; 
    second = s; 
}
public static Pair div(List<Integer> input) {
    int pivot = (int) input.get(0); 
    List<Integer> a = new ArrayList<Integer>();
    List<Integer> b = new ArrayList<Integer>();
    for(int i=1; i<input.size(); i++) {
        if(input.get(i) < pivot) {
            a.add(input.get(i)); 
        } else {
            b.add(input.get(i)); 
        }
    }
    return new Pair(a, b); 
}

} 我差不多完成了,但我无法弄清楚如何在输入数组的单个分区上递归工作。我试着这样做:

if(trivial.apply(input)) {
        solve.apply(input); 
    } else {
        output = myQuickSort(trivial, solve, divide, combine, 
                (List<T>) divide.apply(input).first); 
        output.add(input.get(0)); 
        output.addAll(myQuickSort(trivial, solve, divide, combine, 
                (List<T>) divide.apply(input).second)); 
        return output; 
    }
    return output;

但我现在卡住了。 你们中的任何人都可以告诉我哪里错了和/或我如何更好地实施我的解决方案? 这也是主要的,如果它可以帮助:

Function<List<Integer>, Boolean> trivial = (a) -> a.size()==1; 
    Function<List<Integer>, Pair> divide = (a) -> Pair.div(input); 
    Function<Pair, List<Integer>> combine = 
            (a) -> Stream.concat(a.first.stream(), a.second.stream()).
            collect(Collectors.toList());
    Function<List<Integer>, Integer> solve = (a) -> a.get(0); 
    ArrayList<Integer> output = myQuickSort(trivial, solve, divide, combine, input);

1 个答案:

答案 0 :(得分:0)

带来很多问题。所以我能做的就是消除这个问题。

  1. 我假设你的myQuickSort签名中,联合收割机的类型有R和T交换。如果我是对的,我会发现这个签名很奇怪,如下所述。

  2. &#34; solve.apply()&#34;代码中的行对返回没有任何作用。由于您没有使用该功能的回复,我无法确定&#34;解决&#34;的目的是什么?是。也许你可以澄清一下。结果,你的最后一次&#34;返回输出&#34;没有任何回报。在下面的讨论中,我忽略了&#34;解决&#34;。

  3. 您实施&#34;合并&#34;在主要使用流不必要。 List.addAll()可以解决问题。

  4. 您未在实施中使用合并功能。

  5. 我的问题涉及教授给你的签名。在我看来,R是一个对象,代表一个分为两个的列表。 R将包括第一个和第二个列表,以及&#34; pivot&#34;正如你所说的那样。然后组合使用R并将这三个部分组合成单个列表。由于R,divide和combine的实现是由myQuickSort的调用者完成的,因此他们将处理被排序对象的比较(实现中的整数),这样myQuickSort就不必知道对象的类型了。排序

    如果我是对的,那么在我看来你的R的实现,你称之为Pair,应该存储枢轴。然后,您对combine的实现将组合first,pivot和second。分开或组合将调用myQuickSort:不重要。你做分了,这很好。

    然后

    myQuickSort将成为:

    if (trivial(input))
        return input;    // Remember I am ignoring solve()
    else {
        R r = divide.apply(input);
        return combine.apply(r);
    }
    

    然后执行divide或combine - 在你的情况下除 - 通过为分割列表的两半中的每一半调用myQuickSort来提供递归。

    如果我在上面的话,这是一个奇怪的签名。提供的功能必须具备QuickSort实现的知识。如果将R定义为具有myQuickSort可以操作分割数组的方法,则不会出现这种情况。这意味着,不是简单地在静态方法签名中使用R,而是使用&#34; R扩展DivObject&#34; DivObject是一个定义myQuickSort可以调用的方法的接口(或类)。我会让DivObject有一个getFirst()方法和一个getSecond()方法,它返回相应的列表,以便myQuickSort可以在这两个列表上调用自己。它还需要像setFirst()和setSecond()这样的方法将排序后的列表放回到R中,以便组合可以组合它们(因为combine只将R作为参数)。

    希望这有帮助。