Skip to content

Instantly share code, notes, and snippets.

@Fiser12
Created April 11, 2023 23:10
Show Gist options
  • Save Fiser12/5c47256d3b2e5e1f6a039dfc282be4db to your computer and use it in GitHub Desktop.
Save Fiser12/5c47256d3b2e5e1f6a039dfc282be4db to your computer and use it in GitHub Desktop.
AVLTree in swift for store data in a efficient way
final class AVLTree<Element: Comparable> {
private var value: Element?
private var left: AVLTree<Element>?
private var right: AVLTree<Element>?
private var balanceFactor: Int8 = 0
private var height: Int
init() {
height = (value == nil) ? 0 : 1
}
private init(element: Element?) {
self.value = element
height = (element == nil) ? 0 : 1
}
func contains(_ element: Element) -> Bool {
guard let value = self.value else { return false }
if value == element {
return true
} else if element < value {
return left?.contains(element) ?? false
} else {
return right?.contains(element) ?? false
}
}
@discardableResult
func insert(_ element: Element) -> Bool {
guard let value = self.value else {
self.value = element
return false
}
var rebalanced = false
if element < value {
rebalanced = insert(element, into: &left)
} else {
rebalanced = insert(element, into: &right)
}
if !rebalanced {
updateBalanceAndHeight()
rebalanced = rebalanceIfNeeded()
}
return rebalanced
}
private func insert(_ element: Element, into child: inout AVLTree<Element>?) -> Bool {
if let child = child {
return child.insert(element)
} else {
child = AVLTree(element: element)
return false
}
}
private func rebalanceIfNeeded() -> Bool {
if balanceFactor > 1 {
if left!.balanceFactor > 0 {
rotateRight()
} else {
doubleRotateLeftRight()
}
return true
} else if balanceFactor < -1 {
if right!.balanceFactor < 0 {
rotateLeft()
} else {
doubleRotateRightLeft()
}
return true
}
return false
}
private func rotateLeft() {
let oldRight = right!
let newParent = AVLTree(element: value)
newParent.left = left
newParent.right = oldRight.left
left = newParent
right = oldRight.right
value = oldRight.value
}
private func rotateRight() {
let oldLeft = left!
let newParent = AVLTree(element: value)
newParent.left = oldLeft.right
newParent.right = right
left = oldLeft.left
right = newParent
value = oldLeft.value
}
private func doubleRotateLeftRight() {
left?.rotateLeft()
rotateRight()
}
private func doubleRotateRightLeft() {
right!.rotateRight()
rotateLeft()
}
private func updateBalanceAndHeight() {
let leftHeight = left?.height ?? 0
let rightHeight = right?.height ?? 0
balanceFactor = Int8(leftHeight - rightHeight)
height = max(leftHeight, rightHeight) + 1
}
}
//Example of how to make a find
extension AVLTree where Element == Empleado {
func find(by name: String) -> Empleado? {
guard let value else { return nil }
if value.firstName == name {
return value
} else if name < value.firstName {
return left?.find(by: name)
} else {
return right?.find(by: name)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment