我正在尝试实现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);
答案 0 :(得分:0)
带来很多问题。所以我能做的就是消除这个问题。
我假设你的myQuickSort签名中,联合收割机的类型有R和T交换。如果我是对的,我会发现这个签名很奇怪,如下所述。
&#34; solve.apply()&#34;代码中的行对返回没有任何作用。由于您没有使用该功能的回复,我无法确定&#34;解决&#34;的目的是什么?是。也许你可以澄清一下。结果,你的最后一次&#34;返回输出&#34;没有任何回报。在下面的讨论中,我忽略了&#34;解决&#34;。
您实施&#34;合并&#34;在主要使用流不必要。 List.addAll()可以解决问题。
您未在实施中使用合并功能。
我的问题涉及教授给你的签名。在我看来,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作为参数)。
希望这有帮助。