Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在Prolog中理解这个冒泡排序解决方案_Algorithm_Sorting_Recursion_Prolog_Bubble Sort - Fatal编程技术网

Algorithm 在Prolog中理解这个冒泡排序解决方案

Algorithm 在Prolog中理解这个冒泡排序解决方案,algorithm,sorting,recursion,prolog,bubble-sort,Algorithm,Sorting,Recursion,Prolog,Bubble Sort,这个冒泡排序解决方案在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)) ). bubblesort([],[])。 气泡运动([H],[H])。 气泡运动([H

这个冒泡排序解决方案在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))
    ).
bubblesort([],[])。
气泡运动([H],[H])。
气泡运动([H | D],R):-
泡泡运动(D,E),
[B | G]=E,
((H=B,气泡运动([B,H | G],R))
).
以下是一个跟踪示例:


我知道bubblesort(D,E)这行负责将其排序为一个元素,但我不明白它是如何工作的。我了解prolog中列表的基本知识,但仍然无法理解此解决方案是如何运行的。

此代码的主要困难在于选择了错误的变量名,这使得逻辑难以遵循

前两个案例显然是基本案例。第一个说“空列表已排序”,第二个说“单例列表已排序”。这应该是有意义的。第三种情况是事情变得有趣

让我们检查第一部分

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])
    ;  (H > HeadOfTSorted,  bubblesort([HeadOfTSorted,H|RestOfTSorted], R))
    ).
希望这有帮助

注意:递归问题解决的关键是不要考虑代码操作的细节。假设你已经有了解决方案,然后用它来解决一个较小的子问题,从而得到完整问题的解决方案


您的代码中包含了更具启发性的变量名,因此我可以理解如下内容:

bubblesort([],[])。%空列表已排序
气泡运动([H],[H])。%单例列表已排序
气泡排序([H | T],S):-%`[H | T]`排序为'S',*如果*
bubblesort(T[M|R]),%T`排序为`[M|R]`,*和*
(**)或*,
H=M%,如果“H”大于“M”,
bubblesort([M,H | R],S)%`S`是按相同算法排序的`[M,H | R]`
).
H
表示“头部”;
T
表示“尾部”;
S
表示“已排序”;
R
表示“剩余”;
M
表示“最小值”——见下文)

我们用实例证明了它的正确性。归纳假设(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%,如果“H”大于“M”,
泡泡排序([H | R],S1),%%S1`是按相同算法排序的`[H | R]`
S=[M | S1]
).
其中感应步骤的适用性更为明确

但我不太确定这是不是一个好主意


更新:事实上,它的推断数增加为~n3(或更慢),但真正的气泡排序记录为~n2.1(接近理论~n2),其中n是列表的长度:

tbs([],[])。%真“气泡排序”
tbs([H],[H])。
tbs(L,S):-气泡(L,B),
(L==B->S=L;tbs(B,S))。
气泡([],[])。
气泡([A],[A])。
气泡([A,B | C],R):-
(A=气泡([B | C],X),R=[A | X]
气泡([A | C],X),R=[B | X])。

我重命名了它们,只是为了能够按照代码进行操作。即使只有一个字母的名字也可能是暗示性的:H,T(对于通常的[H | T]),S(“排序”)而不是R,去掉E,用[M | R]替换[B | G](“最小值”;“剩余值”)。那么它是可读的。也许它们在其他语言中是有意义的(比如在英语中,而不是在英语中——此外,简短的var名称应该总是在它们的介绍中用完整的预期名称@OP进行注释)。不过,我不太确定它是否属于泡沫类型。:)@我同意,我认为这是插入式的。我怀疑比那更糟。插入按特殊、高效的步骤对插入进行排序。这个算法做了很多工作,看起来像。@WillNess可能,但是所有的N^2排序都做了很多工作。当然,在文献中,他们谈论的是随机存取和O(1)交换的数组,这不是我们使用链表的生活它是