import Foundation
public class BinaryNode<Element> {
public var value: Element
public var leftChild: BinaryNode?
public var rightChild: BinaryNode?
public init(value: Element) {
self.value = value
}
}
extension BinaryNode: CustomStringConvertible {
public var description: String {
diagram(for: self)
}
private func diagram(
for node: BinaryNode?,
_ 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 BinarySearchTree<Element: Comparable> {
public private(set) var root: BinaryNode<Element>?
public init() { }
}
extension BinarySearchTree: CustomStringConvertible {
public var description: String {
guard let root = root else { return "empty tree" }
return String(describing: root)
}
}
extension BinarySearchTree {
public mutating func insert(_ value: Element) {
root = insert(from: root, value: value)
}
private func insert(from node: BinaryNode<Element>?, value: Element) -> BinaryNode<Element> {
guard let node = node else {
return BinaryNode(value: value)
}
if value < node.value {
node.leftChild = insert(from: node.leftChild, value: value)
} else {
node.rightChild = insert(from: node.rightChild, value: value)
}
return node
}
}
extension BinarySearchTree {
public func contains(_ value: Element) -> Bool {
var current = root
while let node = current {
if node.value = value {
return true
}
if value < node.value {
current = node.leftChild
} else {
current = node.rightChild
}
}
return false
}
}
private extension BinaryNode {
var min: BinaryNode {
leftChild?.min ?? self
}
}
extension BinarySearchTree {
public mutating func remove(_ value: Element) {
root = remove(node: root, value: value)
}
private func remove(node: BinaryNode<Element>?, value: Element) -> BinaryNode<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)
}
return node
}
}
extension BinaryNode where Element: Comparable {
var isBinarySearchTree: Bool {
isBST(self, min: nil, max: nil)
}
private func isBST(_ tree: BinaryNode<Element>?, min: Element?, max: Element? ) -> Bool {
guard let tree = tree else {
return true
}
// tree 오른쪽 비교
if let min = min, tree.value <= min {
return false
// tree 왼쪽 비교
} else if let max = max, tree.value > max {
return false
}
return isBST(tree.leftChild, min: min, max: tree.value) && isBST(tree.rightChild, min: tree.value, max: max)
}
}
extension BinarySearchTree: Equatable {
public static func == (lhs: BinarySearchTree, rhs: BinarySearchTree) -> Bool {
isEqual(lhs.root, rhs.root)
}
private static func isEqual<Element: Equatable>( _ node1: BinaryNode<Element>?, _ node2: BinaryNode<Element>?) -> Bool {
guard let node1 = node1, let node2 = node2 else {
return node1 == nil && node2 == nil
}
return node1.value == node2.value && isEqual(node1.leftChild, node2.leftChild) && isEqual(node1.rightChild, node2.rightChild)
}
}
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다