4. 알고리즘 성능 분석
알고리즘 성능 분석 기법
수행 시간 측정
두 개의 알고리즘의 실제 수행 시간을 측정한다.
실제로 구현이 필요
동일 하드웨어를 사용하여 측정해야 함
알고리즘 복잡도 분석
직접 구현하지 않고서도 수행시간을 분석하는 방법
알고리즘이 수행하는 연산의 횟수를 측정하여 비교한다.
일반적으로 연산의 횟수는 n의 함수
시간 복잡도(time complexity) : 수행 시간 분석
공간 복잡도(space complexity) : 수행 시 필요로 하는 메모리 공간 분석
연산의 수 = 8
3n+2
연산의 수 =26
5n2 +6
프로그램 A 프로그램 B
워드2008 워드2012
10. Best, Average, Worst Cases
알고리즘의수행시간
입력자료의집합에따라다를수있다.
정렬알고리즘의수행시간은입력집합에따라다를수있다.
Case 구분
최선의경우(best case): 수행시간이가장빠른경우
실제로의미가없는경우가많다.
평균의경우(average case): 수행시간이평균적인경우
계산하기가상당히어렵다.
최악의경우(worst case): 수행시간이가장늦은경우
가장널리사용되며, 계산하기쉽다.
응용에따라중요한의미를가질수있다.
최악의경우
최선의경우
평균적인경우
A
B
C
D
E
F
G
입력집합
수행시간
100
50
17. Fibonacci sequence
피보나치수열계산함수
이경우어느함수가더효율적인가?
intfib (int n)
{
if (n<1) returnn;
else{
int i, tmp, current=1; last=0;
for(i=2; i<=n; i++){
tmp= current;
current += last;
last = tmp;
}
return current;
}
intfib(intn)
{
if(n==0) return0;
if(n==1) return1;
return(fib(n-1) + fib(n-1));
}
반복
순환
18. The Tower of Hanoi
하노이탑
이동조건
한번에하나의원판만이동할수있다.
맨위에있는원판만이동할수있다.
크기가작은원판위에큰원판이쌓일수없다.
중간의막대를임시적으로이용할수있으나앞의조건들을지켜야한다.
하노이탑확장
원판이늘어나는경우
막대의수가늘어나는경우
19. The Tower of Hanoi
하노이탑문제에대한의사코드
순환이되는부분을찾는것이Key !!!
voidhanoi_tower(intn, charfrom,char tmp, charto)
{
if(n==1) {
from에서to로원판을옮긴다.
}
else{
①from의맨밑에원판을제외한나머지원판들을tmp로옮긴다.
// hanoi_tower(n-1, from, to, tmp);
②from에있는한개의원판을to로옮긴다.
③tmp의원판들을to로옮긴다.
// hanoi_tower(n-1, tmp, from, to);
}
}
원래문제의
축소된형태이다.
22. 리스트(List)
리스트, 선형 리스트
목록이나 도표처럼 여러 데이터를 관리할 수 있는 자료형을 추상화
순서를 가진 항목들의 모임
※ 집합: 항목간의 순서의 개념이 없음
데이터 삽입, 삭제, 검색 등 필요 작업을 가함
스택과 큐는 리스트의 특수한 경우에 해당
리스트의 연산
( , ,..., ) 0 1 1 n L item item item
연 산 설 명
Insert(Position, Data) 데이터를 해당 위치(Position)에 넣기
Delete(Position) 해당 위치(Position)의 데이터를 삭제
Retrieve(Position, Data) 해당 위치(Position)의 데이터를 Data 변수에 복사
Create( ) 빈 리스트 만들기
Destroy( ) 리스트 없애기
IsEmpty( ) 빈 리스트인지 확인 (아무 것도 안 적혔는지 확인)
Length( ) 몇 개의 항목인지 계산 (몇 개나 적혔는지 세기)
23. 리스트구현방법
배열을이용하는방법
구현이간단
삽입, 삭제시오버헤드
항목의개수제한
연결리스트를이용하는방법
구현이복잡
삽입, 삭제가효율적
크기가제한되지않음
A
B
C
D
n
A
B
C
배열이용
연결리스트이용
하나의노드가데이터와링크로구성되어있고링크가노드들을연결한다
24. Array List
1차원배열에항목들을순서대로저장
L=(A, B, C, D, E)
삽입연산
삽입위치다음의항목들을이동하여야함.
삭제연산
삭제위치다음의항목들을이동하여야함
A
B
C
D
E
0 1 2 3 4 5 6 7 8 9
A
B
C
D
E
0 1 2 3 4 5 6 7 8 9
A
B
D
E
0 1 2 3 4 5 6 7 8 9
N
N
26. ArrayListType의구현
삽입과삭제
// position: 삽입하고자하는위치
// item: 삽입하고자하는자료
void add(ArrayListType*L, int position, element item)
{
if( !is_full(L) && (position >= 0) &&
(position <= L->length) ){
int i;
for(i=(L->length-1); i>=position;i--)
L->list[i+1] = L->list[i];
L->list[position] = item;
L->length++;
}
}
// position: 삭제하고자하는위치
// 반환값: 삭제되는자료
element delete(ArrayListType*L, int position)
{
int i;
element item;
if( position < 0 || position >= L->length )
error("위치오류");
item = L->list[position];
for(i=position; i<(L->length-1);i++)
L->list[i] = L->list[i+1];
L->length--;
return item;
}
27. 연결리스트(Linked List)
연결리스트
리스트의항목들을노드(node)라고하는곳에분산하여저장
다음항목을가리키는주소도같이저장
노드(node) : <항목, 주소> 쌍
노드는데이터필드와링크필드로구성
데이터필드–리스트의원소, 즉데이터값을저장하는곳
링크필드–다른노드의주소값을저장하는장소(포인터)
메모리에서의노드의물리적순서가리스트의논리적순서와일치할필요없음
A
B
C
D
E
28. 연결리스트의장단점
구조
노드= 데이터필드+ 링크필드
Head Pointer
리스트의첫번째노드를가르키는변수
노드의생성
필요시동적메모리생성이용
장점
삽입, 삭제가보다용이하다.
연속된메모리공간이필요없다.
크기제한이없다
단점
구현이어렵다.
오류가발생하기쉽다.
A
B
C
D
E
A
B
C
D
E
X
N
X
X
메인메모리
메인메모리
삽입연산
삭제연산
Data
Link
HeadPointer
30. 단순연결리스트
단순연결리스트
하나의링크필드를이용연결
마지막노드의링크값은NULL
A
B
C
D
NULL
Head Pointer
insert_node(L,before,new)
ifL=NULL
thenL←new
elsenew.link←before.link
before.link←new
C
D
C
E
D
E
삽입연산
remove_node(L,before,removed)
ifL≠NULL
thenbefore.link←removed.link
destroy(removed)
C
E
D
C
E
D
before
before
before
before
removed
after
after
after
new
new
after
removed
33. 연결리스트연산
삭제연산
삭제의2가지경우
p가NULL인경우: 맨앞의노드를삭제
연결리스트의첫번째노드를삭제한다. 헤드포인터변경
p가NULL이아닌경우: 중간노드를삭제
removed 앞의노드인p의링크가removed 다음노드를가리키도록변경
//phead:헤드포인터head의포인터
//p:삭제될노드의선행노드를가리키는포인터
//removed:삭제될노드를가리키는포인터
voidremove_node(ListNode**phead,ListNode*p,ListNode*removed)
10
20
n
11
x
list
removed
10
20
n
11
list
removed
x
p
36. 연결리스트연산
탐색연산
특정한데이터값을갖는노드를찾는연산
A
B
C
D
NULL
Head Pointer
p
ListNode*search(ListNode*head,intx)
{
ListNode*p;
p=head;
while(p!=NULL){
if(p->data==x)returnp;//탐색성공
p=p->link;
}
returnp;//탐색실패일경우NULL반환
}
37. 연결리스트연산
합병연산
2개의리스트를합하는연산
A
B
C
D
n
Head 1
J
K
L
Q
n
Head 2
ListNode*concat(ListNode*head1,ListNode*head2)
{
ListNode*p;
if(head1==NULL)returnhead2;
elseif(head2==NULL)returnhead1;
else{
p=head1;
while(p->link!=NULL)
p=p->link;
p->link=head2;
returnhead1;
}
}
38. 연결리스트연산
역순연산
리스트의노드들을역순으로만드는연산
A
n
B
C
D
n
Head
r
q
p
x
x
x
ListNode*reverse(ListNode*head)
{
//순회포인터로p,q,r을사용
ListNode*p,*q,*r;
p=head;//p는역순으로만들리스트
q=NULL;//q는역순으로만들노드
while(p!=NULL){
r=q;//r은역순으로된리스트.r은q,q는p를차례로따라간다.
q=p;
p=p->link;
q->link=r;//q의링크방향을바꾼다.
}
returnq;//q는역순으로된리스트의헤드포인터
}
40. 원형리스트연산
삽입(처음에삽입)
A
B
C
D
Head
B
x
②
①
//phead:리스트의헤드포인터의포인터
//p:선행노드
//node:삽입될노드
voidinsert_first(ListNode**phead,ListNode*node)
{
if(*phead==NULL){
*phead=node;
node->link=node;
}
else{
node->link=(*phead)->link;
(*phead)->link=node;
}
}
node
41. 원형리스트연산
삭제(끝에삽입)
A
B
C
D
Head
B
x
②
①
node
//phead:리스트의헤드포인터의포인터
//p:선행노드
//node:삽입될노드
voidinsert_last(ListNode**phead,ListNode*node)
{
if(*phead==NULL){
*phead=node;
node->link=node;
}
else{
node->link=(*phead)->link;
(*phead)->link=node;
*phead=node;
}
}
x
③
43. 이중연결리스트
삽입
before
x
x
③
①
②
④
//노드new_node를노드before의오른쪽에삽입한다.
voiddinsert_node(DlistNode*before,DlistNode*new_node)
{
new_node->llink=before;
new_node->rlink=before->rlink;
before->rlink->llink=new_node;
before->rlink=new_node;
}
44. 이중연결리스트
삭제
//노드removed를삭제한다.
voiddremove_node(DlistNode*phead_node,
DlistNode*removed)
{
if(removed==phead_node)return;
removed->llink->rlink=removed->rlink;
removed->rlink->llink=removed->llink;
free(removed);
}
x
x
x
x
45. 연결리스트를이용한리스트ADT 구현
How to ?
리스트ADT의연산을연결리스트를이용하여구현
리스트ADT의add, delete 연산의파라미터는위치
연결리스트의insert_node, remove_node의파리미터는노드포인터
상황에따라연산을적절하게선택하여야함
add(항목의위치)
delete(항목의위치)
insert_node(노드포인터)
remove_node(노드포인터)
리스트ADT
연결리스트
사용자
50. 스택(Stack)
스택
선형리스트구조의특별한형태로, 데이터의삽입과삭제가리스트한쪽끝에서만일어나는자료구조
후입선출(LIFO:Last-InFirst-Out)
가장최근에들어온데이터가가장먼저나감
A
C
삽입
(Push)
삭제
(Pop)
top
스택의동작구조
B
bottom
요소
(element)
51. 스택추상데이터타입(ADT)
스택의용도
에디터에서되돌리기기능, 함수호출에서복귀주소기억
스택의연산
객체: n개의element형의요소들의선형리스트
연산:
▪create() ::=스택을생성한다.
▪is_empty(s) ::= 스택이비어있는지를검사한다.
▪is_full(s) ::= 스택이가득찼는가를검사한다.
▪push(s, e) ::= 스택의맨위에요소e를추가한다.
▪pop(s) ::= 스택의맨위에있는요소를삭제한다.
▪peek(s) ::= 스택의맨위에있는요소를삭제하지않고반환한다.
초기상태
push(A)
push(B)
push(C)
pop()
A
A
B
A
B
C
A
B
52. 배열을이용한스택의구현
스택구현
1차원배열stack[ ]
스택에서가장최근에입력되었던자료를가리키는top 변수
가장먼저들어온요소는stack[0]에, 가장최근에들어온요소는stack[top]에저장
스택이공백상태이면top은-1
Is_empty, is_full연산
공백상태
A
B
C
D
3
2
1
0
-1
3
2
1
0
-1
TOP
A
B
3
2
1
0
-1
TOP
TOP
is_empty(S)
if top= -1
then return TRUE
else return FALSE
is_full(S)
if top= (MAX_STACK_SIZE-1)
then return TRUE
else return FALSE
53. 배열을이용한스택의구현
push 연산
pop 연산
push(S, x)
if is_full(S)
then error "overflow"
else top←top+1
stack[top]←x
pop(S, x)
if is_empty(S)
then error "underflow"
else e←stack[top]
top←top-1
return e
push(C)
A
B
A
B
C
TOP
TOP
pop(C)
A
B
A
B
C
TOP
TOP
54. 연결스택
연결리스트를이용하여구현한스택
장점: 크기가제한되지않음
단점: 구현이복잡하고삽입이나삭제시간이오래걸림
연결스택(Linked Stack)
A
B
3
2
1
0
-1
TOP
C
C
B
A
n
TOP
typedefint element;
typedefstructStackNode{
element item;
structStackNode*link;
} StackeNode;
typedefstruct{
StackNode*top;
} LinkedStackType;
요소타입
노드타입
연결스택의관련데이터
55. 연결스택에서의연산
push(), pop()
// 삽입함수
void push(LinkedStackType*s, element item) {
StackNode*temp=(StackNode*)malloc(sizeof(StackNode));
if( temp == NULL ){
fprintf(stderr, "메모리할당에러n");
return;
}
else{
temp->item = item;
temp->link = s->top;
s->top = temp;
}
}
// 삭제함수
element pop(LinkedStackType*s)
{
if( is_empty(s) ) {
fprintf(stderr, "스택이비어있음n");
exit(1);
}
else{
StackNode*temp=s->top;
int item = temp->item;
s->top = s->top->link;
free(temp);
return item;
}
}
A
C
B
A
n
Top
Temp
②
①
C
B
A
n
Top
Temp
56. 스택의응용: 괄호검사
괄호의종류
괄호의종류: 대괄호(‘[’, ‘]’), 중괄호(‘{’, ‘}’), 소괄호(‘(’, ‘)’)
조건
왼쪽괄호의개수와오른쪽괄호의개수가같아야한다.
같은괄호에서왼쪽괄호는오른쪽괄호보다먼저나와야한다.
괄호사이에는포함관계만존재한다.
잘못된괄호의사용예
(a(b), a(b)c), a{b(c[d]e}f)
if( ( i==0 ) && (j==0 )
비교
비교
오류
{ A [ (i+1 ) ]=0; }
비교
비교
비교
성공
(
(
(
(
(
(
(
(
{
{
[
{
[
{
{
[
(
{
[
(
(
(
60. 배열을이용한큐
선형큐
배열을선형으로사용하여큐를구현
삽입을계속하기위해서는요소들을이용시켜야함
문제점이많아사용되지않음
원형큐
배열을원형으로사용하여큐를구현
front : 첫번째요소하나앞의인덱스
rear : 마지막요소의인덱스
[-1] [0] [1] [2] [3] [4] [5]
[-1] [0] [1] [2] [3] [4] [5]
front
rear
front
rear
rear
a
b
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
61. 원형큐의삽입과삭제
rear
a
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
rear
a
b
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
rear
b
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
2. A 삽입
rear
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
1. 초기상태
4. A 삭제
3. B 삽입
62. 공백상태, 포화상태
공백상태
front == rear
포화상태
front % M == (rear+1) % M
공백상태와포화상태를구별하기위해서는하나의공간은항상비워둔다
rear
front
…
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
1. 공백상태
rear
front
d
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
1. 포화상태
e
f
g
rear
front
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
1. 초기상태
a
b
c
d
e
f
g
a
b
c
h
64. 연결큐(Linked Queue)
연결큐: 연결리스트로구현된큐
front 포인터는삭제와관련되며rear 포인터는삽입
front는연결리스트의맨앞에있는요소를가리킨다
rear 포인터는맨뒤에있는요소를가리킨다
큐에요소가없는경우에는front와rear는NULL
A
B
C
D
NULL
rear
front
삽입
삭제
A
B
C
D
NULL
rear
front
temp
A
B
C
D
NULL
rear
front
A
B
C
D
NULL
rear
front
A
B
C
D
NULL
rear
front
temp
66. 덱의연산
C
A
ddd_front(dq, A)
A
ddd_rear(dq, B)
B
A
ddd_front(dq, C)
B
C
A
ddd_rear(dq, D)
B
D
A
delete_front(dq)
B
D
A
delete_rear(dq)
B
front
rear
front
rear
front
rear
front
rear
front
rear
front
rear
77. 히프연산
Upheap알고리즘
Downheap알고리즘
insert_max_heap(A, key)
heap_size← heap_size+ 1;
i ← heap_size;
A[i] ← key;
while i ≠ 1 and A[i] > A[PARENT(i)] do
A[i] ↔ A[PARENT];
i ← PARENT(i);
delete_max_heap(A)
item ← A[1];
A[1] ← A[heap_size];
heap_size←heap_size-1;
i ← 2;
while i ≤ heap_sizedo
if i < heap_sizeand A[LEFT(i)] > A[RIGHT(i)]
then largest ← LEFT(i);
else largest ← RIGHT(i);
if A[PARENT(largest)] > A[largest]
then break;
A[PARENT(largest)] ↔ A[largest];
i ← CHILD(largest);
return item;
108. 이진트리의분류
포화이진트리(Full binary tree)
트리의각레벨에노드가다차있는이진트리
전체노드개수= 푖=0 푘−12푖= 2k-1
노드의번호는레벨단위로왼쪽에서오른쪽으로
완전이진트리(Complete binary tree)
높이가h일때레벨1부터모두노가채워져있고,
마지막레벨h에서는왼쪽부터오른쪽으로노드가순서대로채워져있는경우
A
B
C
D
E
F
G
A
B
C
D
E
F
G
H
I
J
A
B
C
D
F
G
I
포화이진트리
완전이진트리
기타이진트리
109. 이진트리의특성
노드개수가n이면간선의개수는n-1
높이가h인이진트리의경우,
최소h개의노드를가지며, 최대2h-1개의노드를가진다.
+
*
/
a
b
c
d
노드의개수: 7
간선의개수: 6
1
2
3
높이=3
+
*
/
a
b
c
d
21-1=1
22-1=2
23-1=4
최대노드개수=3
최대노드개수= 21-1 + 22-1+ 23-1= 1+2+4 =7
116. 수식트리
수식트리: 산술식을트리형태로표현한것
비단말노드: 연산자(Operator)
단말노드: 피연산자(Operand)
or
<
<
a
b
c
d
-
a
x
b
c
+
a
b
(a)
(b)
(c)
수식
a + b
a -(b ×c)
(a < b) or (c < d)
전위순회
+ a b
-a ×b c
or < a b < c d
중위순회
a + b
a -b ×c
a < b or c < d
후위순회
a b +
a b c ×-
a b < c d < or
어떤순회방법이적합한가?
126. 그래프(Graph)
연결되어있는객체간의관계를표현하는자료구조
예: 전기회로, 프로젝트관리, 지도에서도시의연결
그래프이론(Graph Theory)
그래프를문제해결의도구로이용하는연구분야
그래프역사
1800년대Euler에의해창안
그래프(Graph)
S
B
K
J
I
D
D
A
C
B
b
a
d
c
g
e
f
위치: 정점(node)
다리: 간선(edge)
127. 그래프용어
그래프는(V, E)로표시된다.
V는정점(Vertices)들의집합
E는간선(Edge)들의집합
정점과간선은모두관련되는데이터를가질수있다.
무방향간선(Undirected Graph) : (A, B) = (B, A)
방향간선(Directed Graph) : <A, B> ≠<B, A>
가중치그래프(Weighted Graph), 네트워크(Network) : 간선에비용이나가중치가할당
S
B
K
J
I
D
9
9
7
6
5
5
5
1
가중치표시
S
B
K
J
I
D
방향표시
S
B
K
J
I
D
방향/가중치표시
9
9
7
6
5
5
5
1
A
B
A
B
A
B
1200
140. Prim의MST 알고리즘
Prim의MST 알고리즘
시작정점에서부터출발하여신장트리집합을단계적으로확장해나가는방법
시작단계에서는시작정점만이신장트리집합에포함
앞단계에서만들어진신장트리집합에, 인접한정점들중에서최저간선으로연결된정점을선택하여트리를확장
이과정은트리가n-1개의간선을가질때까지계속된다
간선(a,b)와간선(f,e)의가중치를비교해보면, (f,e)가27로서(a,b)의29보다낮다
따라서(f,e)간선이선택되고, 정점e가신장트리집합에포함된다.
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
141. Prim의MST 알고리즘
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
143. Kruskal의MST 알고리즘
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
f
a
b
g
e
c
d
10
29
15
25
27
22
12
16
8
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
10
12
15
16
18
22
25
27
29
afcd bgbcdg de egefab
x
x
146. Dijkstra의최단경로알고리즘
Dijkstra의최단경로알고리즘
네트워크에서하나의시작정점으로부터모든다른정점까지의최단경로를찾는알고리즘
집합S: 시작정점v로부터의최단경로가이미발견된정점들의집합
distance 배열: 최단경로를알려진정점만을통하여각정점까지가는최단경로의길이
매단계에서가장distance 값이적은정점을S에추가한다
v
v
w
u
s
s
시작노드
distance=7
distance=3
distance=5
①< (②+③)
①
②
③
최단경로
다른경로
distance 값이
최소인노드
v
w
u
s
새롭게
추가된노드
distance[u]
distance[w]
weight[u][w]
distance 값갱신
distance[w]=min(distance[w],distance[u]
+weight[u][w])
147. Dijkstra의최단경로알고리즘
// 입력: 가중치그래프G, 가중치는음수가아님.
// 출력: distance 배열, distance[u]는v에서u까지의최단거리이다.
shortest_path(G, v)
S←{v}
for 각정점w∈Gdo
distance[w]←weight[v][w];
while 모든정점이S에포함되지않으면do
u←집합S에속하지않는정점중에서최소distance 정점;
S←S∪{u}
for u에인접하고S에있는각정점z do
if distance[u]+weight[u][z] < distance[z]
then distance[z]←distance[u]+weight[u][z];
175. 회전방법
회전종류
LL 회전: A부터N까지의경로상의노드들을오른쪽으로회전시킨다.
LR 회전: A부터N까지의경로상의노드들을왼쪽-오른쪽으로회전시킨다.
RR 회전: A부터N까지의경로상의노드들을왼쪽으로회전시킨다.
RL 회전: A부터N까지의경로상의노드들을오른쪽-왼쪽으로회전시킨다.
A
B
T1
T2
T3
A
B
T1
T2
T3
B
A
T2
T3
T1
일반적인LL 회전
A
T4
B
C
T2
T3
T1
A
T4
B
C
T2
T3
T1
삽입
LL 회전
A
T4
C
B
T2
T1
T3
RR 회전
C
B
A
T2
T1
T3
T4