J'ai besoin d'ajouter un seul entier à une liste qui est déjà triée, de telle sorte qu'elle aille au bon endroit. Ma première pensée était quelque chose comme
(sort (cons newelt list) #'<)
Cependant, étant donné qu'il list
est déjà trié, une seule insertion est vraiment nécessaire, ce qui signifie que cette solution pourrait être horriblement inappropriée en fonction de l'algorithme utilisé par sort
.
Alors, quel est l'algorithme qui sort
utilise?
Serais-je mieux de faire quelque chose comme ce qui suit?
(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
la source
la source
B
initiales déjà triéeslist
etA
etC
initialement vides. DiviserB
en deux partiesB1
,B2
de longueursm
etm
oum+1
etm
, comparernewelt
au premier élément deB2
. Sinewelt
est -≥
étendreA
à sa droite avecB1
et remplacerB
avecB2
, étendre le resteC
à sa gauche avecB2
et remplacerB
parB1
. Après deO(log n)
telles étapes, rien n'est laisséB
.A
Contient ensuite les choses≤ newelt
, etC
celles-ci> newelt
, et la concaténation produit la liste triée étendue. Toutes mes excuses pour une-lisp
langage peu similaire.Réponses:
Si le code source d'Emacs est installé, vous pouvez trouver le code source de
sort
avecM-x find-function
.Vous pouvez y voir qui
sort
effectue un tri par fusion. Il vérifie la longueur de la liste, divise la liste en deux, trie les parties "avant" et "arrière" séparément par récursivité, puis fusionne les deux.Quant à savoir si votre mise en œuvre serait plus rapide - mesurez-la! Il est plus efficace en théorie (O (n) vs O (n log n)), mais
sort
a l'avantage d'être écrit en C, donc le résultat peut aller dans les deux sens. (Bien sûr, n'oubliez pas de compiler vos fonctions en octets.)la source