Advertisement
Guest User

Untitled

a guest
Jun 16th, 2019
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.72 KB | None | 0 0
  1. //=== BinaryTreeNode.swift
  2.  
  3. public final class BinaryTreeNode<T>: BinaryTreeNodeProtocol {
  4. public let payload: T
  5. public let left: BinaryTreeNode<T>?
  6. public let right: BinaryTreeNode<T>?
  7.  
  8. init(
  9. _ payload: T,
  10. _ left: BinaryTreeNode<T>? = nil,
  11. _ right: BinaryTreeNode<T>? = nil
  12. ) {
  13. self.payload = payload
  14. self.left = left
  15. self.right = right
  16. }
  17. }
  18.  
  19. //=== BinaryTreeNodeProtocol.swift
  20.  
  21. public protocol BinaryTreeNodeProtocol {
  22. associatedtype Payload
  23. var payload: Payload { get }
  24. var left: Self? { get }
  25. var right: Self? { get }
  26. }
  27.  
  28. //=== BinaryPreorderIterator.swift
  29.  
  30. public extension BinaryTreeNodeProtocol {
  31. var preorderTraversal: BinaryTreePreorderSequence<Self> { return BinaryTreePreorderSequence(self) }
  32. }
  33.  
  34. public struct BinaryTreePreorderSequence<Tree: BinaryTreeNodeProtocol>: Sequence {
  35. private let tree: Tree
  36.  
  37. public init(_ tree: Tree) { self.tree = tree }
  38.  
  39. public func makeIterator() -> BinaryPreorderIterator<Tree> {
  40. return BinaryPreorderIterator(tree: self.tree)
  41. }
  42. }
  43.  
  44. public struct BinaryPreorderIterator<Tree: BinaryTreeNodeProtocol>: IteratorProtocol {
  45. private var backtrackStack: [(node: Tree, nextAction: NextAction)]
  46.  
  47. private enum NextAction { case visitRoot, visitLeft, visitRight, returnToParent }
  48.  
  49. public init(tree: Tree) {
  50. backtrackStack = [(tree, .visitRoot)]
  51. }
  52.  
  53. public mutating func next() -> Tree.Payload? {
  54. // Using a non-constant boolean expression circumvent's the compilers warnings about the value always being false.
  55. let debugPrinting = Bool("false")!
  56.  
  57. if debugPrinting { print("next()") }
  58.  
  59. while let popped = backtrackStack.last {
  60.  
  61. if debugPrinting {
  62. print("tloop - backtrackStack:")
  63. for (node, nextAction) in backtrackStack.dropLast() {
  64. print("tt| (node.payload) (nextAction)")
  65. }
  66. print("tt↳ (popped.node.payload) (popped.nextAction) <--- current staten")
  67. }
  68.  
  69. advanceState()
  70.  
  71. switch (popped.nextAction) {
  72. case .visitRoot:
  73. let returnValue = popped.node.payload
  74. if debugPrinting { print("treturning (returnValue)n") }
  75. return returnValue
  76.  
  77. case .visitLeft:
  78. // This block could be more nicely expressed as the following code,
  79. // but that doesn't work, because the second method call is unconditional,
  80. // unlike an if/else-if pair.
  81. //
  82. // tryMarkingLeftToVisitNext()
  83. // tryMarkingRightToVisitNext()
  84.  
  85. if let leftChild = lastState().node.left {
  86. self.visitNext(leftChild)
  87. }
  88. else if let rightChild = lastState().node.right {
  89. self.visitNext(rightChild)
  90. }
  91.  
  92. case .visitRight:
  93. tryMarkingRightToVisitNext()
  94.  
  95. case .returnToParent:
  96. break
  97. }
  98. }
  99.  
  100. return nil
  101. }
  102.  
  103. private func assertLastStateExists() {
  104. precondition(!backtrackStack.isEmpty, """
  105. lastState() should only be called when there IS a last state, i.e. the backtrace stack isn't empty.
  106. """)
  107. }
  108.  
  109. private func lastState() -> (node: Tree, nextAction: NextAction) {
  110. assertLastStateExists()
  111. return backtrackStack.last!
  112. }
  113.  
  114. private mutating func setNextActionOnLastNode(_ newNextAction: NextAction) {
  115. assertLastStateExists()
  116. backtrackStack[backtrackStack.count - 1].nextAction = newNextAction // gross, but Array.last is write-only
  117. }
  118.  
  119. private mutating func advanceState() {
  120. switch lastState().nextAction {
  121. case .visitRoot: setNextActionOnLastNode(.visitLeft)
  122. case .visitLeft: setNextActionOnLastNode(.visitRight)
  123. case .visitRight: setNextActionOnLastNode(.returnToParent)
  124. case .returnToParent: backtrackStack.removeLast()
  125. }
  126. }
  127.  
  128. private mutating func tryMarkingLeftToVisitNext() {
  129. if let leftChild = lastState().node.left {
  130. self.visitNext(leftChild)
  131. }
  132. }
  133.  
  134. private mutating func tryMarkingRightToVisitNext() {
  135. if let rightChild = lastState().node.right {
  136. self.visitNext(rightChild)
  137. }
  138. }
  139.  
  140. private mutating func visitNext(_ node: Tree) {
  141. backtrackStack.append((node: node, nextAction: .visitRoot))
  142. }
  143. }
  144.  
  145. func sampleTree() -> BinaryTreeNode<Int> {
  146. typealias B = BinaryTreeNode
  147.  
  148. // 4
  149. // /
  150. // 2 6
  151. // / /
  152. // 1 3 5 7
  153. return B(4, B(2, B(1), B(3)), B(6, B(5), B(7)))
  154. }
  155.  
  156. print(Array(sampleTree().preorderTraversal))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement