Мне нужно добавить одно целое число в список, который уже отсортирован, так что он идет в нужном месте. Моя первая мысль была что-то вроде
(sort (cons newelt list) #'<)
Однако, учитывая, что list
это уже отсортировано, действительно требуется только одна вставка, что означает, что это решение может быть ужасно непригодным в зависимости от используемого алгоритма sort
.
Итак, какой алгоритм sort
использует?
Буду ли я лучше делать что-то вроде следующего?
(let ((tail list))
;; The first element is never less-than
(while (and tail (< newelt (cadr tail)))
(setq tail (cdr tail)))
(setcdr tail (cons newelt (cdr tail)))
list)
elisp
performance
emacs-internals
Malabarba
источник
источник
B
будут изначально уже отсортированныеlist
иA
иC
изначально пустые списки. РазделитеB
на две частиB1
,B2
длиныm
иm
илиm+1
иm
, сравнитеnewelt
с первым элементомB2
. Еслиnewelt
это≥
расширениеA
вправо с помощьюB1
и заменитьB
сB2
, в противном случае расширитьC
его слева сB2
и заменитьB
наB1
. ПослеO(log n)
таких шагов ничего не осталосьB
. ЗатемA
содержит вещи≤ newelt
, иC
те> newelt
, и конкатенация создает расширенный отсортированный список. Извиняюсь за не оченьe-lisp
похожий язык.Ответы:
Если у вас установлен исходный код Emacs, вы можете найти исходный код для
sort
сM-x find-function
.Там вы можете увидеть, что
sort
выполняет сортировку слиянием. Он проверяет длину списка, разбивает список на две части, сортирует «переднюю» и «заднюю» части по рекурсии по отдельности, а затем объединяет их.Что касается того, будет ли ваша реализация быстрее - измерьте это! Он более эффективен в теории (O (n) по сравнению с O (n log n)), но
sort
имеет преимущество в том, что он написан на C, поэтому результат может пойти в любую сторону. (Конечно, не забудьте побайтно скомпилировать вашу функцию.)источник