> AVL Tree
> Unbalanced Tree
public class AVLNode<Element> {
public var value: Element
public var leftChild: AVLNode?
public var rightChlid: AVLNode?
// root가 가장 높음, 기본값을 0으로 반영하고 child가 생기면
// child의 root node height을 변경해주는 방식
public var height = 0
/// 2 or -2 이상일 경우 unbalanced tree
/// 최초 child가 없으면 0
/// left child가 생겼을 시 1
/// right child가 생겼을 시 -1
/// 즉, right 쪽으로 계속 추가될 시 balanceFactor는 음수
//// left 쪽으로 계속 추가될 시 balanceFactor는 양수
public var balanceFactor: Int {
leftHeight - rightHeight
}
public var leftHeight: Int {
leftChild?.height ?? -1
}
public var rightHeight: Int {
rightChild?.height ?? -1
}
public init(value: Element) {
self.value = value
}
}
extension AVLNode: CustomStringConvertible {
public var description: String {
diagram(for: self)
}
private func diagram(for node: AVLNode?,
_ top: String = "",
_ root: String = "",
_ bottom: String = "") -> String {
guard let node = node else {
return root + "nil\n"
}
if node.leftChild == nil && node.rightChild == nil {
return root + "\(node.value)\n"
}
return diagram(for: node.rightChild, top + " ", top + "┌──", top + "│ ")
+ root + "\(node.value)\n"
+ diagram(for: node.leftChild, bottom + "│ ", bottom + "└──", bottom + " ")
}
}
public struct AVLTree<Element: Comparable> {
public private(set) var root: AVLNode<Element>?
public init() { }
}
extension AVLTree: CustomStringConvertible {
public var description: String {
guard let root = root else { return "Empty Tree"}
return String(describing : root)
}
}
유형 | 설명 | 방식 |
---|---|---|
RR Problem | 노드 N이 A의 오른쪽 서브 트리의 오른쪽 서브 트리에 삽입되는 경우 | A를 기준으로 한번의 반 시계 방향 회전 |
LL Problem | 노드 N이 A의 읜쪽 서브 트리의 왼쪽 서브 트리에 삽입되는 경우 | A를 기준으로 한번의 시계 방향 회전 |
RL Problem | 노드 N이 A의 오른쪽 서브 트리의 왼쪽 서브 트리에 삽입되는 경우 | A의 오른쪽 자식을 기준으로 시계 방향 회전 후 A를 기준으로 반시계 방향 회전 |
LR Problem | 노드 N이 A의 왼쪽 서브 트리의 오른쪽 서브 트리에 삽입되는 경우 | A의 왼쪽 자식을 기준으로 반시계 방향 회전 후 A를 기준으로 시계 방향 회전 |
extension AVLTree {
private func leftRotate(_ node: AVLNode<Element>) -> AVLNode<Element> {
let pivot = node.rightChild!
node.rightChild = pivot.leftChild
pivot.leftChild = node
node.height = max(node.leftHeight, node.rightHeight) + 1
pivot.height = max(pivot.leftHeight, pivot.rightHeight) + 1
return pivot
}
}
extension AVLTree {
private func rightRotate(_ node: AVLNode<Element>) -> AVLNode<Element> {
let pivot = node.leftChild!
node.leftChild = pivot.rightChild
pivot.rightChild = node
node.height = max(node.leftHeight, node.rightHeight) + 1
pivot.height = max(pivot.leftHeight, pivot.rightHeight) + 1
return pivot
}
}
extension AVLTree {
private func rightLeftRotate(_ node: AVLNode<Element>) -> AVLNode<Element> {
guard let rightChild = node.rightChild else {
return node
}
node.rightChild = rightRotate(rightChild)
return leftRotate(node)
}
}
extension AVLTree {
private func leftRightRotate(_ node: AVLNode<Element>) -> AVLNode<Element> {
guard let leftChild = node.leftChild else {
return node
}
node.leftChild = leftRotate(leftChild)
return rightRotate(node)
}
}
private func balanced(_ node: AVLNode<Element>) -> AVLNode<Element> {
switch node.balanceFactor {
case 2:
if let leftChild = node.leftChild, leftChild.balanceFactor == -1 {
return leftRightRotate(node)
} else {
return rightRotate(node)
}
case -2:
if let rightChild = node.rightChild, rightChild.balanceFactor == 1 {
return rightLeftRotate(node)
} else {
return leftRotate(node)
}
default :
return node
}
}
extension AVLTree: {
public mutating func insert(_ value: Element) {
root = insert(from: root, value: value)
}
private func insert(from node: AVLNode<Element>?, value: Element) -> AVLNode<Element> {
guard let node = node else {
return AVLNode(value: value)
}
if value < node.value {
node.leftChild = insert(from: node.leftChild, value: value)
} else {
node.rifhtChild = insert(from: node.rightChild, value: value)
}
let balanceNode = balanced(node)
balanceNode.height = max(balanceNode.leftHeight, balanceNode.rightHeight) + 1
return balanceNode
}
}
private extension AVLNode {
var min: AVLNode {
leftChild?.min ?? self
}
}
extension AVLTree {
public mutating func remove(_ value: Element) {
root = remove(node: root, value: value)
}
private func remove(node: AVLNode<Element>?, value: Element) -> AVLNode<Element>? {
guard let 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)
}
let balancedNode = balanced(node)
balancedNode.height = max(balancedNode.leftHeight, balancedNode.rightHeight) + 1
return balancedNode
}
}
var tree = AVLTree<Int>()
for i in 0..<15 {
tree.insert(i)
}
print(tree)
tree.remove(14)
print(tree)
┌──14
┌──13
│ └──12
┌──11
│ │ ┌──10
│ └──9
│ └──8
7
│ ┌──6
│ ┌──5
│ │ └──4
└──3
│ ┌──2
└──1
└──0
┌──nil
┌──13
│ └──12
┌──11
│ │ ┌──10
│ └──9
│ └──8
7
│ ┌──6
│ ┌──5
│ │ └──4
└──3
│ ┌──2
└──1
└──0
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다