Guest User

Untitled

a guest
Jul 27th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.44 KB | None | 0 0
  1. /**
  2. * D Holbrook
  3. *
  4. * Code Club: PO1
  5. *
  6. * (*) Define a binary tree data structure and related fundamental operations.
  7. *
  8. * Use whichever language features are the best fit (this will depend on the language you have selected). The following operations should be supported:
  9. *
  10. * Constructors
  11. * (bitree data left right) - Should return a binary tree containing data and the left and right children.
  12. * Accessors
  13. * (bitree-data t) - Should return the data contained by the tree.
  14. * (bitree-left t) - Should return the left child of the tree.
  15. * (bitree-right t) - Should return the right child of the tree.
  16. * Predicates
  17. * (bitree-leaf? t) - Should return true if the tree is a leaf (has null left and right children), false otherwise
  18. */
  19. trait Tree[+A] {
  20.  
  21. import scala.annotation.tailrec
  22.  
  23. def value: Option[A] = this match {
  24. case n: Node[A] => Some(n.v)
  25. case l: Leaf[A] => Some(l.v)
  26. case Empty => None
  27. }
  28.  
  29. def left: Option[Tree[A]] = this match {
  30. case n: Node[A] => Some(n.l)
  31. case l: Leaf[A] => None
  32. case Empty => None
  33. }
  34.  
  35. def right: Option[Tree[A]] = this match {
  36. case n: Node[A] => Some(n.r)
  37. case l: Leaf[A] => None
  38. case Empty => None
  39. }
  40.  
  41. /**
  42. * Represents a deferred evaluation of a node value
  43. */
  44. private case class Eval[A](v: A) extends Tree[A]
  45.  
  46. /**
  47. * represents common functionality of all traversal order folds
  48. */
  49. @tailrec
  50. private def foldLoop[A, B](a: List[Tree[A]], z: B)(f: (B, A) => B)(o: (Node[A], List[Tree[A]]) => List[Tree[A]]): B = a match {
  51. case (n: Node[A]) :: tl => foldLoop(o(n, tl), z)(f)(o) // never directly evaluate nodes, function o will create new accumulator
  52. case (l: Leaf[A]) :: tl => foldLoop(tl, f(z, l.v))(f)(o) // always evaluate Leaf
  53. case (e: Eval[A]) :: tl => foldLoop(tl, f(z, e.v))(f)(o) // always evaluate Eval
  54. case Empty :: tl => foldLoop(tl, z)(f)(o) // ignore Empty
  55. case _ => z // will be Nil (empty list)
  56. }
  57.  
  58. /**
  59. * fold with preorder traversal (root, left, right)
  60. * Tail Recursive Optimized
  61. *
  62. * F
  63. * / \
  64. * B G
  65. * / \ \
  66. * A D I
  67. * / \ /
  68. * C E H
  69. *
  70. * head evaluate accumulator
  71. * ---- -------- -----------
  72. * | (F)
  73. * F | () | F::B::G::()
  74. * F | (F) | (B,G)
  75. * B | () | B::A::D::(G)
  76. * B | (B) | (A,D,G)
  77. * A | (A) | (D,G)
  78. * D | () | D::C::E::(G)
  79. * D | (D) | (C,E,G)
  80. * C | (C) | (E,G)
  81. * E | (E) | (G)
  82. * G | () | G::I::()
  83. * G | (G) | (I)
  84. * I | () | I::H::()
  85. * I | (I) | (H)
  86. * H | (H) | ()
  87. *
  88. * result
  89. * F, B, A, D, C, E, G, I, H
  90. */
  91. def foldPreorder[B](z: B)(f: (B, A) => B): B = {
  92. foldLoop(List(this), z)(f) { (n, tl) => Eval(n.v) :: n.l :: n.r :: tl }
  93. }
  94.  
  95. /**
  96. * fold with inorder traversal (left, root, right)
  97. * tail recursive optimized
  98. *
  99. * F
  100. * / \
  101. * B G
  102. * / \ \
  103. * A D I
  104. * / \ /
  105. * C E H
  106. *
  107. * head evaluate accumulator
  108. * ---- -------- -----------
  109. * | (F)
  110. * F | () | B::F::G::()
  111. * B | () | A::B::D::(F,G)
  112. * A | (A) | (B,D,F,G)
  113. * B | (B) | (D,F,G)
  114. * D | () | C::D::E::(F,G)
  115. * C | (C) | (D,E,F,G)
  116. * D | (D) | (E,F,G)
  117. * E | (E) | (F,G)
  118. * F | (F) | (G)
  119. * G | () | G::I::()
  120. * G | (G) | (I)
  121. * I | () | H::I::()
  122. * H | (H) | H
  123. * I | (I) | ()
  124. *
  125. * result
  126. * A,B,C,D,E,F,G,H,I
  127. */
  128. def foldInorder[B](z: B)(f: (B, A) => B): B = {
  129. foldLoop(List(this), z)(f) { (n, tl) => n.l :: Eval(n.v) :: n.r :: tl }
  130. }
  131.  
  132. /**
  133. * fold with postorder traversal (left, right, root)
  134. * tail recursive optimized
  135. *
  136. * F
  137. * / \
  138. * B G
  139. * / \ \
  140. * A D I
  141. * / \ /
  142. * C E H
  143. *
  144. * head evaluate accumulator
  145. * ---- -------- -----------
  146. * | (F)
  147. * F | () | B::G::F::()
  148. * B | () | A::D::(B,G,F)
  149. * A | (A) | (D,B,G,F)
  150. * D | () | C::E::D::(B,G,F)
  151. * C | (C) | (E,D,B,G,F)
  152. * E | (E) | (D,B,G,F)
  153. * D | (D) | (B,G,F)
  154. * B | (B) | (G,F)
  155. * G | () | I::G::(F)
  156. * I | () | H::I::(G,F)
  157. * H | (H) | (I,G,F)
  158. * I | (I) | (G,F)
  159. * G | (G) | (F)
  160. * F | (F) | ()
  161. *
  162. * result
  163. * A,C,E,D,B,H,I,G,F
  164. */
  165. def foldPostorder[B](z: B)(f: (B, A) => B): B = {
  166. foldLoop(List(this), z)(f) { (n, tl) => n.l :: n.r :: Eval(n.v) :: tl }
  167. }
  168.  
  169. /**
  170. * fold with levelorder traversal
  171. * tail recursive optimized
  172. *
  173. * F
  174. * / \
  175. * B G
  176. * / \ \
  177. * A D I
  178. * / \ /
  179. * C E H
  180. *
  181. * head evaluate accumulator
  182. * ---- -------- -----------
  183. * | (F)
  184. * F | () | (F::()) ::: (B,G)
  185. * F | (F) | (B,G)
  186. * B | () | (B::(G)) ::: (A,D)
  187. * B | (B) | (G,A,D)
  188. * G | () | (G::(A,D)) ::: (I)
  189. * G | (G) | (A,D,I)
  190. * A | (A) | (D,I)
  191. * D | () | (D::(I)) ::: (C,E)
  192. * D | (D) | (I,C,E)
  193. * I | () | (I::(C,E)) ::: (H)
  194. * I | (I) | (C,E,H)
  195. * C | (C) | (E,H)
  196. * E | (E) | (H)
  197. * H | (H) | ()
  198. *
  199. * result
  200. * F, B, G, A, D, I, C, E, H
  201. */
  202. def foldLevelorder[B](z: B)(f: (B, A) => B): B = {
  203. foldLoop(List(this), z)(f) { (n, tl) => (Eval(n.v) :: tl) ::: List(n.l, n.r) }
  204. }
  205.  
  206. /**
  207. * calls foldInorder
  208. */
  209. def fold[B](z: B)(f: (B, A) => B): B = foldInorder(z)(f)
  210.  
  211. /**
  212. * P02
  213. * (*) Count the number of nodes in a binary tree.
  214. */
  215. def size: Int = fold(0) { (sum, v) => sum + 1 }
  216.  
  217. /**
  218. * P03
  219. * (*) Determine the height of a binary tree.
  220. * Definition: The height of a tree is the length of the path from the root to the deepest node in the tree. A (rooted) tree with only one node (the root) has a height of zero.
  221. */
  222. def height: Int = {
  223. def loop(t: Tree[A]): Int = t match {
  224. case l: Leaf[A] => 1
  225. case n: Node[A] => Seq(loop(n.left.get), loop(n.right.get)).max + 1
  226. case _ => 0
  227. }
  228. loop(this) - 1
  229. }
  230.  
  231. /**
  232. * P04
  233. * (*) Count the number of leaves in a binary tree.
  234. */
  235. def leafCount: Int = {
  236. @tailrec
  237. def loop(t: List[Tree[A]], z: Int): Int = t match {
  238. case (l: Leaf[A]) :: tl => loop(tl, z + 1)
  239. case (n: Node[A]) :: tl => loop(n.left.get :: n.right.get :: tl, z)
  240. case _ :: tl => loop(tl, z)
  241. case _ => z
  242. }
  243. loop(List(this), 0)
  244. }
  245.  
  246. def toSeq: Seq[A] = fold(List[A]()) { (l, v) => v :: l } reverse
  247.  
  248. def toSeqPreorder: Seq[A] = foldPreorder(List[A]()) { (l, v) => v :: l } reverse
  249. def toSeqInorder: Seq[A] = foldInorder(List[A]()) { (l, v) => v :: l } reverse
  250. def toSeqPostorder: Seq[A] = foldPostorder(List[A]()) { (l, v) => v :: l } reverse
  251. def toSeqLevelorder: Seq[A] = foldLevelorder(List[A]()) { (l, v) => v :: l } reverse
  252.  
  253. /**
  254. * P05
  255. * (**) Find the last element in a binary tree using pre/in/post/level order traversals.
  256. * Note: This is S-99 problem P01 converted from lists to binary trees.
  257. */
  258. def lastPreorder = toSeqPreorder.last
  259. def lastInorder = toSeqInorder.last
  260. def lastPostorder = toSeqPostorder.last
  261. def lastLevelorder = toSeqLevelorder.last
  262.  
  263. /**
  264. * P06
  265. * (**) Find the last but one element in a binary tree using pre/in/post/level order traversals.
  266. * Note: This is S-99 problem P02 converted from lists to binary trees.
  267. */
  268. def penultimatePreorder = toSeqPreorder.dropRight(1).last
  269. def penultimateInorder = toSeqInorder.dropRight(1).last
  270. def penultimatePostorder = toSeqPostorder.dropRight(1).last
  271. def penultimateLevelorder = toSeqLevelorder.dropRight(1).last
  272.  
  273. /**
  274. * P07
  275. * (**) Find the Nth element in a binary tree using pre/in/post/level order traversals.
  276. * By convention, the first element in the tree is element 0.
  277. *
  278. */
  279. def nthPreorder(n: Int) = toSeqPreorder(n)
  280. def nthInorder(n: Int) = toSeqInorder(n)
  281. def nthPostorder(n: Int) = toSeqPostorder(n)
  282. def nthLevelorder(n: Int) = toSeqLevelorder(n)
  283.  
  284. }
  285.  
  286. case class Node[A](v: A, l: Tree[A], r: Tree[A]) extends Tree[A]
  287. case class Leaf[A](v: A) extends Tree[A]
  288. case object Empty extends Tree[Nothing]
  289.  
  290. object Run extends App {
  291. val t: Tree[Symbol] = Node('F, Node('B, Leaf('A), Node('D, Leaf('C), Leaf('E))), Node('G, Empty, Node('I, Leaf('H), Empty)))
  292. println("tree: " + t)
  293.  
  294. //print the value of b node navigating from root
  295. for {
  296. b <- t.left
  297. value <- b.value
  298. } println("B node: " + value)
  299.  
  300. //print the value of e node navigating from root
  301. for {
  302. b <- t.left
  303. d <- b.right
  304. value <- d.value
  305. } println("D node: " + value)
  306.  
  307. //no println() is executed for empty node chain
  308. for {
  309. b <- t.left
  310. d <- b.right
  311. e <- d.right
  312. x <- e.right
  313. value <- x.value
  314. } println("X node SHOUL NOT PRINT!: " + value)
  315.  
  316. println("as seq: " + t.toSeq)
  317.  
  318. println("count: " + t.size)
  319. assert(t.size == 9)
  320.  
  321. println("height: " + t.height)
  322. assert(t.height == 3)
  323.  
  324. println("leaft count: " + t.leafCount)
  325. assert(t.leafCount == 4)
  326.  
  327. println("as seqPreorder: " + t.toSeqPreorder)
  328. println("as seqInorder: " + t.toSeqInorder)
  329. println("as seqPostorder: " + t.toSeqPostorder)
  330. println("as seqLevelorder: " + t.toSeqLevelorder)
  331.  
  332. println("last preorder :" + t.lastPreorder)
  333. println("last inorder :" + t.lastInorder)
  334. println("last postorder :" + t.lastPostorder)
  335. println("last levelorder: " + t.lastLevelorder)
  336.  
  337. println("nth preorder 5 : " + t.nthPreorder(5))
  338. println("nth inorder 5 : " + t.nthInorder(5))
  339. println("nth postorder 5 : " + t.nthPostorder(5))
  340. println("nth levelorder 5 : " + t.nthLevelorder(5))
  341.  
  342. //
  343. /**
  344. * **** output *********
  345. *
  346. * tree: Node('F,Node('B,Leaf('A),Node('D,Leaf('C),Leaf('E))),Node('G,Empty,Node('I,Leaf('H),Empty)))
  347. * B node: 'B
  348. * D node: 'D
  349. * as seq: List('A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'I)
  350. * count: 9
  351. * height: 3
  352. * leaft count: 4
  353. * as seqPreorder: List('F, 'B, 'A, 'D, 'C, 'E, 'G, 'I, 'H)
  354. * as seqInorder: List('A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'I)
  355. * as seqPostorder: List('A, 'C, 'E, 'D, 'B, 'H, 'I, 'G, 'F)
  356. * as seqLevelorder: List('F, 'B, 'G, 'A, 'D, 'I, 'C, 'E, 'H)
  357. * last preorder :'H
  358. * last inorder :'I
  359. * last postorder :'F
  360. * last levelorder: List('F, 'B, 'G, 'A, 'D, 'I, 'C, 'E, 'H)
  361. * nth preorder 5 : 'C
  362. * nth inorder 5 : 'E
  363. * nth postorder 5 : 'B
  364. * nth levelorder 5 : 'D
  365. *
  366. * ***********************
  367. */
  368.  
  369. }
Add Comment
Please, Sign In to add comment