簡體   English   中英

了解 Prolog 中的冒泡排序解決方案

[英]Understanding this bubble sort solution in Prolog

這個冒泡排序解決方案在 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

我理解冒泡排序(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])

現在考慮另一種情況,我給你一個以 [1,2,...] 開頭的列表。 你知道你不能把三個放在開頭然后把我還給 [3,1,2,...]。 但是你真的不知道 3 去哪里了; 它只是一開始就沒有。 所以,你必須做的是采取與3在啟動列表中的其余部分,之后的1: [1 | resorted([3,2,...])] [1 | resorted([3,2,...])] 這實際上是條件的另一個分支:

    ;  (H > HeadOfTSorted,  bubblesort([HeadOfTSorted,H|RestOfTSorted], R))
    ).

希望這可以幫助!

注意:遞歸問題解決的關鍵正是不要考慮我們代碼操作的細節。 想象一下,您已經有了解決方案,然后只需使用它來解決較小的子問題,從而得出完整問題的解決方案。


您的代碼帶有更多提示性的變量名稱,以便我可以遵循它,內容如下:

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 “最小”——見下文)。

我們通過結構歸納證明其正確性。 歸納假設 ( IH ) 是這個定義對於較短的列表是正確的。 我們需要證明它對於更長的列表也是正確的。 實際上T[H|T]短一個元素。 因此IH表示[M|R]已排序。 這意味着MT的最小元素。 這也意味着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] 
    ).

其中歸納步驟的適用性就更加明確了。

不過,我不太確定這是冒泡排序


(or slower), but true bubble sort clocked at (close enough to the theoretical ), where n is the list's length:更新:實際上,測量增長經驗階數,其推斷數量增長為 (或更慢),但真正的冒泡排序時鍾為 (足夠接近理論 ),其中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] ).

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM