์๋ ํ์ธ์ Foma ๐ป ์ ๋๋ค!
์ ๋ฒ ์๊ฐ์ AVL ํธ๋ฆฌ๊ฐ ๋ญ์ง ์ด๋ก ์ ๋ํด ์์๋ณด์๋๋ฐ์.
(ํน์ ์๋ณด์ ๋ถ๋ค์ ์ฌ๊ธฐ ์์ ํ์ธํด์ฃผ์ธ์!)
์ค๋์ AVL ํธ๋ฆฌ๋ฅผ ์ง์ ๊ตฌํํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
AVLNode
๊ธฐ๋ณธ์ ์ผ๋ก ์ด์งํ์ํธ๋ฆฌ์ ๋ ธ๋์ ๋๊ฐ์ง๋ง ์ผ์ชฝ๊ณผ,์ค๋ฅธ์ชฝ ์์์ ๋์ด์ ๋ฐธ๋ฐ์ค ํฉํฐ๋ฅผ ์ธก์ ํ ๋ณ์๋ฅผ ๋ฐ๋ก
๋ง๋ค์ด์์ต๋๋ค.
class AVLNode<T:Comparable> {
var value:T
var leftChild:AVLNode?
var rightChild:AVLNode?
var height:Int = 0
var leftHeight:Int {
return leftChild?.height ?? -1
}
var rightHeight:Int {
return rightChild?.height ?? -1
}
var balanceFactor:Int {
return leftHeight - rightHeight
}
init(value:T) {
self.value = value
}
}
extension AVLNode {
var min: AVLNode {
return leftChild?.min ?? self
}
}
Balance
๊ท ํ์ธ์ง ์๋์ง๋ฅผ ์ฒดํฌํ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
์ ๋๊ฐ์ด 2์ธ์ง ์๋์ง๋ฅผ ์ฒดํฌํด์ค๋๋ค.
private func isBalanced(_ node: AVLNode<T>) -> Bool {
return abs(node.balanceFactor) != 2
}
๋ง์ฝ ๊ท ํ์ด ์กํ์ง ์์๋ค๋ฉด ๊ท ํ์ ์ก์์ค์ผ๊ฒ ์ฃ ?
๋ฐธ๋ฐ์คํฉํฐ๊ฐ 2๋ผ๋ฉด ์ผ์ชฝ์ผ๋ก ์น์ฐ์ณ์ง ๊ฒ์ด๊ณ -2๋ผ๋ฉด ์ค๋ฅธ์ชฝ์ผ๋ก ์น์ฐ์ณ์ง ๊ฒ์ด๋ฏ๋ก
๋ฐธ๋ฐ์ค ํฉํฐ์ ๋ง๊ฒ ๊ท ํ์ ๋ง์ถฐ์ค๋๋ค.
private func makeBalanced(_ node: AVLNode<T>) -> AVLNode<T> {
if node.balanceFactor == 2 {
return leftBalanced(node)
}else {
return rightBalanced(node)
}
}
์ผ์ชฝ์ผ๋ก ์น์ฐ์ณ ์๋ ๊ฒฝ์ฐ ์ผ์ชฝ ์์์ ๋ฐธ๋ฐ์ค ํฉํฐ๊ฐ -1์ด๋ผ๋ฉด ์ค๋ฅธ์ชฝ์ ์์์ด ์๋ ๊ฒ์ด๋ฏ๋ก
์ผ์ชฝ์ผ๋ก ํ์ ์ ํ๊ณ ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค๋๋ค.
๊ทธ๊ฒ ์๋๋ผ๋ฉด ๊ทธ๋ฅ ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค๋๋ค.
private func leftBalanced(_ node: AVLNode<T>) -> AVLNode<T> {
if let leftChild = node.leftChild, leftChild.balanceFactor == -1 {
return leftRightRotate(node)
}else {
return rightRotate(node)
}
}
์ค๋ฅธ์ชฝ์ผ๋ก ์น์ฐ์ณ ์๋ ๊ฒฝ์ฐ ์ค๋ฅธ์ชฝ ์์์ ๋ฐธ๋ฐ์ค ํฉํฐ๊ฐ 1์ด๋ผ๋ฉด ์ผ์ชฝ์ ์์์ด ์๋ ๊ฒ์ด๋ฏ๋ก
์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ์ ํ๊ณ ์ผ์ชฝ์ผ๋ก ํ์ ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค๋๋ค.
๊ทธ๊ฒ ์๋๋ผ๋ฉด ๊ทธ๋ฅ ์ผ์ชฝ์ผ๋ก ํ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค๋๋ค.
private func rightBalanced(_ node: AVLNode<T>) -> AVLNode<T> {
if let rightChild = node.rightChild, rightChild.balanceFactor == 1 {
return rightLeftRotate(node)
}else {
return leftRotate(node)
}
}
Rotate
Right
์ผ์ชฝ์ผ๋ก ์น์ฐ์ณ์ ธ ์๋ ๊ฒฝ์ฐ๋ ์๋์ ๊ฐ์ด ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค์ผ ํฉ๋๋ค.
ํ์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ค์๊ฐ์ ์ค๋ฅธ์ชฝ ์์์ผ๋ก ๋ง๋ญ๋๋ค.
์ค์๊ฐ์ ๋ ๋ฒ์งธ ๊ฐ์ด๋ฏ๋ก ์ฒซ ๋ฒ์งธ ๋ ธ๋์ ์ผ์ชฝ ์์์ด ๋๊ฒ ์ฃ ?
๊ท ํ์ ๋ง์ถฐ์คฌ์ผ๋ ๋ ธ๋์ ๋์ด๋ฅผ ์กฐ์ ํด์ค๋๋ค.
private func rightRotate(_ node: AVLNode<T>) -> AVLNode<T> {
let middle = node.leftChild!
node.leftChild = middle.rightChild
middle.rightChild = node
node.height = max(node.leftHeight, node.rightHeight) + 1
middle.height = max(middle.leftHeight, middle.rightHeight) + 1
return middle
}
Left
์ค๋ฅธ์ชฝ์ผ๋ก ์น์ฐ์ณ ์๋ ๊ฒฝ์ฐ๋ ์๋์ ๊ฐ์ด ์ผ์ชฝ์ผ๋ก ํ์ ํด์ ๊ท ํ์ ๋ง์ถฐ์ค์ผ ํฉ๋๋ค.
ํ์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ค์๊ฐ์ ์ผ์ชฝ ์์์ผ๋ก ๋ง๋ญ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํ์ ๋์ ๋์ผํ๊ฒ ๋ง๋ค์ด์ค๋๋ค.
private func leftRotate(_ node: AVLNode<T>) -> AVLNode<T>{
let middle = node.rightChild!
node.rightChild = middle.leftChild
middle.leftChild = node
node.height = max(node.leftHeight, node.rightHeight) + 1
middle.height = max(middle.leftHeight, middle.rightHeight) + 1
return middle
}
Right-Left
์๋ ์ฒซ ๋ฒ์งธ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ">" ๋ฅผ ํ์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ ๋จผ์ ๋ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํด์ค ๋ค
์ผ์ชฝ์ผ๋ก ํ์ ํด์ค๋๋ค.
์ค๋ฅธ์ชฝ ์์์ ๊ธฐ์ค์ผ๋ก ์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํด์ค ๋ค ์ผ์ชฝ์ผ๋ก ํ์ ํด์ค๋๋ค.
private func rightLeftRotate(_ node: AVLNode<T>) -> AVLNode<T> {
node.rightChild = rightRotate(node.rightChild!)
return leftRotate(node)
}
Left-Right
Right-Left์ ๋์ผํ๊ฒ "<" ๋ฅผ ํ์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ ๋จผ์ ๋ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ๋ ธ๋๋ฅผ ์ผ์ชฝ์ผ๋ก ํ์ ํด์ค ๋ค
์ค๋ฅธ์ชฝ์ผ๋ก ํ์ ํด์ค๋๋ค.
private func leftRightRotate(_ node: AVLNode<T>) -> AVLNode<T> {
node.leftChild = leftRotate(node.leftChild!)
return rightRotate(node)
}
Insert
์ฝ์ ์ ํ ๋ ์ฌ๊ท๋ฅผ ์ด์ฉํด์ ๊ท ํ์ด ๋ง๋์ง ์๋์ง ํ์ธ์ ํด์ค๋๋ค.
public mutating func insert(value: T) {
root = insert(from: root, value: value)
}
private func insert(from node: AVLNode<T>?, value: T) -> AVLNode<T> {
guard var node = node else {
return AVLNode(value: value)
}
if value < node.value {
node.leftChild = insert(from: node.leftChild, value: value)
} else {
node.rightChild = insert(from: node.rightChild, value: value)
}
if !isBalanced(node) {
node = makeBalanced(node)
}
node.height = max(node.leftHeight, node.rightHeight) + 1
return node
}
Remove
์ฝ์ ๊ณผ ๋์ผํ๊ฒ ์ฌ๊ท๋ฅผ ์ด์ฉํด ๊ท ํ์ด ๋ง๋์ง ์๋์ง ํ์ธํฉ๋๋ค.
public mutating func remove(_ value: T) {
root = remove(node: root, value: value)
}
private func remove(node: AVLNode<T>?, value: T) -> AVLNode<T>? {
guard var node = node else {
return nil
}
if value == node.value {
if node.leftChild == nil && node.rightChild == nil {
return nil
}
if node.leftChild == nil {
return node.rightChild
}
if node.rightChild == nil {
return node.leftChild
}
node.value = node.rightChild!.min.value
node.rightChild = remove(node: node.rightChild, value: node.value)
} else if value < node.value {
node.leftChild = remove(node: node.leftChild, value: value)
} else {
node.rightChild = remove(node: node.rightChild, value: value)
}
if !isBalanced(node) {
node = makeBalanced(node)
}
node.height = max(node.leftHeight, node.rightHeight) + 1
return node
}
Test
7,4,3,2,5,8,10,11,9 ์์ผ๋ก ์ซ์๋ฅผ ์ฝ์ ํ๊ณ ์ถ๋ ฅ์ ํ๋ฉด ๊ท ํ์ด ์กํ ํธ๋ฆฌ๊ฐ ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
var avl = AVLTree<Int>()
avl.insert(value: 7)
avl.insert(value: 4)
avl.insert(value: 3)
avl.insert(value: 2)
avl.insert(value: 5)
avl.insert(value: 8)
avl.insert(value: 10)
avl.insert(value: 11)
avl.insert(value: 9)
// 4
// 3 8
// 2 7 10
// 5 9 11
์์์ 8์ ์ญ์ ํ๊ณ ์ถ๋ ฅ์ ํด๋ ์ ์์ ์ผ๋ก ๊ท ํ์กํ ํธ๋ฆฌ๊ฐ ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
avl.remove(8)
// 4
// 3 9
// 2 7 10
// 5 11
Reference
'๐ฅ Computer Science > Data Structure' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Data Structure] Trie๋? (feat. ์ด๋ก ) (0) | 2022.07.29 |
---|---|
[Data Structure] B-Tree๋? (0) | 2021.12.06 |
[Data Structure] AVL(Adelson-Velsky and Landis) ํธ๋ฆฌ๋? (0) | 2021.12.01 |
[Data Structure] ์ด์ง ํ์ ํธ๋ฆฌ(Binary Search Tree) ๊ตฌํํด๋ณด๊ธฐ (feat.Swift) (0) | 2021.11.18 |
[Data Structure] ์ด์ง ํ์ ํธ๋ฆฌ(Binary Search Tree)๋? (0) | 2021.11.17 |
๋๊ธ