'predsort / 3`的可能行为

时间:2015-01-21 21:00:43

标签: list sorting prolog compare stable-sort

这是对answer关于对术语的特定参数进行排序的问题的跟进,而没有为keysort创建新列表(如果我正确理解了原始问题)。< / p>

假设我们希望predsort/3的行为与sort/2完全相同:如果我理解正确,这就意味着将其称为:

?- predsort(compare, List, Sorted).

现在说我们要使用predsort/3msort/2的方式进行排序(另请参阅此question)。一种方法是定义一个比较谓词Pred(-Delta, +A, +B),当元素实际上相等时,它不会将Delta=统一起来:

mcompare(Delta, A, B) :-
    compare(Delta0, A, B),
    (   Delta0 == (=)
    ->  Delta = (<)
    ;   Delta = Delta0
    ).

?- predsort(mcompare, List, Sorted).

问题:这真的只是排序而不删除重复项,如msort/2那样吗?好像应该这样。

继续:说我们想用arity&gt;对术语进行排序n,关于术​​语中第n个参数的标准顺序。干净的方法是:

sort_argn(N, List, Sorted) :-
    map_list_to_pairs(arg(N), List, Pairs),
    keysort(Pairs, Sorted_pairs),
    pairs_values(Sorted_pairs, Sorted).

如果我们想使用predsort/3来达到同样的效果,我们可以尝试使用比较谓词,如下所示:

compare_argn(N, Delta, A, B) :-
    arg(N, A, AN),
    arg(N, B, BN),
    compare(Delta, AN-A, BN-B).

并对第二个论点进行排序:

?- predsort(compare_argn(2), List, Sorted).

但是,这与使用sort_argn/3的上述keysort/2 不一样。它将删除重复项,如果两个术语的第二个参数恰好相同,它将根据原始完整项的标准顺序排序复合词:

?- predsort(compare_argn(2), [f(b,2), f(a,1), f(a,1), f(a,2)], Sorted).
Sorted = [f(a, 1), f(a, 2), f(b, 2)].

?- sort_argn(2, [f(b,2), f(a,1), f(a,1), f(a,2)], Sorted).
Sorted = [f(a, 1), f(a, 1), f(b, 2), f(a, 2)].

进行假设对于传递给比较谓词A的每对BPred(Delta, A, B)A来到{{1}之前在原始列表中。我们可以定义一个比较:

B

此时,当且仅当任何两个元素compare_argn_stable(N, Delta, A, B) :- arg(N, A, AN), arg(N, B, BN), compare(Delta0, AN, BN), ( Delta0 == (=) -> Delta = (<) ; Delta = Delta0 ). A总是以与原始列表中相同的顺序传递给比较谓词,这应该与上面B的行为相同:

sort_argn/3

当然,当两个“密钥”相等时,?- predsort(compare_argn_stable(N), List, Sorted). compare_argn_stable/4统一Delta非常重要。此外,行为是依赖于实现的,并且仅与<示例相同iff keysort在将元素传递给比较谓词时保留元素的原始顺序。

问题这是正确的吗?

问题是否有任何标准涵盖predsort/3的这一方面?

1 个答案:

答案 0 :(得分:4)

由于没有人回答,因为我现在对此非常肯定:

是的,您可以使用predsort/3来模拟任何其他类别。这个问题详细描述了如何。

然而:出于几个原因,这是一个坏主意。

  • “稳定性”取决于predsort/3的实施(参见问题)
  • predsort/3本身不属于任何标准(据我所知)
  • 您的Prolog实施可能提供的msort/2keysort/2远远高于predsort/3

可能在极少数情况下,列表元素的大小远远大于我们正在排序的列表的长度,以及这个小小的舞蹈:

list_to_keyval_pairs(List, Pairs), % defined by the user as necessary
keysort(Pairs, Sorted_pairs),
pairs_values(Sorted_pairs, Sorted)

see here)实际上比使用predsort(keycmp, List, Sorted)更昂贵(更慢),用户定义了keycmp/3。即便如此,具有等效键的结果顺序不仅取决于keycmp/3的(用户)定义,还取决于predsort/3的实现。

换句话说,使用predsort/3进行“稳定”排序是一个坏主意。