github.com/Nigel2392/go-datastructures@v1.1.5/binarytree/interfaced_bst.go (about) 1 package binarytree 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 8 "github.com/Nigel2392/go-datastructures" 9 "golang.org/x/exp/slices" 10 ) 11 12 // A binary search tree implementation which works with any type that implements the Comparable[T] interface. 13 type InterfacedBST[T datastructures.Comparable[T]] struct { 14 root *IF_BSTNode[T] 15 len int 16 height int 17 } 18 19 // Return the binary search tree as a string. 20 func (t *InterfacedBST[T]) String() string { 21 if t.root == nil { 22 return "" 23 } 24 25 height := t.root.getHeight() 26 IF_BSTNodes := make([][]string, height) 27 28 fillIF_BSTNodes(IF_BSTNodes, t.root, 0) 29 30 var b strings.Builder 31 padding := int(math.Pow(2, float64(height)) - 1) 32 33 for i, level := range IF_BSTNodes { 34 if i == 0 { 35 paddingStr := strings.Repeat(" ", (padding/2)+1) 36 b.WriteString(paddingStr) 37 } else { 38 paddingStr := strings.Repeat(" ", padding/2) 39 b.WriteString(paddingStr) 40 } 41 42 for j, IF_BSTNode := range level { 43 b.WriteString(IF_BSTNode) 44 if j != len(level)-1 { 45 b.WriteString(strings.Repeat(" ", padding)) 46 } 47 } 48 49 padding /= 2 50 b.WriteString("\n") 51 } 52 53 return b.String() 54 } 55 56 // Initialize a new binary search tree with the given initial value. 57 func NewInterfaced[T datastructures.Comparable[T]](initial T) *InterfacedBST[T] { 58 return &InterfacedBST[T]{ 59 root: &IF_BSTNode[T]{value: initial}} 60 } 61 62 // Insert a value into the binary search tree. 63 func (t *InterfacedBST[T]) Insert(value T) (inserted bool) { 64 if t.root == nil { 65 t.root = &IF_BSTNode[T]{value: value} 66 t.len++ 67 return true 68 } 69 inserted = t.root.insert(value) 70 if inserted { 71 t.len++ 72 } 73 return inserted 74 } 75 76 // Search for, and return, a value in the binary search tree. 77 func (t *InterfacedBST[T]) Search(value T) (v T, ok bool) { 78 if t.root == nil { 79 return 80 } 81 return t.root.search(value) 82 } 83 84 // Delete a value from the binary search tree. 85 func (t *InterfacedBST[T]) Delete(value T) (deleted bool) { 86 if t.root == nil { 87 return false 88 } 89 t.root, deleted = t.root.delete(value) 90 if deleted { 91 t.len-- 92 } 93 return deleted 94 } 95 96 // Delete all values from the binary search tree that match the given predicate. 97 func (t *InterfacedBST[T]) DeleteIf(predicate func(T) bool) (deleted int) { 98 if t.root == nil { 99 return 0 100 } 101 t.root, deleted = t.root.deleteIf(predicate) 102 t.len -= int(deleted) 103 return deleted 104 } 105 106 // Traverse the binary search tree in-order. 107 func (t *InterfacedBST[T]) Traverse(f func(T)) { 108 if t.root == nil { 109 return 110 } 111 t.root.traverse(f) 112 } 113 114 // Return the number of values in the binary search tree. 115 func (t *InterfacedBST[T]) Len() int { 116 return t.len 117 } 118 119 // Return the height of the binary search tree. 120 func (t *InterfacedBST[T]) Height() int { 121 if t.root == nil { 122 return 0 123 } 124 return t.root.getHeight() 125 } 126 127 // Clear the binary search tree. 128 func (t *InterfacedBST[T]) Clear() { 129 t.root = nil 130 t.len = 0 131 } 132 133 func fillIF_BSTNodes[T datastructures.Comparable[T]](IF_BSTNodes [][]string, n *IF_BSTNode[T], depth int) { 134 if n == nil { 135 return 136 } 137 138 IF_BSTNodes[depth] = append(IF_BSTNodes[depth], fmt.Sprintf("%v", n.value)) 139 fillIF_BSTNodes(IF_BSTNodes, n.left, depth+1) 140 fillIF_BSTNodes(IF_BSTNodes, n.right, depth+1) 141 } 142 143 // Create a new binary search tree from an array. 144 func SliceToInterfacedBST[T datastructures.Comparable[T]](items []T, sorted bool) *InterfacedBST[T] { 145 if !sorted { 146 slices.SortFunc[T](items, func(i, j T) bool { 147 return i.Lt(j) 148 }) 149 } 150 var bst InterfacedBST[T] 151 bst.root = constructInterfacedBSTFromSortedSlice(items, 0, len(items)) 152 return &bst 153 } 154 155 func constructInterfacedBSTFromSortedSlice[T datastructures.Comparable[T]](items []T, start, end int) *IF_BSTNode[T] { 156 if start == end { 157 return nil 158 } 159 mid := start + (end-start)/2 160 return &IF_BSTNode[T]{ 161 value: items[mid], 162 left: constructInterfacedBSTFromSortedSlice(items, start, mid), 163 right: constructInterfacedBSTFromSortedSlice(items, mid+1, end), 164 } 165 }