Prolog递归不会按预期停止

时间:2017-11-11 02:41:58

标签: recursion prolog

大家好,这是我的第一篇文章,所以如果你对如何提出问题有任何建议,我会全力以赴。所以我的问题是我尝试使用递归对数字列表进行排序,我有一个<div class="wrapper"> <span class="block1">23</span> <span class="block2">Quote</span> </div>谓词返回列表的最大值,所以在返回后我从列表中选择该值然后再添加它到我的排序列表。然后我用新列表递归。

我的问题是谓词似乎工作并找到了正确的列表,但是当谓词退出时,它将所有列表恢复到原始状态,基本上撤消了谓词所做的所有工作。我认为这与Prolog如何回溯有关?

my_max/2

我添加了写只是为了表明它对列表进行了排序。输出应为%finds the max of a list, if the list is empty return int_min my_max([],-2147483647). my_max(L,M):-select(M,L,Rest), \+ (member(E,Rest),E>M). %calls the my_max predicate store it in X, combines x and sorted and appends %it to sorted2,then it takes X out of unsorted and creates Unsorted2 then %recurse with unsorted2 and sorted2 should stop and output when unsorted is %empty or [] my_sort([],S). %my_sort([],S):-write(S). for test my_sort(Unsorted,Sorted):- my_max(Unsorted,X), append(Sorted,[X],Sorted2), select(X,Unsorted,Unsorted2), my_sort(Unsorted2,Sorted2).

Output from the trace

1 个答案:

答案 0 :(得分:2)

首先,在加载文件时,我得到:

Warning: Singleton variables: [S]

由于基本情况:

my_sort([],S).

问题是基本情况表明空列表与单例变量S匹配,因此请尝试:

?- my_sort([],[1,2]).
true ;
false.

?- my_sort([],hello).
true ;
false.

在任何情况下my_sort/2都不应该成功。所以你的基本情况应该是空列表:

my_sort([],S). 

而不是在基本情况下构建完整的排序列表,而不是通过递归构建它,并在基本情况下留下一个空列表:

my_sort([],[]).
my_sort(Unsorted,Sorted):-
   my_max(Unsorted,X),
   select(X,Unsorted,Unsorted2),
   my_sort(Unsorted2,Sorted2),  %  <- continue to find the sorted sublist
   append(Sorted2,[X],Sorted).  %  <-place max at the end of sorted

在上面,Sorted2是Sorted的子列表,因此您可以递归地找到子问题的列表Sorted2,然后添加max。这是在每个步骤中递归完成的,在基本情况下,您将有空列表。

所以更好地理解它是一个例子 - 解释:
假设您要对[2,1,3]列表进行排序。

  • 查找max = 3查找为[2,1]排序(将在稍后的所有递归调用后添加3)
  • 查找按max = 2
  • 排序的[1]
  • 查找max = 1查找已排序为[] ,即[]
  • 添加max = 1 - &gt; Sorted = [1]
  • 添加max = 2 - &gt; Sorted = [2]
  • 最后添加max = 3 - &gt; Sorted = [1,2,3] 例如:

    ? - my_sort([4,1,3,2],L)。 L = [1,2,3,4]; 假

  

一些优化

在每个步骤中,您可以通过遍历未排序的列表找到O(n)步的最大值,其中n是未排序列表的长度。再次附加O(n)。再次选择O(n)。因此,在每个步骤中总共执行3次O(n)计算。

为了避免你可以按降序构建列表,所以你不需要在O(n)中使用append。

此外,您的最大谓词可以返回Rest列表,这样您就可以避免排序谓词中的select / 3来减少另外N个步骤:

my_sort([],[]).

my_sort(Unsorted,[X|Sorted]):-
   my_max(Unsorted,X,Unsorted2),
   my_sort(Unsorted2,Sorted).

示例:

?- my_sort([4,1,3,2],L).
L = [4, 3, 2, 1] ;
false.

现在要升序使用reverse / 2:

?- my_sort([4,1,3,2],L),reverse(L,L1).
L = [4, 3, 2, 1],
L1 = [1, 2, 3, 4] ;
false.

O(N)步骤反转列表,但每次递归调用只有一次!!