M binarysearchtree.go => binarysearchtree.go +93 -4
@@ 2,10 2,10 @@ package algorithms
type Node struct {
parent *Node
- lChild *Node
- rChild *Node
- Count int
- Value int
+ left *Node
+ right *Node
+ count int
+ value int
}
type Tree struct {
@@ 13,6 13,8 @@ type Tree struct {
size int
}
+type fn func(int)
+
func NewBST() *Tree {
return &Tree{}
}
@@ 20,3 22,90 @@ func NewBST() *Tree {
func (t *Tree) Size() int {
return t.size
}
+
+func (t *Tree) Insert(v int) {
+ var prevNode *Node
+ currNode := t.root
+
+ // Walk the tree until we find a spot to insert a new node.
+ for currNode != nil {
+ prevNode = currNode
+ switch {
+ case v < currNode.value:
+ currNode = currNode.left
+ case v > currNode.value:
+ currNode = currNode.right
+ default: // Our value is already present, so we can return early.
+ currNode.count++
+ t.size++
+ return
+ }
+ }
+
+ // Create a new node, place it, and increase the size of the tree.
+ newNode := &Node{value: v, parent: prevNode}
+ switch {
+ case prevNode == nil:
+ t.root = newNode
+ case newNode.value < prevNode.value:
+ prevNode.left = newNode
+ default:
+ prevNode.right = newNode
+ }
+ t.size++
+}
+
+func (t *Tree) InOrderWalk(f fn) {
+ if t == nil {
+ return
+ }
+ t.root.left.inOrderWalk(f)
+ f(t.root.value)
+ t.root.right.inOrderWalk(f)
+
+}
+
+func (n *Node) inOrderWalk(f fn) {
+ if n == nil {
+ return
+ }
+ n.left.inOrderWalk(f)
+ f(n.value)
+ n.right.inOrderWalk(f)
+}
+
+func (t *Tree) PreOrderWalk(f fn) {
+ if t == nil {
+ return
+ }
+ f(t.root.value)
+ t.root.left.preOrderWalk(f)
+ t.root.right.preOrderWalk(f)
+}
+
+func (n *Node) preOrderWalk(f fn) {
+ if n == nil {
+ return
+ }
+ f(n.value)
+ n.left.preOrderWalk(f)
+ n.right.preOrderWalk(f)
+}
+
+func (t *Tree) PostOrderWalk(f fn) {
+ if t == nil {
+ return
+ }
+ t.root.left.postOrderWalk(f)
+ t.root.right.postOrderWalk(f)
+ f(t.root.value)
+}
+
+func (n *Node) postOrderWalk(f fn) {
+ if n == nil {
+ return
+ }
+ n.left.postOrderWalk(f)
+ n.right.postOrderWalk(f)
+ f(n.value)
+}
M binarysearchtree_test.go => binarysearchtree_test.go +12 -0
@@ 22,3 22,15 @@ func TestNewBST(t *testing.T) {
t.Errorf("expected %s; actual %s", expected, actual)
}
}
+
+func TestTreeInsert(t *testing.T) {
+ tree := algorithms.NewBST()
+
+ tree.Insert(2)
+ tree.Insert(10)
+ tree.Insert(-15)
+
+ if 3 != tree.Size() {
+ t.Errorf("inserted three items; actual tree.Size() is %d", tree.Size())
+ }
+}
A bst_example_test.go => bst_example_test.go +106 -0
@@ 0,0 1,106 @@
+package algorithms_test
+
+import (
+ "fmt"
+
+ "git.sr.ht/~telemachus/algorithms"
+)
+
+func ExampleInOrderWalk() {
+ t := algorithms.NewBST()
+ t.Insert(15)
+ t.Insert(6)
+ t.Insert(18)
+ t.Insert(3)
+ t.Insert(2)
+ t.Insert(4)
+ t.Insert(7)
+ t.Insert(13)
+ t.Insert(9)
+ t.Insert(17)
+ t.Insert(20)
+
+ show := func(i int) {
+ fmt.Printf("%d\n", i)
+ }
+
+ t.InOrderWalk(show)
+ // Output:
+ // 2
+ // 3
+ // 4
+ // 6
+ // 7
+ // 9
+ // 13
+ // 15
+ // 17
+ // 18
+ // 20
+}
+
+func ExamplePreOrderWalk() {
+ t := algorithms.NewBST()
+ t.Insert(15)
+ t.Insert(6)
+ t.Insert(18)
+ t.Insert(3)
+ t.Insert(2)
+ t.Insert(4)
+ t.Insert(7)
+ t.Insert(13)
+ t.Insert(9)
+ t.Insert(17)
+ t.Insert(20)
+
+ show := func(i int) {
+ fmt.Printf("%d\n", i)
+ }
+
+ t.PreOrderWalk(show)
+ // Output:
+ // 15
+ // 6
+ // 3
+ // 2
+ // 4
+ // 7
+ // 13
+ // 9
+ // 18
+ // 17
+ // 20
+}
+
+func ExamplePostOrderWalk() {
+ t := algorithms.NewBST()
+ t.Insert(15)
+ t.Insert(6)
+ t.Insert(18)
+ t.Insert(3)
+ t.Insert(2)
+ t.Insert(4)
+ t.Insert(7)
+ t.Insert(13)
+ t.Insert(9)
+ t.Insert(17)
+ t.Insert(20)
+
+ show := func(i int) {
+ fmt.Printf("%d\n", i)
+ }
+
+ t.PostOrderWalk(show)
+ // Output:
+ // 2
+ // 4
+ // 3
+ // 9
+ // 13
+ // 7
+ // 6
+ // 17
+ // 20
+ // 18
+ // 15
+}