2013-10-09 3 views
4

나는 실제 세계 하스켈에 다음과 같은 문장을 건너 온 :대한 설명은

게으른 평가가 어떤 유령 효과가있다. 정렬되지 않은 목록의 최소값 요소 인 개를 찾고 싶다고 가정 해 봅시다. 기존의 언어에서는 분명히 목록을 정렬하고 첫 번째 요소를 가져 오는 것이지만 비용이 많이 듭니다. 효율성을 높이기 위해 대신이 값을 한 번에 사용하는 특수 함수 인 을 작성하면 다소 복잡한 서적 작업을 수행해야합니다. Haskell에서 sort-then-take 방식은 실제로 잘 수행됩니다. 게으름 은 목록이 k 최소값을 찾기에 충분할만큼만 정렬되도록합니다.

그리고 그들은 그에 대한 코드 implemntation 제공 :

minima k xs = take k (sort xs) 

을하지만 그래서인가? 나는 Haskell 에서조차도 k 엘리먼트를 가져 오는 일종의리스트를 작성해야한다고 생각한다. (목록의 끝에 가장 작은 숫자가 있다고 상상해보십시오). 내가 여기서 뭔가를 놓치고 있니?

+12

전체 목록을 정렬하는 것과 동일한 가장 작은 요소를 찾고 있습니까? quicksort (실제 구현이 아닐 수도 있음)를 수행한다고 가정합니다. 여기서 피벗 요소를 중심으로 배열을 분할 한 다음 배열의 왼쪽과 오른쪽 절반을 재귀 적으로 정렬합니다. 왼쪽 절반의 요소 만 요구하면 오른쪽 절반을 정렬 할 필요가 없습니다. – Satvik

+2

@Satvik 대답에 텍스트를 넣어 라. 친구! –

+3

평상시처럼 게으른 평가 그 자체의 효율성이 아니라 구성 가능성 및 분리 이해의 더 나은 예입니다. – jberryman

답변

1

(내 의견을 여기에 답하면됩니다.) 전체 목록을 순회하는 것은 정렬과 동일하지 않습니다. 피벗 주위의 목록을 분할 한 다음 목록의 왼쪽과 오른쪽 절반을 재귀 적으로 정렬하는 quicksort를 수행한다고 가정합니다. 왼쪽 절반의 요소 만 요구하면 오른쪽 절반을 정렬 할 필요가 없습니다. 이 인수는 재귀 적으로 적용 할 수 있습니다. 따라서 정렬 후 k 개의 요소를 n 길이 목록에서 가져 오는 경우에는 O(n + klog k)이 아닌 O(n log n)이됩니다. @MoFu가 지적한 바와 같이 Heinrich는 좋은 블로그 게시물 here을 보유하고 있습니다.