简体   繁体   English

prolog 中的合并排序 - 无限递归?

[英]mergesort in prolog - infinite recursion?

I am attempting to implement mergesort in prolog (swi prolog on raspberry pi).我正在尝试在 prolog 中实现合并排序(树莓派上的 swi prolog)。 I'm very new to the language and what I have here is basically my Haskell version "ported" to Prolog as best I could:我对这种语言非常陌生,我在这里所拥有的基本上是我的 Haskell 版本“移植”到 Prolog 尽我所能:

:- use_module(library(list_util), [split_at/4, take/3, drop/3]).

merge([], [], []).
merge(Lst, [], Lst).
merge([], Lst, Lst).
merge([X|XS], [Y|YS], MergedLst) :- X < Y, MergedLst = [X|MergedLst2], merge(XS, [Y|YS], MergedLst2).
merge([X|XS], [Y|YS], MergedLst) :- X >= Y, MergedLst = [Y|MergedLst2], merge([X|XS], YS, MergedLst2).


mergesort([], []).
mergesort([Only], [Only]).
mergesort(Lst, SortedLst) :-
  length(Lst, LstLen),
  HalfWay is truncate(LstLen / 2),
  take(HalfWay, Lst, FirstHalf),
  drop(HalfWay, Lst, SecondHalf),
  mergesort(FirstHalf, A),
  mergesort(SecondHalf, B),
  merge(A, B, SortedLst).

Running this code appears to perform the sort correctly, but then goes spiraling into infinite and beyond:运行此代码似乎可以正确执行排序,但随后会螺旋式上升到无限甚至更远:

?- mergesort([1,6,3,10,4,9,2,4,7,3], Y).
Y = [1, 2, 3, 3, 4, 4, 6, 7, 9|...] ;
Y = [1, 2, 3, 3, 4, 4, 6, 7, 9|...] ;
Y = [1, 2, 3, 3, 4, 4, 6, 7, 9|...]

I creeped through the debugger (trace mode) and didn't find any clues我爬过调试器(跟踪模式)并没有找到任何线索

   Call: (18) merge([10], [], _5322) ? creep
   Exit: (18) merge([10], [], [10]) ? creep
   Exit: (17) merge([10], [9], [9, 10]) ? creep
   Exit: (16) merge([10], [7, 9], [7, 9, 10]) ? creep
   Exit: (15) merge([6, 10], [7, 9], [6, 7, 9, 10]) ? creep
   Exit: (14) merge([4, 6, 10], [7, 9], [4, 6, 7, 9, 10]) ? creep
   Exit: (13) merge([4, 6, 10], [4, 7, 9], [4, 4, 6, 7, 9, 10]) ? creep
   Exit: (12) merge([3, 4, 6, 10], [4, 7, 9], [3, 4, 4, 6, 7, 9, 10]) ? creep
   Exit: (11) merge([3, 4, 6, 10], [3, 4, 7, 9], [3, 3, 4, 4, 6, 7, 9, 10]) ? creep
   Exit: (10) merge([3, 4, 6, 10], [2, 3, 4, 7, 9], [2, 3, 3, 4, 4, 6, 7, 9|...]) ? creep
   Exit: (9) merge([1, 3, 4, 6, 10], [2, 3, 4, 7, 9], [1, 2, 3, 3, 4, 4, 6, 7|...]) ? creep
   Exit: (8) mergesort([1, 6, 3, 10, 4, 9, 2, 4|...], [1, 2, 3, 3, 4, 4, 6, 7|...]) ? creep
Y = [1, 2, 3, 3, 4, 4, 6, 7, 9|...] ;

I tried it again with an empty list and this time the debugger reveals that "merge" is being called, which shouldn't be happening for that case.我用一个空列表再次尝试,这次调试器显示正在调用“合并”,这种情况不应该发生。

?- mergesort([], Y).
Y = [] ;
Y = [] ;
Y = []
Action (h for help) ? trace
continue (trace mode)
; [trace]
   Redo: (9) merge([], [], _3038) ? creep
   Exit: (9) merge([], [], []) ? creep
   Exit: (8) mergesort([], []) ? creep
Y = []

If anyone more experienced in the language knows where the infinite loop is coming from, please let me know, thank you.如果有语言经验丰富的人知道无限循环来自哪里,请告诉我,谢谢。

Your third clause of mergesort will match previous two clauses.合并排序的第三个子句将匹配前两个子句。 You can cut the first two clauses or pattern match the third to ensure atleast two elements.您可以剪切前两个子句或模式匹配第三个子句以确保至少两个元素。

mergesort(Lst, SortedLst) :-
    Lst = [_, _ | _],
    ...

Or或者

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM