此气泡排序解决方案在Prolog中如何工作?
bubblesort([], []).
bubblesort([H], [H]).
bubblesort([H|D], R) :-
bubblesort(D, E),
[B|G] = E,
( (H =< B, R = [H|E])
; (H > B, bubblesort([B,H|G], R))
).
以下是示例跟踪:https://pastebin.com/T0DLsmAV
我了解该行bubbleort(D,E)负责将其归类为一个元素,但是我不知道这是如何工作的。我了解序言中列表的基本知识,但仍然无法弄清楚该解决方案的工作方式。
答案 0 :(得分:1)
此代码的主要困难是选择了错误的变量名,这使得逻辑难以理解。
前两个案例显然是基本案例。第一个说“空列表已经排序”,第二个说“单例列表已经排序”。这应该是有道理的。第三种情况是让事情变得有趣。
让我们检查一下第一部分。
bubblesort([H|D], R) :-
bubblesort(D, E),
到目前为止,所有发生的事情都是我们将结果命名为R
,并将输入分为第一个元素H
和一个尾部D
。从那里开始,我们已经说过了,让我们对输入的尾部进行冒泡排序,并将其命名为E
。也许这样做会更容易些?
bubblesort([H|T], Result) :-
bubblesort(T, TSorted),
接下来,
[B|G] = E,
同样,名字不好,但是作者打算在这里做的很简单:分解排序尾巴的结果,这样我们就可以讨论排序后的尾巴中的下一项是否适合该位置,或者如果需要在我们输入的开头切换位置。我们重命名:
[HeadOfTSorted|RestOfTSorted] = TSorted,
现在我们有一个条件。从添加到排序列表的角度考虑。假设您有一些元素,例如3,我递给您一个排序列表。您想确定您的3排在前面还是其他地方。好吧,假设我给了您一个看起来像[5,7,19,23,...]的排序列表。您会知道自己的3正好在需要的位置,然后交出[3,5,7,19,23,...]。这正是该情况的第一种情况:
( (H =< HeadOfTSorted, Result = [H|TSorted])
现在考虑另一种情况,在这里我将以[1,2,...]开头的列表交给您。您知道您不能只是将这三个词放在开头并给我[3,1,2,...]。但是您真的不知道3的去向。它只是一开始就没有。因此,您需要做的是对列表的其余部分进行 resort ,在列表的1:[1 | resorted([3,2,...])]
之后,以3开头。实际上,这是条件的另一个分支:
; (H > HeadOfTSorted, bubblesort([HeadOfTSorted,H|RestOfTSorted], R))
).
希望这会有所帮助!
答案 1 :(得分:1)
注意:递归解决问题的关键恰恰是 not 来思考我们代码操作的细节。想象您已经有解决方案,然后使用它来解决较小的子问题,从而找到完整的问题解决方案。
您的代码带有更多提示性的变量名,以便我可以关注它,内容如下:
bubblesort([], []). % empty list is already sorted
bubblesort([H], [H]). % singleton list is already sorted
bubblesort([H|T], S) :- % `[H|T]` sorted is `S`, *if*
bubblesort(T, [M|R]), % `T` sorted is `[M|R]`, *and*
( % *either*,
H =< M, % in case `H` is not greater than `M`,
S = [H,M|R] % `S` is `[H,M|R]`,
; % *or*
H > M, % in case `H` is greater than `M`,
bubblesort([M,H|R], S) % `S` is `[M,H|R]` sorted by the same algorithm
).
({H
代表“头”,T
代表“尾”,S
代表“已排序”,R
代表“休息”和M
是“最小值”-参见下文)。
我们通过structural induction证明了其正确性。归纳假设( IH )是此定义对于较短的列表是正确的。我们需要证明它对于更长的列表也是正确的。实际上,T
比[H|T]
短一个元素。因此, IH 说[M|R]
已排序。这意味着M
是T
中的最小元素。这也意味着T
是非空的(排序不会更改元素的数量),因此子句的确是互斥的。
如果H
不大于T
中的最小元素,则显然[H,M|R]
被排序。
否则,我们对[M,H|R]
进行排序。 M
是最小元素,因此保证是结果中的第一元素。实际排序的是[H|R]
,它短了一个元素,因此通过 IH 排序就可以了。 QED 。
如果您觉得最后一步很可疑,请考虑用等效的替代第二种选择
; H > M, % in case `H` is greater then `M`,
bubblesort([H|R], S1), % `S1` is `[H|R]` sorted by the same algorithm
S = [M|S1]
).
归纳步骤的适用性更加明确。
我不确定这是bubble sort。
更新:的确,measuring empirical orders of growth的推理次数随着〜n 3 (或更慢的速度),但真正的气泡排序的时钟频率为〜n 2.1 (足够接近理论上的〜n 2 ),其中 n 是列表的长度:
tbs([], []). % 'true' bubble sort
tbs([H],[H]).
tbs(L,S):- bubble(L,B),
( L==B -> S=L ; tbs(B,S) ).
bubble([],[]).
bubble([A],[A]).
bubble([A,B|C],R):-
( A =< B -> bubble([B|C],X), R=[A|X]
; bubble([A|C],X), R=[B|X] ).