Можете ли вы сформулировать пузырьковую сортировку как моноид или полугруппу?
Учитывая следующий псевдокод для пузырьковой сортировки
procedure bubbleSort( A : list of sortable items )
repeat
swapped = false
for i = 1 to length(A) - 1 inclusive do:
/* if this pair is out of order */
if A[i-1] > A[i] then
/* swap them and remember something changed */
swap( A[i-1], A[i] )
swapped = true
end if
end for
until not swapped
end procedure
Вот код для Bubble Sort as Scala
def bubbleSort[T](arr: Array[T])(implicit o: Ordering[T]) {
import o._
val consecutiveIndices = (arr.indices, arr.indices drop 1).zipped
var hasChanged = true
do {
hasChanged = false
consecutiveIndices foreach { (i1, i2) =>
if (arr(i1) > arr(i2)) {
hasChanged = true
val tmp = arr(i1)
arr(i1) = arr(i2)
arr(i2) = tmp
}
}
} while(hasChanged)
}
Это реализация Haskell:
bsort :: Ord a => [a] -> [a]
bsort s = case _bsort s of
t | t == s -> t
| otherwise -> bsort t
where _bsort (x:x2:xs) | x > x2 = x2:(_bsort (x:xs))
| otherwise = x:(_bsort (x2:xs))
_bsort s = s
Можно ли сформулировать это как моноид или полугруппу?
1 ответ
Я использую свой телефон с плохим подключением к сети, но здесь идет.
tl; dr bubblesort - сортировка вставкой - моноидальная "дробь" для моноида упорядоченных списков со слиянием.
Упорядоченные списки образуют моноид.
newtype OL x = OL [x]
instance Ord x => Monoid (OL x) where
mempty = OL []
mappend (OL xs) (OL ys) = OL (merge xs ys) where
merge [] ys = ys
merge xs [] = xs
merge xs@(x : xs') ys@(y : ys')
| x <= y = x : merge xs' ys
| otherwise = y : merge xs ys'
Сортировка вставки дается
isort :: Ord x => [x] -> OL x
isort = foldMap (OL . pure)
потому что вставка точно объединяет одноэлементный список с другим списком. (Mergesort задается путем построения сбалансированного дерева, а затем с использованием той же карты foldMap.)
Какое это имеет отношение к пузырьковой сортировке? Сортировка вставок и сортировка пузырьков имеют одинаковую стратегию сравнения. Это можно увидеть, если нарисовать как сеть сортировки, состоящую из блоков сравнения и обмена. Здесь данные передаются вниз, а нижние входы в блоки [n] идут влево:
| | | |
[1] | |
| [2] |
[3] [4]
| [5] |
[6] | |
| | | |
Если вы выполняете сравнения в последовательности, указанной в приведенной выше нумерации, вырезая диаграмму в / слайсы, вы получаете вставку сортировки: первая вставка не нуждается в сравнении; второй нуждается в сравнении 1; третий 2,3; последние 4,5,6.
Но если вместо этого вы режете \ ломтики...
| | | |
[1] | |
| [2] |
[4] [3]
| [5] |
[6] | |
| | | |
... вы делаете пузырьковую сортировку: первый проход 1,2,3; второй проход 4,5; последний проход 6.