【问题标题】:understand the running trace of quicksort in prolog了解prolog中quicksort的运行轨迹
【发布时间】:2014-10-30 08:50:05
【问题描述】:

我有以下快速排序的序言代码:

gt(X,Y):- X @> Y.
conc([], List, List).
conc([Head|Tail], List1, [Head|List2]):- conc(Tail, List1, List2).

quicksort([], []).
quicksort([X|Tail], Sorted):-
    split(X,Tail,Small,Big),
    quicksort(Small,SortedSmall),
    quicksort(Big, SortedBig),
    conc(SortedSmall, [X|SortedBig], Sorted).

split(X,[],[],[]).
split(X,[Y|Tail],[Y|Small],Big):-
    gt(X,Y),
    !,
    split(X,Tail,Small, Big).

split(X,[Y|Tail],Small,[Y|Big]):-
    split(X,Tail,Small,Big).

例如数组是[3,2,4,1,5]。快速排序([3,2,4,1,5],排序)。我需要了解程序的运行轨迹。我几乎做到了,但有一点我没有:(这只是跟踪的一部分):

Redo: (11) split(3, [5], _G3785, _G3782) ? creep
Call: (12) split(3, [], _G3785, _G3788) ? creep
Exit: (12) split(3, [], [], []) ? creep
Exit: (11) split(3, [5], [], [5]) ? creep
Exit: (10) split(3, [1, 5], [1], [5]) ? creep
Exit: (9) split(3, [4, 1, 5], [1], [4, 5]) ? creep
Exit: (8) split(3, [2, 4, 1, 5], [2, 1], [4, 5]) ? creep

为什么我们有 Exit: (11) split(3, [5], [], [5]) ?爬到第 11 行,5 从哪里来? 有人可以帮助我吗!!我真的很感激。

【问题讨论】:

  • 明确地说,(11) 不是对行号的引用,而是目标的级别或深度。调用子目标时,级别会增加 1。在子目标成功并将控制权返回给调用者后,级别会降低。

标签: sorting prolog quicksort trace


【解决方案1】:

我们将以此作为参考:

[1] split(X,[],[],[]).
[2] split(X,[Y|Tail],[Y|Small],Big):-
        gt(X,Y),
        split(X,Tail,Small, Big).

[3] split(X,[Y|Tail],Small,[Y|Big]):-
        split(X,Tail,Small,Big).

我们将跟踪您的跟踪片段。

Redo: (11) split(3, [5], _G3785, _G3782) ? creep

此重做是由于原始查询中的子句 [2] 失败(未显示,在跟踪之前),因为 gt(3,5) 为假。然后重做将导致对子句 [3] 的查询。我们将替换已知的实例化变量,看看第三个子句查询是什么样的:

[A] split(3, [5|[]], Small, [5|Big]) :- split(3, [], Small, Big)

这导致下一个跟踪行,其中_G3785Small_G3788Big

Call: (12) split(3, [], _G3785, _G3788) ? creep

这将在第一个子句 [1] 上成功并产生这部分跟踪:

Exit: (12) split(3, [], [], []) ? creep

由于这是在执行上面的子句 [3] 中(如 [A] 所示),因此它产生以下内容,因为现在 Small 已用 []Big[] 实例化。

split(3, [5|[]], [], [5|[]])

换句话说,执行 [A] 中显示的第三个子句会导致:

split(3, [5], [], [5])

下一条跟踪线显示的是什么:

Exit: (11) split(3, [5], [], [5]) ? creep

【讨论】:

  • 其实在split函数的rule 1后面有一个cut (!)。正如您所说:如果 gt(3,5) 为假,prolog 将回溯并应用拆分函数的规则 3。是对的吗?如果 gt 返回 true 会怎样?你能给我解释一下吗?
  • @ThơHoàng 看来您在我回答后添加了剪辑,但这并不影响我在给定示例中的解释。如果gt 成功而不是失败,那么第二个子句不会回溯,并且跟踪会相应改变。如果您有一个 gt 成功的新跟踪示例,并且您需要一些帮助来理解该新跟踪,请随时将其作为新问题发布。
  • 剪辑总是在那里,我的错误忘了把它放在那里。我展示的痕迹是有切口的痕迹。但是好的,我会尝试提出一个新问题,因为我仍然对跟踪感到困惑。并希望您可以再次查看并提供一些帮助。非常感谢!
  • @ThơHoàng,好的。正如我所说,我上面的解释是独立的,因为gt 在你提到的场景中失败了。我的答案中是否有部分尚不清楚,我可以在这种特定情况下更好地解释?
  • 不,您的回答有很大帮助。我从一开始就误解了trace(我自己画的),然后看prolog的trace,很难弄清楚。如果你有时间,你可以帮助我:link。非常感谢你的帮助@lurker
【解决方案2】:

在函数拆分的规则2处比较后应该有一个cut:

split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y), 
!,
split(X,Tail,Small, Big).

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2010-10-29
    相关资源
    最近更新 更多