이 문제는 차례 매긴 리스트(ordered list)를
균형 잡힌 두 갈래 나무(balanced binary tree)로 바꾸는 프로시저를 살펴봅니다.

실행기는 그리 필요없을 듯싶지만,
quotient 프로시저가 어떻게 작동하는지 정확히 알 수없어 돌려보았습니다.
quotient 프로시저는 몫이라는 뜻답게
6을 2로 나누면 3, 5를 2로 나누면 2, 1을 2로 나누면 0을 내놓습니다.
즉, 1 = 2 * 0 + 1이라는 식에서 몫만을 내놓는 프로시저입니다.
a.
partial-tree 프로시저가 어떻게 돌아가는지 깔끔하고 짧은 문장으로 설명하라는군요.

(SICP 206쪽)
이것을 깔끔하고 짧게라...
먼저 받은 리스트에서 entry가 될 가운데 원소를 정하고
그 왼쪽의 것들의 개수를 계산합니다.
그리고 그 개수만큼을 tree로 만들도록 partial-tree를 호출합니다.
그럼 거기에 맞춰 알아서 왼쪽 tree가 만들어지겠지요.
원소들을 통째로 넘겨주었기에 왼쪽 tree는 첫 번째 원소에
오른쪽에 쓰일 나머지 원소들은 다음 원소에 저장되어 나옵니다.
이를 오른쪽의 것들의 개수를 계산한 후
가운데 것을 entry로 지정하고 오른쪽의 것들을 인자로 하는 partial-tree를 부릅니다.
그렇게 하면 역시 오른쪽 tree가 알아서 만들어지겠지요.
이 때 쓰고 남은 원소들을 remaining-elts로 하여
위에서 오른쪽에 쓰일 나머지 원소들을 지정합니다.
마지막으로 이들을 하나로 묶어 결과로 내놓습니다.
이건 거의 코드를 읽어내린 수준이네요.;;;
그럼 조금 바꿔서 말하겠습니다.
partial-tree에 리스트와 왼쪽에서부터 tree로 만들 원소들 개수를 적어주면
그에 맞춰 만들어진 tree와 나머지 원소들을 내놓다는다고 가정하고,
들어온 리스트의 가운데 원소를 entry로 한 후
들어온 리스트와 왼쪽 원소들의 개수만큼을 인자로 하여 partial-tree를 부릅니다.
그럼 왼쪽 tree와 나머지 원소들이 나올터이니
나머지 원소들과 그 크기를 인자로 하여 partial-tree를 부릅니다.
그렇게 하여 만들어진 tree와 함께 남은 원소들을 결과로 내놓습니다.
이것도 너무 길군요.OTL...
앞에서 프로시저를 만드는 생각을 할 때
'이미 만드는 방법을 알고 있다고 가정하고...'라는 표현을 씁니다.
(예 : 'set1의 cdr과 set2의 교집합을 어떻게 구하는지 안다 치고' - SICP 197쪽)
어차피 해당 프로시저를 호출하면 tree가 나오도록 해야할 것이니
'왼쪽 tree와 오른쪽 tree는 부르면 알아서 나온다.'라 가정하고
그렇게 나온 것들을 어떻게 구성하여 내놓을 것인가를 고민한다면
프로시저를 만드는데 좀 더 쉽게 만들 수 있지 않을까 생각했습니다.
하지만 그렇게 말을 하더라도 복잡하군요.OTL...
아직 실력이 멀었다는 증거이겠죠.ㅜㅜ
리스트 (1 3 5 7 9 11)을 넘길 경우 나무는 이렇게 그려집니다.

조금은 이상한 듯싶지만,
entry를 기준으로 큰 것과 작은 것이 각각 왼쪽과 오른쪽에 있으니 문제 없습니다.^^
b.
이 프로시저의 자람 차수(order of growth)는
연습문제 2.63의 tree->list 프로시저처럼 Θ(n)이라 생각합니다.
왜냐하면 tree의 각 entry에 맞춰 한 번씩 연산이 되고
마지막의 경우 세 번 연산이 되기 때문입니다.
각 entry는 n과 같기에 자람 차수는 Θ(n)이 됩니다.
참조
해럴드 애빌슨, 김재우 역, <컴퓨터 프로그램의 구조와 해석>, 인사이트, 2007, pp. 206
; BINARY TREES
(define (entry tree) (car tree))
(define (left-branch tree) (cadr tree))
(define (right-branch tree) (caddr tree))
(define (make-tree entry left right)
(list entry left right))
; exercise 2.64
(define (list->tree elements)
(car (partial-tree elements (length elements))))
(define (partial-tree elts n)
(if (= n 0)
(cons '() elts)
(let ((left-size (quotient (- n 1) 2)))
(let ((left-result (partial-tree elts left-size)))
(let ((left-tree (car left-result))
(non-left-elts (cdr left-result))
(right-size (- n (+ left-size 1))))
(let ((this-entry (car non-left-elts))
(right-result (partial-tree (cdr non-left-elts)
right-size)))
(let ((right-tree (car right-result))
(remaining-elts (cdr right-result)))
(cons (make-tree this-entry left-tree right-tree)
remaining-elts))))))))
; execute
(define list1 (list 1 3 5 7 9 11))
(list->tree list1)
(newline)
(length list1)
(quotient 6 2)
(quotient 5 2)
(quotient 1 2)
(quotient 0 2)
- SICP Exercise 연습문제 2.67 (0)2008/02/25
- SICP Exercise 연습문제 2.66 (2)2008/02/25
- SICP Exercise 연습문제 2.65 (0)2008/02/25
- SICP Exercise 연습문제 2.64 (0)2008/02/25
- SICP Exercise 연습문제 2.63 (0)2008/02/25
- SICP Exercise 연습문제 2.62 (1)2008/02/22
- SICP Exercise 연습문제 2.61 (0)2008/02/22
글에 잘못된 점, 다른 점, 부족한 점이 있다면 지적해주세요.
댓글, 트랙백, 메일 모두 고맙습니다.







댓글을 달아 주세요