2.2.6 배열과 직교 목록연습문제 풀이
[ The Art of Computer Programming ]
아.꿈.사 Study2011. 04. 30
2. [21]
6. [M24]
9. [22]
12. [20]
13. [22]
15. [29]
24. [25]
풀이할 연습문제
2. [21]
6. [M24]
9. [22]
12. [20]
13. [22]
15. [29]
24. [25]
풀이할 연습문제
커누스 할아버지가
중요하다고 한 문제
2. [21]
6. [M24]
9. [22]
12. [20]
13. [22]
15. [29]
24. [25]
풀이할 연습문제
재미있을것 같아서
건드렸다가
후회한 문제
2.[21] 공식 (5)와 (6)은 1 ≤ r ≤ k 에 대해 0 ≤ I r ≤ d r 이라는
가정하에서 유도한 것이다. l r 과 u r 이 해당 차원의 하계,
상계라고 할 때, l r ≤ I r ≤ u r 인 경우에 적용되는 일반적인
공식을 제시하라.
공식(5), (6) 을 이용해서
I r 위치에서 하계인 l r 위치를
빼주면되지 않을까?
공식(5), (6) 을 이용해서
I r 위치에서 하계인 l r 위치를
빼주면되지 않을까?
즉, 공식(5), (6) 에서
LOC(A[I1, I2, … , Ik]) - LOC(A[l1, l2, … , lk])
…
LOC(A[0, 0, … , 0])
LOC(A[l1, l2, … , lk])
LOC(A[u1, u2, … , uk])
LOC(A[I1, I2, … , Ik])
…
2.[21] 공식 (5)와 (6)은 1 ≤ r ≤ k에 대해 0 ≤ I r ≤ d r 이라는
가정하에서 유도한 것이다. l r 과 u r 이 해당 차원의 하계,
상계라고 할 때, l r ≤ I r ≤ u r 인 경우에 적용되는 일반적인
공식을 제시하라.
LOC(A[I1, I2, … , Ik]) = LOC(A[0, 0, … , 0]) +kr
rrIa1
LOC(A[l1, l2, … , lk]) = LOC(A[0, 0, … , 0]) +kr
rrla1
-
LOC(A[I1, I2, … , Ik]) - LOC(A[l1, l2, … , lk])
kr
rrIa1
= -kr
rrla1
∴ LOC(A[I1, I2, … , Ik]) = LOC(A[l1, l2, … , lk])
kr
rrIa1
+ -kr
rrla1
ksr
ssr luca )1(여기서,
6.[M24] “4면체 배열” A[i, j, k]와 B[i, j, k] 가 있다. A의 경우
에는 0 ≤ k ≤ j ≤ i ≤ n 이고 B 경우에는 0 ≤ i ≤ j ≤ k ≤ n 이다.
두 배열 모두 색인의 사전식 순서에 따라 연속적인 메모리
장소에 저장되어 있다고 가정한다. 이 때, 어떠한 함수 f1, f2,
f3 에 대해 LOC(A[i, j, k])=a0+f1(I)+f2(J)+f3(K)임을 보여라.
LOC(B[i, j, k]) 도 그와 비슷한 방식으로 표현할 수 있을까?
6.[M24] “4면체 배열” A[i, j, k]와 B[i, j, k] 가 있다. A의 경우
에는 0 ≤ k ≤ j ≤ i ≤ n 이고 B 경우에는 0 ≤ i ≤ j ≤ k ≤ n 이다.
두 배열 모두 색인의 사전식 순서에 따라 연속적인 메모리
장소에 저장되어 있다고 가정한다. 이 때, 어떠한 함수 f1, f2,
f3 에 대해 LOC(A[i, j, k])=a0+f1(I)+f2(J)+f3(K)임을 보여라.
LOC(B[i, j, k]) 도 그와 비슷한 방식으로 표현할 수 있을까?
풀이) (a) LOC(A[I, J, K]) = LOC(A[0, 0, 0]) +12
1
3
2 KJI
(b) LOC(B[I, J, K]) = LOC(B[0, 0, 0])
JKJnInInn
2
2
2
2
3
3
3
3
6.[M24] “4면체 배열” A[i, j, k]와 B[i, j, k] 가 있다. A의 경우
에는 0 ≤ k ≤ j ≤ i ≤ n 이고 B 경우에는 0 ≤ i ≤ j ≤ k ≤ n 이다.
두 배열 모두 색인의 사전식 순서에 따라 연속적인 메모리
장소에 저장되어 있다고 가정한다. 이 때, 어떠한 함수 f1, f2,
f3 에 대해 LOC(A[i, j, k])=a0+f1(I)+f2(J)+f3(K)임을 보여라.
LOC(B[i, j, k]) 도 그와 비슷한 방식으로 표현할 수 있을까?
풀이) (a) LOC(A[I, J, K]) = LOC(A[0, 0, 0]) +12
1
3
2 KJI
(b) LOC(A[I, J, K]) = LOC(A[0, 0, 0])
JKJnInInn
2
2
2
2
3
3
3
3
9.[22] 그림 13에 나온 것과 비슷하지만 그보다는 훨씬 큰
어떤 표가 있으며, 그것의 모든 링크들이 그 그림에 나온
것과 같은 방향으로 설정되어 있다고 하자. (즉, 모든 노드
들과 링크들에서 LINK(X) < X 이다.) 여러 링크 필드들을
훑으면서 21세에서 23세 사이의 파란 눈 금발 여성을 모두
찾는 알고리즘을 설계하라. 단, 목록 FEMALE, A21, A22,
A23, BLOND, BLUE 각각을 최대 한 번만 훑어서 모든 답
을 찾아야 한다.
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G1. P1←FEMALE(HEAD)
P2←A21(HEAD)
P3←A22(HEAD)
P4←A23(HEAD)
P5←BLUE(HEAD)
P6←BLOND(HEAD)
goto G2
P1 P2
P3
P4
=NULL
P5
P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G2. while ( P5 > P6 )
P5←EYES(P5)
if P5 < P6 then
goto G5
else if P5 == P6 then
goto G3
P1 P2
P3
P4
=NULL
P5
P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G5. P6←HAIR(P6)
if P6 == ∧ then
return FALSE
else
goto G2
P1 P2
P3
P4
=NULL
P5
P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G2. while ( P5 > P6 )
P5←EYES(P5)
if P5 < P6 then
goto G5
else if P5 == P6 then
goto G3
P1 P2
P3
P4
=NULL
P5
P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G5. P6←HAIR(P6)
if P6 == ∧ then
return FALSE
else
goto G2
P1 P2
P3
P4
=NULL
P5
P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22G2. while ( P5 > P6 )
P5←EYES(P5)
if P5 < P6 then
goto G5
else if P5 == P6 then
goto G3
P1 P2
P3
P4
=NULL
P5 P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
P1 P2
P3
P4
=NULL
P5 P6
G3. while ( P4 > P6 )
P4←A23(P4)
while ( P3 > P6 )
P3←A22(P3)
while ( P2 > P6 )
P2←A21(P2)
if P4 < P6 && P3 < P6
&& P2 < P6 then
goto G5
else
goto G4
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
G3. while ( P4 > P6 )
P4←A23(P4)
while ( P3 > P6 )
P3←A22(P3)
while ( P2 > P6 )
P2←A21(P2)
if P4 < P6 && P3 < P6
&& P2 < P6 then
goto G5
else
goto G4
P1 P2
P3 P4
=NULL
P5 P6
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
P1
P2
P3 P4
=NULL
P5 P6
G3. while ( P4 > P6 )
P4←A23(P4)
while ( P3 > P6 )
P3←A22(P3)
while ( P2 > P6 )
P2←A21(P2)
if P4 < P6 && P3 < P6
&& P2 < P6 then
goto G5
else
goto G4
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
P1
P2
P3 P4
=NULL
P5 P6
G4. while ( P1 > P6 )
P1←SEX(P1)
if P1 == P6 then
print *P6
return TRUE
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
P1
P2
P3 P4
=NULL
P5 P6
G4. while ( P1 > P6 )
P1←SEX(P1)
if P1 == P6 then
print *P6
return TRUE
PERSON[6]
PERSON[5]
PERSON[4]
PERSON[3]
PERSON[2]
PERSON[1]
MA
LE
FE
MA
LE
A21
DA
RK
A24
A23
A28
BLU
EB
RO
WN
GR
EE
NH
AZ
EL
BLO
ND
RE
D
A22
P1 P2
P3 P4
=NULL
P5 P6
G4. while ( P1 > P6 )
P1←SEX(P1)
if P1 == P6 then
print *P6
return TRUE
결국 P6 기준으로
모든 포인터가 같을 때 값을 반환
이 알고리즘은 최적화 방법은 아니다.
모든 노드를 선형 탐색을 하기 때문에…?
최적화 방법은
TAOCP 3권 6.5절 2차키에 의한 조회
참고.
12.[20] 단계 S7의 시작에서 VAL(Q0), VAL(P0), VAL(P1)
값들을 (13)에 쓰인 a, b, c 로 표현하라.
12.[20] 단계 S7의 시작에서 VAL(Q0), VAL(P0), VAL(P1)
값들을 (13)에 쓰인 a, b, c 로 표현하라.
VAL(Q0) = c
VAL(P0) = b/a
VAL(P1) = d
알고리즘 비교해보시면 간단하게 알 수 있습니다.
13.[22] 그림 14에서 직선적인 선형 목록 대신 순환 목록
을 사용한 이유는 무엇일까? 순환 연결을 사용하지 않
도록 알고리즘 S를 재작성하는 게 가능할까?
13.[22] 그림 14에서 직선적인 선형 목록 대신 순환 목록
을 사용한 이유는 무엇일까? 순환 연결을 사용하지 않
도록 알고리즘 S를 재작성하는 게 가능할까?
순환 목록 사용 이유
“경계값” (Tail Node) 를 설정.
Tail Node 의 링크(리스트의 처음) 시작.
=> 편리하게 Tail Node 검사 가능
Ex) 그림 14 에서 Tail Node 의 row, col 필드의 값은 모두 -1
알고리즘S 에서 행, 열 리스트의 마지막 검사는
ROW(I) < 0 또는 COL(J) < 0
13.[22] 그림 14에서 직선적인 선형 목록 대신 순환 목록
을 사용한 이유는 무엇일까? 순환 연결을 사용하지 않
도록 알고리즘 S를 재작성하는 게 가능할까?
알고리즘S 재작성 가능여부
단방향 리스트를 사용할 수는 있지만
알고리즘이 더욱 복잡해지며
메모리를 절약할 수도 없다.
비효율적
15.[29] 알고리즘 S를 위한 MIXAL 프로그램을 작성하라.
VAL 필드는 부동소수점이고, 그 필드들의 연산을 위
해 MIX의 부동소수점 산술 연산자 FADD, FSUB,
FMUL, FDIV를 사용할 수 있다고 가정할 것. 단순함을
위해, 피연산자들의 덧셈 또는 뺄셈에 의해 대부분의
유효숫자들이 취소된다면 FADD나 FSUB가 0을 돌려
준다고 가정한다. 즉, 단계 S7의 “VAL(P1)=0” 판정을
그대로 사용해도 안전하다고 가정하는 것이다. 부동
소수점 연산들은 rA만 사용한다(rX는 사용하지 않는
다).
24.[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
질문이 너무 길다.
무슨 소리지………?
[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
24.
이것은 희소 배열이다.
[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
24.
A[k]에 처음 접근하면
0으로 초기화하고
[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
24.
시간은 상관 X
[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
24.
A[k] 미리 초기화 X
쓰레기 일수도 있다.
[25] (희소 배열 요령.) 커다란 배열을 임의 접근으로
사용해야 하지만, 그 행렬의 아주 많은 성분들을 실제
로 참조하지 않을 것이라고 가정하자. 임의의 성분
A[k]에 처음 접근했을 때 그것을 0으로 설정하되, 모든
장소들을 미리 0으로 초기화 하는데 시간을 소비하지
는 않고자 한다. 임의의 k가 주어졌을 때, 실제 초기 메
모리 내용들에 대해 어떠한 것도 가정하지 않고, 배열
접근 당 오직 고정된 적은 수의 추가적인 연산들만 사
용해서 해당 성분 A[k]를 신뢰성 있게 읽고 쓰는 것이
어떻게 가능할지 설명하라.
24.
A[k] 값이 유효할 수 있는
방법을 설명하시오.
임의의 희소 배열 A 알수 없는 값
같은 크기의 검증용 배열 V 알수 없는 값
사용된 장소들의 목록 L 알수 없는 값
목록 L 의 요소 개수 n 0
임의의 값 k 에 대해 A[k] 접근시
if 0 ≤ V[k] ≤ n && L[V[k]] == k then
return TRUE
else
V[k] ← n
L[n] ← k
A[k] ← 0
n ← n+1
return FALSE
임의의 값 k1 에 대해 A[k1] 접근시
if 0 ≤ V[k1] ≤ n && L[V[k1]] == k1 then
return TRUE
else
V[k1] ← n
L[n] ← k1
A[k1] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
n 0
…
임의의 값 k1 에 대해 A[k1] 접근시
if 0 ≤ V[k1] ≤ n && L[V[k1]] == k1 then
return TRUE
else
V[k1] ← n
L[n] ← k1
A[k1] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
k1
0
n 1
…
임의의 값 k2 에 대해 A[k2] 접근시
if 0 ≤ V[k2] ≤ n && L[V[k2]] == k2 then
return TRUE
else
V[k2] ← n
L[n] ← k2
A[k2] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 1
k1…
임의의 값 k2 에 대해 A[k2] 접근시
if 0 ≤ V[k2] ≤ n && L[V[k2]] == k2 then
return TRUE
else
V[k2] ← n
L[n] ← k2
A[k2] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 2
k1
0
1
…k2
임의의 값 k1 에 대해 A[k1] 접근시
if 0 ≤ V[k1] ≤ n && L[V[k1]] == k1 then
return TRUE
else
V[k1] ← n
L[n] ← k2
A[k1] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 2
k1
0
1
…k2
임의의 값 k1 에 대해 A[k1] 접근시
if 0 ≤ V[k1] ≤ n && L[V[k1]] == k1 then
return TRUE
else
V[k1] ← n
L[n] ← k2
A[k1] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 2
k1
0
1
…k2
임의의 값 k2 에 대해 A[k2] 접근시
if 0 ≤ V[k2] ≤ n && L[V[k2]] == k2 then
return TRUE
else
V[k2] ← n
L[n] ← k2
A[k2] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 2
k1
0
1
…k2
임의의 값 k2 에 대해 A[k2] 접근시
if 0 ≤ V[k2] ≤ n && L[V[k2]] == k2 then
return TRUE
else
V[k2] ← n
L[n] ← k2
A[k2] ← 0
n ← n+1
return FALSE
A
V
… …
… …
L
k1
0
0
k2
n 2
k1
0
1
…k2
끝