View
1.865
Download
2
Embed Size (px)
Citation preview
1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0
0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1
0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1
DATA STRUCTURES
@Override
public void add(Node<T> node) {
Node pointer = header;
while (pointer.next != null) {
pointer = pointer.next;}pointer.next = node;
size++;}
A
B
H
G
front
rearAVL Tree
SHOUT OUR PASSION TOGETHER DATA STRUCTURES INDEX
004
005
006
011
012
020
030
AVL - 개요
AVL - 특징
AVL - 용어
AVL - 요구사항
AVL - 코드분석
AVL - 예제
AVL - 성능분석
TABLE OF CONTENTS
035AVL - 사례
NO CONTENTStudy - Data Structures
AVL개요
각노드마다왼쪽, 오른쪽부분트리의높이차정보가있음
가장초기에나온균형잡힌 이진탐색트리
부분트리의높이차이가 1보다크지않은성질을가짐
4
1
0 2
0 3
7
5 8
6 9
Study - Data Structures
AVL특징
노드가삽입, 삭제될때회전을통해트리를재구성하여높이균형성질을유지시킨다
이진탐색트리에서의검색시간복잡도는트리의높이과같으므로 O (log n) 임을알수있다
높이균형성질로부터, n 개의원소를갖는 AVL 트리의높이는 log n 이다
삽입과삭제를할때, 원하는노드를찾기위해 2개의경로를필요로하기때문에효율이낮다
Ref. https://ko.wikipedia.org/wiki/AVL_%ED%8A%B8%EB%A6%AC
Study - Data Structures
AVL요구사항
삽입 · 삭제 : 트리에특정노드를추가하거나삭제
높이계산 : 루트부터리프노드까지의높이를계산
회전구현 : LL, RR, LR, RL
높이조절
출력을위한 Depth 지정및출력
Study - Data Structures
코드분석 - 삽입
AVL
Root Node 여부확인
중복 key 확인
자식 Node를 생성하기 위한작업
부모 key와 비교후 방향선택
public boolean insert(int key) {
if (root == null)root = new Node(null, key, null);
else {
Node<Integer> n = root;Node<Integer> parent;
while (true) {
if (n.key == key)return false;
parent = n;
boolean goLeft = parent.key > key;n = goLeft ? parent.left : parent.right;
if (n == null) {
if (goLeft) parent.left = new Node(null, key, parent);
else parent.right = new Node(null, key, parent);
rebalance(parent);break;
}}
}return true;
}
Study - Data Structures
AVL
Node 생성
코드분석 -삭제
삭제할 Node 검색
Key값비교로 방향선택
자식 Node 분리
삭제할 Node의 자식 Node를 부모 Node에 연결한다
Key값 비교로방향선택
높이조절
public void delete(int delKey) {
if (root == null)return;
Node<Integer> n = root, parent = root, child = root;Node<Integer> delNode = null;
while (child != null) {
parent = n;n = child;child = delKey >= n.key ? n.right : n.left;if (delKey == n.key)
delNode = n;}
if (delNode != null) {
delNode.key = n.key;child = n.left != null ? n.left : n.right;
if (root.key == delKey)root = child;
else {
if (parent.left == n) parent.left = child;else parent.right = child;
rebalance(parent);}
}}
Study - Data Structures
AVL
Balance 설정
양쪽높이의 차이를 -2 미만으로조절
코드분석 -높이조절
양쪽높이의 차이를 2 미만으로 조절
모든트리의 balance를맞춘다.
private void rebalance(Node n) {
setBalance(n);
if (n.balance == -2) {
if (height(n.left.left) >= height(n.left.right))n = rotateRight(n);
elsen = rotateLeftThenRight(n);
} else if (n.balance == 2) {
if (height(n.right.right) >= height(n.right.left))n = rotateLeft(n);
elsen = rotateRightThenLeft(n);
}
if (n.parent != null) rebalance(n.parent);
else root = n;
}
Study - Data Structures
AVL
임의의 b Node를 두고정보를 옮김
Node를 이동시켜 회전한다.
코드분석 -왼쪽회전
Balance를 다시맞춰준다.
최종적으로 b Node 반환
private Node rotateLeft(Node a) {
Node b = a.right;
b.parent = a.parent;a.right = b.left;
if (a.right != null)a.right.parent = a;
b.left = a;a.parent = b;
if (b.parent != null) {
if (b.parent.right == a) b.parent.right = b;
else b.parent.left = b;
}
setBalance(a, b);return b;
}
private Node rotateLeftThenRight(Node n) {
n.left = rotateLeft(n.left);return rotateRight(n);
}
LR 회전
왼쪽을먼저 회전한다음 오른쪽을회전
Study - Data Structures
AVL코드분석 -오른쪽회전
임의의 b Node를 두고정보를 옮김
Node를 이동시켜 회전한다.
Balance를 다시맞춰준다.
최종적으로 b Node 반환
private Node rotateRight(Node a) {
Node b = a.left;
b.parent = a.parent;a.left = b.right;
if (a.left != null)a.left.parent = a;
b.right = a;a.parent = b;
if (b.parent != null) {
if (b.parent.right == a)b.parent.right = b;
else b.parent.left = b;
}
setBalance(a, b);return b;
}
private Node rotateRightThenLeft(Node n) {
n.right = rotateRight(n.right);return rotateLeft(n);
}
RL 회전
오른쪽을먼저 회전한다음 왼쪽을회전
Study - Data Structures
AVL
재귀를통해 높이를계산
코드분석 -높이,밸런스,깊이계산
Balance를 계산
왼쪽과오른쪽 높이의차를 저장
Root depth를 0으로지정
Root의 왼쪽, 오른쪽 Node의 depth를 계산
N의깊이 =부모 Depth + 1로설정
Node n의왼쪽, 오른쪽 Node의 depth를 계산
private int height(Node n) {
if (n == null)return -1;
return 1 + Math.max(height(n.left), height(n.right));}
private void setBalance(Node... nodes) {
for (Node n : nodes)n.balance = height(n.right) - height(n.left);
}
public void caldep() {
root.depth = 0;
caldep(root.left);caldep(root.right);
}
private void caldep(Node n) {
if(n != null){
n.depth = n.parent.depth + 1;
caldep(n.left);caldep(n.right);
}}
Study - Data Structures
AVL
Depth 값인 max과 비교하여 Tree를출력
코드분석 - Tree 출력
Node n의 depth가 max값과같으면 출력
Node n의왼쪽, 오른쪽 Node를탐색
public void printTree(int max){
printTree(root, max);}
private void printTree(Node n, int max){
if(n != null){
if(n.depth == max)System.out.print(n.key + " ");
printTree(n.left, max);printTree(n.right, max);
}}
AVL
Insert 7 Rebalance Insert 8
1
2
3
4
5
6
7 1
2
3
4
5
6
7
5번 Node가기준RR회전
1
2
3
4
5
6
7
8
예제 - 1 ~ 10삽입
AVL
Insert 9 Rebalance Insert 10
5번 Node가기준RR회전
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10
6번 Node가기준RR회전
예제 - 1 ~ 10삽입
AVL
Rebalance Rebalance Result
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
예제 - 1 ~ 10삽입
1
2
3
4
5
6
7
8
9
10
AVL
Start Delete node 6 Result
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
7
8
9
10
6 node값을 7로변경한후오른쪽자식 Node를 7 node의자식 node로갱신한다.예제 - 6 삭제
1
2
3
4
5
7
8
9
10
AVL
Start Delete node 8 update
삭제시가장가까운값. 만약 9 node.left에값이있었다면그값이삭제되는 8 node로갱신된다.예제 - 8삭제
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
9
9
10
6
7
Study - Data Structures
AVL성능분석
Ref. https://ko.wikipedia.org/wiki/AVL_%ED%8A%B8%EB%A6%AC
메모리사용공간
연산시간
1. 균형이진트리이므로다음식이도출된다.
→ 1번검색, 삽입, 삭제에대해 h 만큼이동 : h = log₂ n
2. 검색, 삽입, 삭제에대해평균﹒최악의경우모두 O (log n)의시간복잡도를갖는다
3. 삽입과삭제시, 검색에소요되는시간 + 상수시간이걸리므로 O (log n)의시간복잡도를갖는다
평균시간복잡도
O (log n)
O (n) : n 개의원소에대하여 n 개의메모리사용