Prolog - 将两个列表放在一起并对其进行排序

时间:2014-06-25 22:15:55

标签: list prolog

如果列表NL包含来自L1L2的所有成员并且已排序,我想在Prolog中写入一个属实的属性。

putTogether(L1,L2,NL).

如果我拨打putTogether(L1,L2,X),它应该给我L1 + L2并且已经排序。

基本案例是

putTogether([],[],[]).

IMHO。

好吧,我忘了说我不想使用内置谓词。因此,例如sort无效。

但我不知道其余部分。

感谢提前提供的有用提示。

2 个答案:

答案 0 :(得分:1)

可能只是:

putTogether(L1, L2, NL) :-
    append(L1, L2, L12),
    sort(L12, NL).

这将删除所有重复项,但这与"列表NL具有来自L1和L2 AND的所有成员排序"。

更新。如果您不想使用内置谓词" (可能不被教师允许)只需查看Prolog书籍,在线或Prolog系统来源如何实现您的appendsort版本。

答案 1 :(得分:1)

这个问题的核心是对无序列表进行排序。在Prolog中实现的最简单的排序是 merge sort ,因为它非常适合链表。一般算法是

  • 如果列表为空,它已经排序,只需将其归还。
  • 如果列表的长度为1,它已经排序,只需将其返回。
  • 如果长度列表> 1,将列表分为两个子列表。
  • 递归,合并排序左半部分
  • 递归,合并排序右半部分
  • 合并现在排列的两个列表。

在Prolog中,您可以实现以下内容:

merge_sort( []     , [] ) .     % the empty list is already sorted
merge_sort( [X|Xs] , Zs ) :-    % for a non-empty list, we ...
  partition( [X|Xs] , L , R ) , % - partition it into two lists of more-or-less equal length
  merge_sort( L , L1 ) ,        % - sort the left half
  merge_sort( R , R1 ) ,        % - sort the right half
  merge( L1 , R1 , Zs )         % - merge the two now-ordered lists into 1
  .                             % Easy!

分区过程并不困难:

  • 而2个或更多项目仍保留在源列表中
    • 为左右子列表分配1次
  • 如果列表非空,则此时只剩下一个项目:
    • 将其分配给左侧或右侧子列表(无所谓)。
  • 返回左右子列表

您可能会注意到,这里真正发生的事情是将列表划分为平均值和赔率,而不是两半,尽管净效果是相同的:两个长度大致相等的列表,长度不同超过1。

这可以在Prolog中实现:

partition( []      , []     , []     ) .   % the empty list gets partitioned into 2 empty lists
partition( [L]     , [L]    , []     ) .   % a list of length 1 gets partitioned into itself and and empty list
partition( [L,R|T] , [L|Ls] , [R|Rs] ) :-  % for a list of 2+ items, we add 1 each to the left and right halves, 
  partition(T,Ls,Rs)                       % ...and recursively partition the remainder
  .                                        % Easy!

合并两个有序列表也非常简单:

  • 虽然两个列表都是非空的
    • 从每个
    • 中取出项目A和B.
    • 比较它们。
    • 如果A< B,然后将它们以A,B顺序添加到结果列表中。
    • 如果A> B,然后将它们添加到B,A订单中的结果列表中。
    • 如果A = B,那么它们的添加顺序并不重要
  • 如果任一列表非空,请将其添加到结果列表中。

这可以在prolog中实现,因此:

merge( []     , []     , []       ) .   % the merger of two empty lists yields the empty list.
merge( [L|Ls] , []     , [L|Ls]   ) .   % the merger of a non-empty, ordered list with the empty list yields the ordered list
merge( []     , [R|Rs] , [R|Rs]   ) .   % the merger of the empty list with a non-empty, ordered list yields the ordered list
merge( [L|Ls] , [R|Rs] , [X,Y|Zs] ) :-  % the merger of two, non-empty, ordered lists is accomplished by:
  compare(CC,L,R) ,                     % - comparing the heads,
  collate(CC,L,R,X,Y) ,                 % - putting them in the proper order
  merge( Ls , Rs , Zs )                 % - and recursively merging the remainder
  .                                     %

collate(<,X,Y,X,Y) .
collate(>,X,Y,Y,X) .
collate(=,X,Y,X,Y) .

一旦拥有了,您的问题的解决方案就很容易了。你有两个无序列表:你要做的就是对每个列表进行排序并合并它们:

merge_and_sort( Xs , Ys , Zs ) :- % to merge and sort two unordered lists
  merge_sort(Xs,X1) ,             % - sort the first list
  merge_sort(Ys,Y1) ,             % - sort the second list
  merge(X1,Y1,Zs)                 % - merge the two now-ordered lists
  .                               % Easy!