tbintree.nim 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. discard """
  2. output: '''hello
  3. world
  4. 99
  5. 110
  6. 223'''
  7. """
  8. type
  9. TBinaryTree[T] = object # TBinaryTree is a generic type with
  10. # with generic param ``T``
  11. le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
  12. data: T # the data stored in a node
  13. PBinaryTree*[A] = ref TBinaryTree[A] # type that is exported
  14. proc newNode*[T](data: T): PBinaryTree[T] =
  15. # constructor for a node
  16. new(result)
  17. result.data = data
  18. proc add*[Ty](root: var PBinaryTree[Ty], n: PBinaryTree[Ty]) =
  19. # insert a node into the tree
  20. if root == nil:
  21. root = n
  22. else:
  23. var it = root
  24. while it != nil:
  25. # compare the data items; uses the generic ``cmp`` proc that works for
  26. # any type that has a ``==`` and ``<`` operator
  27. var c = cmp(n.data, it.data)
  28. if c < 0:
  29. if it.le == nil:
  30. it.le = n
  31. return
  32. it = it.le
  33. else:
  34. if it.ri == nil:
  35. it.ri = n
  36. return
  37. it = it.ri
  38. proc add*[Ty](root: var PBinaryTree[Ty], data: Ty) =
  39. # convenience proc:
  40. add(root, newNode(data))
  41. proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
  42. # for testing this needs to be recursive, so that the
  43. # instantiated type is checked for proper tyGenericInst envelopes
  44. if b == nil:
  45. result = false
  46. else:
  47. var c = cmp(data, b.data)
  48. if c < 0: result = find(b.le, data)
  49. elif c > 0: result = find(b.ri, data)
  50. else: result = true
  51. iterator preorder*[T](root: PBinaryTree[T]): T =
  52. # Preorder traversal of a binary tree.
  53. # This uses an explicit stack (which is more efficient than
  54. # a recursive iterator factory).
  55. var stack: seq[PBinaryTree[T]] = @[root]
  56. while stack.len > 0:
  57. var n = stack.pop()
  58. while n != nil:
  59. yield n.data
  60. add(stack, n.ri) # push right subtree onto the stack
  61. n = n.le # and follow the left pointer
  62. iterator items*[T](root: PBinaryTree[T]): T =
  63. ## Inorder traversal of the binary tree.
  64. var stack: seq[PBinaryTree[T]] = @[]
  65. var n = root
  66. while true:
  67. while n != nil:
  68. add(stack, n)
  69. n = n.le
  70. if stack.len > 0:
  71. n = stack.pop()
  72. yield n.data
  73. n = n.ri
  74. if stack.len == 0 and n == nil: break
  75. proc debug[T](a: PBinaryTree[T]) =
  76. if a != nil:
  77. debug(a.le)
  78. echo a.data
  79. debug(a.ri)
  80. when true:
  81. var
  82. root: PBinaryTree[string]
  83. x = newNode("hello")
  84. add(root, x)
  85. add(root, "world")
  86. if find(root, "world"):
  87. for str in items(root):
  88. echo(str)
  89. else:
  90. echo("BUG")
  91. var
  92. r2: PBinaryTree[int]
  93. add(r2, newNode(110))
  94. add(r2, 223)
  95. add(r2, 99)
  96. for y in items(r2):
  97. echo(y)