Я пытаюсь написать простую пузырьковую сортировку в Common Lisp (также работает в Emacs Lisp) наиболее интуитивным способом:
(defun bubble-sort-long (list)
(labels ((rec (list acc)
(if (null list) (nreverse acc)
(progn
(dolist (x (cdr list))
(if (< x (car list))
(rotatef x (car list))))
(rec (cdr list) (push (car list) acc))))))
(rec list nil)))
Это не работает. Потому что rotatef заменяет только значение временной переменной x и (список автомобилей) вместо сравниваемого элемента в списке. Результат трассировки выглядит следующим образом:
>(setf a '(1 3 2 5 4))
>(trace bubble-sort)
>(bubble-sort a)
0: (BUBBLE-SORT-LONG (1 3 2 5 4))
0: BUBBLE-SORT-LONG returned (1 2 2 4 4)
Полагаю, что самым прямым способом решения этой проблемы было бы определение «деструктивного» макроса dolist, который присваивает x, который непосредственно указывает , на повторяющийся элемент в списке. Что-то вроде ndolist, так что я могу сделать следующую работу:
(setf a '(1 2 3))
(ndolist (x a)
(setf x (+ 1 x)))
даст: (2 3 4).
Кроме того, если вы можете дать более интуитивные мысли о сортировке пузырьков с помощью lisp, пожалуйста, дайте намек.
В ruby подобный алгоритм будет выглядеть примерно так:
class Array
def bubble_sort
self.each_with_index do |a,j|
i=j+1
while i<self.length
if (self[j]>self[i])
self[j],self[i]=self[i],self[j]
end
i=i+1
end
end
end
Что забавно, я все еще должен использовать «параллельное назначение», чтобы поменять значение. Ruby не поддерживает (поощряет) свопинг с использованием временной переменной через ссылку в стиле C / C ++.