정렬은 어떤 알고리즘을 사용합니까?


24

이미 정렬 된 목록에 단일 정수를 추가해야 올바른 위치로 이동합니다. 내 첫 강인은

(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)

1
이진 힙 (예 : heap.el )을 사용하면 코드에서 자주 작동합니다.
lunaryorn

하자 B이미 정렬 초기 수 listA그리고 C처음에 빈 목록. 분할 B두 부분으로 B1, B2길이 mmm+1하고는 m, 비교 newelt의 첫 번째 요소 B2. 경우 neweltIS는 확장 A과 오른쪽에 B1와 교체 BB2, 다른 확장 C과 그 왼쪽 B2과 교체 B와 함께 B1. O(log n)이러한 단계 후에 는 아무것도 남지 않습니다 B. 그런 다음 A사물 ≤ neweltC그 사물을 포함 > newelt하고 연결하면 확장 정렬 목록이 생성됩니다. e-lisp언어가 그리 좋지 않은 것에 대한 사과 .
jfbu

답변:


26

당신이 이맥스 소스 코드가 설치되어있는 경우에 대한 소스 코드를 찾을 수 sort와를 M-x find-function.

거기 sort에서 병합 정렬 을 수행하는 것을 볼 수 있습니다 . 목록의 길이를 확인하고 목록을 반으로 나누고 재귀를 통해 "전면"과 "후면"부분을 개별적으로 정렬 한 다음 두 부분을 병합합니다.

구현 속도가 더 빨라질 지 여부를 측정하십시오! 이론적으로는 더 효율적이지만 (O (n) vs O (n log n)) sortC로 작성하는 이점이 있으므로 결과는 어느 쪽이든 갈 수 있습니다. (물론, 함수를 바이트 컴파일하는 것을 잊지 마십시오.)


@Malabarba 기록을 위해, 어느 정도의 길이로 테스트 했습니까?
T. Verron

8
1000 개의 난수 목록에 난수를 삽입하여 1000 번 테스트했습니다 (모두 사전 생성됨). 수동 방법은 6 배 빨랐습니다.
Malabarba
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.