binary-tree.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. (library (binary-tree)
  2. (export <tree>
  3. make-tree
  4. make-leaf
  5. make-empty-tree
  6. make-complete-tree
  7. make-balanced-tree
  8. create-balanced-trees-pair
  9. tree?
  10. tree-empty?
  11. tree-value
  12. tree-left
  13. tree-right
  14. set-tree-left
  15. set-tree-right
  16. set-tree-value
  17. tree-leaf?
  18. tree-member?
  19. tree-insert
  20. tree-insert-using-continuation
  21. tree-insert-with-exception
  22. tree-depth
  23. tree-size
  24. tree-fold
  25. display-tree
  26. make-already-exists-exception
  27. &already-exists
  28. already-exists?)
  29. (import (except (rnrs base) error vector-map)
  30. (only (guile)
  31. lambda*
  32. λ
  33. call-with-output-string
  34. current-output-port
  35. display
  36. error
  37. even?
  38. floor
  39. record-constructor
  40. simple-format)
  41. ;; SRFI-9 for structs
  42. (srfi srfi-9 gnu)
  43. ;; let-values
  44. (srfi srfi-11)
  45. (ice-9 exceptions)
  46. (string-helpers))
  47. (define-immutable-record-type <tree>
  48. (make-tree value left right)
  49. tree?
  50. (left tree-left set-tree-left)
  51. (right tree-right set-tree-right)
  52. (value tree-value set-tree-value))
  53. (define-immutable-record-type <empty-tree>
  54. (make-empty-tree)
  55. empty-tree?)
  56. (define make-leaf
  57. (λ (val)
  58. (make-tree val
  59. (make-empty-tree)
  60. (make-empty-tree))))
  61. (define tree-empty?
  62. (λ (tree)
  63. (empty-tree? tree)))
  64. (define tree-leaf?
  65. (λ (a-tree)
  66. (and (tree-empty? (tree-left a-tree))
  67. (tree-empty? (tree-right a-tree)))))
  68. ;; tree-member? makes use of a performance trick to reduce the
  69. ;; number of comparisons needed to find out, whether a value is a
  70. ;; member or not. The trick is to keep track of a candidate element
  71. ;; which could be equal to the value that is searched and drawing
  72. ;; conclusions from comparisons with elements deeper in the tree.
  73. (define tree-member?
  74. (λ (a-tree searched-val less)
  75. (cond
  76. [(tree-empty? a-tree) #f]
  77. [else
  78. (let traverse ([tree° a-tree] [candidate° #f])
  79. (let ([node-val (tree-value tree°)])
  80. (cond
  81. [(less searched-val node-val)
  82. (let ([left (tree-left tree°)])
  83. (if (tree-empty? left)
  84. ;; Not possible to go deeper left. Compare with
  85. ;; candidate.
  86. (and candidate°
  87. (not (less candidate° searched-val)))
  88. ;; Otherwise descent left.
  89. (traverse left candidate°)))]
  90. [else
  91. (let ([right (tree-right tree°)])
  92. (cond
  93. [(tree-empty? right)
  94. ;; Not possible to go deeper right. Compare with
  95. ;; candidate.
  96. (and node-val
  97. (not (less node-val searched-val)))]
  98. [else
  99. (traverse right node-val)]))])))])))
  100. ;; The GNU Guile manual recommends to only use
  101. ;; call-with-current-continuation, when elegance warants it or no
  102. ;; other simple solution is available. Still putting it here to show
  103. ;; it.
  104. (define tree-insert-using-continuation
  105. (λ (tree insertion-value less)
  106. (call-with-current-continuation
  107. (λ (exit-cont)
  108. (cond
  109. [(tree-empty? tree) (make-leaf insertion-value)]
  110. [else
  111. (let traverse ([tree° tree])
  112. (let ([node-val (tree-value tree°)])
  113. (cond
  114. [(less insertion-value node-val)
  115. (set-tree-left tree°
  116. (tree-insert-using-continuation (tree-left tree°)
  117. insertion-value
  118. less))]
  119. [(less node-val insertion-value)
  120. (set-tree-right tree°
  121. (tree-insert-using-continuation (tree-right tree°)
  122. insertion-value
  123. less))]
  124. [else
  125. (exit-cont tree)])))])))))
  126. ;; To use an exception, we define one.
  127. (define &already-exists (make-exception-type '&already-exists &exception '()))
  128. (define already-exists? (exception-predicate &already-exists))
  129. (define make-already-exists-exception
  130. (λ (irritants)
  131. (make-exception
  132. ((record-constructor &already-exists))
  133. (make-exception-with-message "value already exists in tree")
  134. (make-exception-with-irritants irritants))))
  135. (define tree-insert
  136. (λ (tree insertion-value less)
  137. (guard (exn [(already-exists? exn) tree])
  138. (cond
  139. [(tree-empty? tree) (make-leaf insertion-value)]
  140. [else
  141. (let traverse ([tree° tree] [candidate° #f])
  142. (let ([node-val (tree-value tree°)])
  143. (cond
  144. [(less insertion-value node-val)
  145. ;; Check if left subtree is empty. If it is empty,
  146. ;; compare with the memorized candidate. If equal to
  147. ;; the candidate value, raise the exception, otherwise
  148. ;; insert as a new left subtree.
  149. (let ([left (tree-left tree°)])
  150. (cond
  151. [(tree-empty? left)
  152. (if (and candidate° (not (less candidate° insertion-value)))
  153. (raise-exception
  154. (make-already-exists-exception insertion-value))
  155. (set-tree-left tree° (make-leaf insertion-value)))]
  156. [else
  157. (traverse left candidate°)]))]
  158. [else
  159. ;; Check if the right subtree is empty. (1) If it is
  160. ;; empty, compare with the memorized candidate. If the
  161. ;; candidate is equal to the insertion value, raise
  162. ;; the exception, otherwise insert the insertion value
  163. ;; as a new right subtree. (2) If the right subtree is
  164. ;; not empty, memorize the value at the current node
  165. ;; and insert into the right subtree.
  166. (let ([right (tree-right tree°)])
  167. (cond
  168. [(tree-empty? right)
  169. (if (and candidate° (not (less candidate° insertion-value)))
  170. (raise-exception
  171. (make-already-exists-exception insertion-value))
  172. (set-tree-right tree° (make-leaf insertion-value)))]
  173. [else
  174. (traverse right node-val)]))])))]))))
  175. (define make-complete-tree
  176. (λ (fill depth)
  177. "Build a full binary tree bottom up, enabling to share
  178. already created subtrees for both, left and right, branches
  179. of each next higher level."
  180. (cond
  181. [(= depth 0) (make-empty-tree)]
  182. [else
  183. (let iter-depth ([tree° (make-leaf fill)]
  184. [depth° (- depth 1)])
  185. (cond
  186. [(= depth° 0) tree°]
  187. [else
  188. (iter-depth (make-tree fill tree° tree°)
  189. (- depth° 1))]))])))
  190. (define tree-depth
  191. (λ (tree)
  192. "Calculate the tree depth. That is, how many splits the tree
  193. has in its longest path from the root to any leaf."
  194. (cond
  195. [(tree-empty? tree) 0]
  196. [else
  197. (+ 1 (max (tree-depth (tree-left tree))
  198. (tree-depth (tree-right tree))))])))
  199. (define create-balanced-trees-pair
  200. (λ (fill size)
  201. "Make a pair of balanced trees, one tree of size SIZE and
  202. one tree of SIZE + 1. This is according to the hint in Chris
  203. Okasaki's book 'Purely Functional Data Structures'."
  204. (simple-format #t "create2 got size: ~a\n" size)
  205. (values (make-balanced-tree fill (+ size 1))
  206. (make-balanced-tree fill size))))
  207. (define make-balanced-tree
  208. (λ (fill num-nodes)
  209. "Create a balanced binary tree. Should run in O(log(n)),
  210. where n is the number of nodes."
  211. (cond
  212. [(= num-nodes 0)
  213. (make-empty-tree)]
  214. [(even? num-nodes)
  215. (let ([subtree-size (floor (/ (- num-nodes 1) 2))])
  216. (let-values ([(left-subtree right-subtree)
  217. (create-balanced-trees-pair fill subtree-size)])
  218. (make-tree fill
  219. left-subtree
  220. right-subtree)))]
  221. [else
  222. (let ([subtree-size (/ (- num-nodes 1) 2)])
  223. (let ([subtree (make-balanced-tree fill subtree-size)])
  224. (make-tree fill
  225. ;; Share equal subtrees, only do half the work.
  226. subtree
  227. subtree)))])))
  228. (define tree-size
  229. (λ (tree)
  230. (cond
  231. [(empty-tree? tree) 0]
  232. [else (+ 1
  233. (tree-size (tree-left tree))
  234. (tree-size (tree-right tree)))])))
  235. (define tree-fold
  236. (λ (reducing-func neutral-elem tree)
  237. "Fold operation over a tree. Reduce left branch, then right
  238. branch, then the parent node value."
  239. (cond
  240. [(tree-empty? tree) neutral-elem]
  241. [(tree-leaf? tree)
  242. (reducing-func (tree-value tree)
  243. neutral-elem)]
  244. [else
  245. (reducing-func (tree-value tree)
  246. (reducing-func
  247. (tree-fold reducing-func neutral-elem (tree-left tree))
  248. (tree-fold reducing-func neutral-elem (tree-right tree))))])))
  249. (define display-tree
  250. (lambda* (tree
  251. #:optional (port (current-output-port))
  252. #:key
  253. (indentation-str " ")
  254. (tree-value->string (λ (val) (simple-format #f "~s" val))))
  255. (define display-value-at-level
  256. (lambda* (val level)
  257. (simple-format
  258. port "~a\n"
  259. (string-append (string-repeat indentation-str level)
  260. (tree-value->string val)))))
  261. (let iter ([tree° tree] [level 0])
  262. (display-value-at-level (tree-value tree°) level)
  263. (cond
  264. [(tree-leaf? tree°)
  265. (display-value-at-level 'empty (+ level 1))
  266. (display-value-at-level 'empty (+ level 1))]
  267. [(tree-empty? (tree-left tree°))
  268. (display-value-at-level 'empty (+ level 1))
  269. (iter (tree-right tree°) (+ level 1))]
  270. [(tree-empty? (tree-right tree°))
  271. (iter (tree-left tree°) (+ level 1))
  272. (display-value-at-level 'empty (+ level 1))]
  273. [else
  274. (iter (tree-left tree°) (+ level 1))
  275. (iter (tree-right tree°) (+ level 1))]))))
  276. ;; TODO: implement tree-balanced?
  277. ;; TODO: tree-leaf-count
  278. )
  279. ;; (define tree-leaf-count
  280. ;; (λ (a-tree)
  281. ;; (cond
  282. ;; [(leaf? a-tree) 1]
  283. ;; [(branch-empty? (tree-left a-tree))
  284. ;; (tree-leaf-count (tree-right a-tree))]
  285. ;; [(branch-empty? (tree-right a-tree))
  286. ;; (tree-leaf-count (tree-left a-tree))]
  287. ;; [else (+ (tree-leaf-count (tree-left a-tree))
  288. ;; (tree-leaf-count (tree-right a-tree)))])))