[英]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]
已排序。 這意味着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]
).
其中歸納步驟的適用性就更加明確了。
不過,我不太確定這是冒泡排序。
(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.