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  }