Простой алгоритм сортировки пузырьков состоит из двух основных циклов:
- Пройдите по списку, «меняя» каждую пару элементов, если они не «в порядке» (внутренний цикл).
- Повторяйте (1) для результата, пока список не будет полностью отсортирован (внешний цикл).
Внутренний цикл (1) можно выразить так:
% performs a single pass of a bubble-sort on a list
do_bubble_sort([], []).
do_bubble_sort([X], [X]).
do_bubble_sort([X0,X1|Xs], [X0|Rem]) :-
X0 =< X1, !,
do_bubble_sort([X1|Xs], Rem).
do_bubble_sort([X0,X1|Xs], [X1|Rem]) :-
do_bubble_sort([X0|Xs], Rem).
do_bubble_sort/2
выше берет список и рекурсивно меняет последовательные элементы в списке, если они не удовлетворяют критерию =<
(3-е предложение). Этот внутренний цикл затем вызывается предикатом внешнего цикла bubble_sort/2
, как показано ниже:
% repeatedly performs a bubble sort on a list until it is sorted
bubble_sort(L, SL) :-
do_bubble_sort(L, L0),
(sorted_order(L0) ->
SL = L0
; bubble_sort(L0, SL)
).
Этот предикат принимает список ввода и рекурсивно применяет do_bubble_sort/2
, пока предикат sorted_order/1
не преуспеет в результате, то есть, если список в конечном итоге будет отсортирован. sorted_order/1
можно определить так:
% checks a list of things are in sorted (ascending) order
sorted_order([]).
sorted_order([_]) :- !.
sorted_order([X0,X1|R]) :-
X0 =< X1,
sorted_order([X1|R]).
Этот предикат берет список и рекурсивно проверяет, что каждая пара последовательных элементов находится в отсортированном порядке (посредством теста =<
, так же, как мы используем в do_bubble_sort/2
- это важно, иначе алгоритм может не прекратить!)