【问题标题】:Create a list from user input and it should be merge sorted in Prolog从用户输入创建一个列表,它应该在 Prolog 中合并排序
【发布时间】:2021-01-19 03:09:52
【问题描述】:

所以我的程序应该询问用户要输入多少个数字,然后用户将输入要排序的数字,排序算法应该是合并排序

main:-   
   writeln('Number of items? '),
   read(N),
   length(L, N),
   maplist(read, L),    
   mergesort(L, S). 

mergesort([L,B|R],S):-
    split([L, B|R], A1, A2),
    mergesort(A1, S1),
    mergesort(A2, S2),
    format('Sorted list: ~w~n', merge(S1, S2, S)).
    
split([],[],[]).
split([L], [L],[]).
split([L, B|R], [L|Ra], [B|Rb]) :-
    split(R, Ra, Rb).
    
merge(L, [], L).
merge([], B, B).
merge([L|Ra], [B|Rb], [L|M]) :-
    L=< B, 
    merge(Ra, [B|Rb], M).
merge([L|Ra], [L|Rb], [B|M]) :-
    L > B, 
    merge([A|Ra], Rb, M). 

这不起作用,在用户输入要排序的数字后,它总是显示 false

【问题讨论】:

  • 谓词调用不能嵌套,因此format('Sorted list: ~w~n', merge(S1, S2, S)) 不会产生你想要的结果。
  • 我不明白 :(
  • 调用format('Sorted list: ~w~n', merge(S1, S2, S))应该写成连词merge(S1,S2,S), format('Sorted list: ~w~n',S)

标签: sorting split prolog mergesort


【解决方案1】:

我在您的代码中发现了两个问题。第一个是最后一条规则中的错字:您混淆了AB 和/或L。应该是这样的

merge([A|Ra], [L|Rb], [L|M]) :-
    L < A, 
    merge([A|Ra], Rb, M).

第二个错误是您从未说明何时结束递归拆分。我建议把

mergesort([A],[A]):-!.

在您的主要 mergesort 规则之前。爆炸(!)被称为剪切,在这种情况下可以防止进一步的回溯。这会缩短代码,因为如果您的列表包含多个元素,您不必检查“main”mergesort 规则。


完整代码;在SWISH工作

mergesort([A],[A]):-!.
mergesort([L,B|R],S):-
    split([L, B|R], A1, A2),
    mergesort(A1, S1),
    mergesort(A2, S2),
    merge(S1, S2, S).
    
split([],[],[]).
split([L], [L],[]).
split([L, B|R], [L|Ra], [B|Rb]) :-
    split(R, Ra, Rb).
    
merge(L, [], L).
merge([], B, B).
merge([L|Ra], [B|Rb], [L|M]) :-
    L=< B, 
    merge(Ra, [B|Rb], M).
merge([A|Ra], [L|Rb], [L|M]) :-
    L < A, 
    merge([A|Ra], Rb, M).

测试用例

?- mergesort([5,2,4,7,1,0],L).
L = [0, 1, 2, 4, 5, 7] ;
false.

工作。

【讨论】:

  • @seungcheol 添加了完整的代码 + 测试用例。在 swish 中测试(编辑中的链接)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
相关资源
最近更新 更多