Remove unnecessary comparable type constraints from data structures

Some data structures support custom comparators. In these cases,
the generic type constraint does not need to be comparable. This
commit removes the unnecessary comparable type constraints from
these data structures.
pull/244/head
Yujie Xia 3 months ago
parent 14f714261f
commit 7c91a38e2a

@ -0,0 +1,89 @@
package treeenc
import (
"encoding"
"encoding/json"
"reflect"
"strconv"
)
// KeyMarshaler is a helper type for marshaling keys of a tree.
// When marshaling a tree, we need first to convert tree key/value
// pairs to a standard Go map, and then marshal the map. However,
// Go maps can only have keys of comparable types, and so we wrap
// the key in a KeyMarshaler and implement the encoding.TextMarshaler
// interface to make it comparable and marshalable.
//
// The map should be declared as map[*KeyMarshaler[K]]V.
type KeyMarshaler[K any] struct {
Key K
}
var _ encoding.TextMarshaler = &KeyMarshaler[string]{}
func (m *KeyMarshaler[T]) MarshalText() ([]byte, error) {
kv := reflect.ValueOf(m.Key)
if tm, ok := kv.Interface().(encoding.TextMarshaler); ok {
if kv.Kind() == reflect.Pointer && kv.IsNil() {
return nil, nil
}
return tm.MarshalText()
}
var text string
switch kv.Kind() {
case reflect.String:
text = kv.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
text = strconv.FormatInt(kv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
text = strconv.FormatUint(kv.Uint(), 10)
default:
return nil, &json.UnsupportedTypeError{Type: kv.Type()}
}
return []byte(text), nil
}
// KeyUnmarshaler is a helper type for unmarshaling keys of a tree.
// When unmarshaling a tree, we first unmarshal the JSON into a Go
// map, and then convert the map to tree key/value pairs. Similar to
// KeyMarshaler, we wrap the key in a KeyUnmarshaler to make it
// unmarshalable by implementing the encoding.TextUnmarshaler interface.
//
// The map should be declared as map[KeyUnmarshaler[K]]V.
type KeyUnmarshaler[K any] struct {
Key *K
}
var _ encoding.TextUnmarshaler = &KeyUnmarshaler[string]{}
func (m *KeyUnmarshaler[K]) UnmarshalText(text []byte) error {
var key K
m.Key = &key
kv := reflect.ValueOf(m.Key)
if tu, ok := kv.Interface().(encoding.TextUnmarshaler); ok {
if kv.Kind() == reflect.Ptr && kv.IsNil() {
return nil
}
return tu.UnmarshalText(text)
}
var err error
kv = kv.Elem()
switch kv.Kind() {
case reflect.String:
kv.SetString(string(text))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
var i int64
i, err = strconv.ParseInt(string(text), 10, 64)
kv.SetInt(i)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
var u uint64
u, err = strconv.ParseUint(string(text), 10, 64)
kv.SetUint(u)
default:
err = &json.UnsupportedTypeError{Type: kv.Type()}
}
return err
}

@ -0,0 +1,140 @@
package treeenc
import (
"encoding/json"
"fmt"
"math"
"strings"
"testing"
)
type customType struct {
value string
}
func (c customType) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf("customType(%s)", c.value)), nil
}
func (c *customType) UnmarshalText(text []byte) error {
value := strings.TrimPrefix(string(text), "customType(")
value = strings.TrimSuffix(value, ")")
c.value = value
return nil
}
func TestKeyMarshaler(t *testing.T) {
strMap := make(map[*KeyMarshaler[string]]string)
strMap[&KeyMarshaler[string]{Key: "key"}] = "value"
data, err := json.Marshal(strMap)
if err != nil {
t.Fatalf("Got error: %v", err)
}
expected := "{\"key\":\"value\"}"
if string(data) != expected {
t.Fatalf("Expected %q, got %q", expected, string(data))
}
intMap := make(map[*KeyMarshaler[int]]int)
intMap[&KeyMarshaler[int]{Key: math.MinInt}] = math.MinInt
data, err = json.Marshal(&intMap)
if err != nil {
t.Fatalf("Got error: %v", err)
}
expected = "{\"-9223372036854775808\":-9223372036854775808}"
if string(data) != expected {
t.Fatalf("Expected %q, got %q", expected, string(data))
}
uintMap := make(map[*KeyMarshaler[uint]]uint)
uintMap[&KeyMarshaler[uint]{Key: math.MaxUint}] = math.MaxUint
data, err = json.Marshal(&uintMap)
if err != nil {
t.Fatalf("Got error: %v", err)
}
expected = "{\"18446744073709551615\":18446744073709551615}"
if string(data) != expected {
t.Fatalf("Expected %q, got %q", expected, string(data))
}
customMap := make(map[*KeyMarshaler[customType]]string)
customMap[&KeyMarshaler[customType]{Key: customType{value: "key"}}] = "value"
data, err = json.Marshal(&customMap)
if err != nil {
t.Fatalf("Got error: %v", err)
}
expected = "{\"customType(key)\":\"value\"}"
if string(data) != expected {
t.Fatalf("Expected %q, got %q", expected, string(data))
}
}
func TestKeyUnmarshaler(t *testing.T) {
strMap := make(map[KeyUnmarshaler[string]]string)
data := []byte("{\"key\":\"value\"}")
if err := json.Unmarshal(data, &strMap); err != nil {
t.Fatalf("Got error: %v", err)
}
if len(strMap) != 1 {
t.Fatalf("Expected 1 key, got %d", len(strMap))
}
for k, v := range strMap {
if *k.Key != "key" {
t.Fatalf("Expected key %q, got %q", "key", *k.Key)
}
if v != "value" {
t.Fatalf("Expected value %q, got %q", "value", v)
}
}
intMap := make(map[KeyUnmarshaler[int]]int)
data = []byte("{\"-9223372036854775808\":-9223372036854775808}")
if err := json.Unmarshal(data, &intMap); err != nil {
t.Fatalf("Got error: %v", err)
}
if len(intMap) != 1 {
t.Fatalf("Expected 1 key, got %d", len(intMap))
}
for k, v := range intMap {
if *k.Key != math.MinInt {
t.Fatalf("Expected key %d, got %d", math.MinInt, *k.Key)
}
if v != math.MinInt {
t.Fatalf("Expected value %d, got %d", math.MinInt, v)
}
}
uintMap := make(map[KeyUnmarshaler[uint]]uint)
data = []byte("{\"18446744073709551615\":18446744073709551615}")
if err := json.Unmarshal(data, &uintMap); err != nil {
t.Fatalf("Got error: %v", err)
}
if len(uintMap) != 1 {
t.Fatalf("Expected 1 key, got %d", len(uintMap))
}
for k, v := range uintMap {
if *k.Key != math.MaxUint {
t.Fatalf("Expected key %d, got %d", uint(math.MaxUint), *k.Key)
}
if v != math.MaxUint {
t.Fatalf("Expected value %d, got %d", uint(math.MaxUint), v)
}
}
customMap := make(map[KeyUnmarshaler[customType]]string)
data = []byte("{\"customType(key)\":\"value\"}")
if err := json.Unmarshal(data, &customMap); err != nil {
t.Fatalf("Got error: %v", err)
}
if len(customMap) != 1 {
t.Fatalf("Expected 1 key, got %d", len(customMap))
}
for k, v := range customMap {
if (*k.Key).value != "key" {
t.Fatalf("Expected key %q, got %q", "key", (*k.Key).value)
}
if v != "value" {
t.Fatalf("Expected value %q, got %q", "value", v)
}
}
}

@ -22,9 +22,10 @@ import (
var _ lists.List[int] = (*List[int])(nil)
// List holds the elements in a slice
type List[T comparable] struct {
type List[T any] struct {
elements []T
size int
equal func(a, b T) bool
}
const (
@ -34,7 +35,14 @@ const (
// New instantiates a new list and adds the passed values, if any, to the list
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
equal := func(a, b T) bool { return a == b }
return NewWith(equal, values...)
}
// NewWith instantiates a new list with the custom equal
// function and adds the passed values, if any, to the list.
func NewWith[T any](equal func(a, b T) bool, values ...T) *List[T] {
list := &List[T]{equal: equal}
if len(values) > 0 {
list.Add(values...)
}
@ -85,7 +93,7 @@ func (list *List[T]) Contains(values ...T) bool {
for _, searchValue := range values {
found := false
for index := 0; index < list.size; index++ {
if list.elements[index] == searchValue {
if list.equal(list.elements[index], searchValue) {
found = true
break
}
@ -99,7 +107,7 @@ func (list *List[T]) Contains(values ...T) bool {
// Values returns all elements in the list.
func (list *List[T]) Values() []T {
newElements := make([]T, list.size, list.size)
newElements := make([]T, list.size)
copy(newElements, list.elements[:list.size])
return newElements
}
@ -110,7 +118,7 @@ func (list *List[T]) IndexOf(value T) int {
return -1
}
for index, element := range list.elements {
if element == value {
if list.equal(element, value) {
return index
}
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator[T comparable] struct {
type Iterator[T any] struct {
list *List[T]
index int
}

@ -22,13 +22,14 @@ import (
var _ lists.List[any] = (*List[any])(nil)
// List holds the elements, where each element points to the next and previous element
type List[T comparable] struct {
type List[T any] struct {
first *element[T]
last *element[T]
size int
equal func(a, b T) bool
}
type element[T comparable] struct {
type element[T any] struct {
value T
prev *element[T]
next *element[T]
@ -36,7 +37,14 @@ type element[T comparable] struct {
// New instantiates a new list and adds the passed values, if any, to the list
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
equal := func(a, b T) bool { return a == b }
return NewWith(equal, values...)
}
// NewWith instantiates a new list with the custom equal
// function and adds the passed values, if any, to the list.
func NewWith[T any](equal func(a, b T) bool, values ...T) *List[T] {
list := &List[T]{equal: equal}
if len(values) > 0 {
list.Add(values...)
}
@ -158,7 +166,7 @@ func (list *List[T]) Contains(values ...T) bool {
for _, value := range values {
found := false
for element := list.first; element != nil; element = element.next {
if element.value == value {
if list.equal(element.value, value) {
found = true
break
}
@ -185,7 +193,7 @@ func (list *List[T]) IndexOf(value T) int {
return -1
}
for index, element := range list.Values() {
if element == value {
if list.equal(element, value) {
return index
}
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator[T comparable] struct {
type Iterator[T any] struct {
list *List[T]
index int
element *element[T]

@ -15,7 +15,7 @@ import (
)
// List interface that all lists implement
type List[T comparable] interface {
type List[T any] interface {
Get(index int) (T, bool)
Remove(index int)
Add(values ...T)

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator[T comparable] struct {
type Iterator[T any] struct {
list *List[T]
index int
element *element[T]

@ -22,20 +22,28 @@ import (
var _ lists.List[int] = (*List[int])(nil)
// List holds the elements, where each element points to the next element
type List[T comparable] struct {
type List[T any] struct {
first *element[T]
last *element[T]
size int
equal func(a, b T) bool
}
type element[T comparable] struct {
type element[T any] struct {
value T
next *element[T]
}
// New instantiates a new list and adds the passed values, if any, to the list
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
equal := func(a, b T) bool { return a == b }
return NewWith(equal, values...)
}
// NewWith instantiates a new list with the custom equal
// function and adds the passed values, if any, to the list.
func NewWith[T any](equal func(a, b T) bool, values ...T) *List[T] {
list := &List[T]{equal: equal}
if len(values) > 0 {
list.Add(values...)
}
@ -139,7 +147,7 @@ func (list *List[T]) Contains(values ...T) bool {
for _, value := range values {
found := false
for element := list.first; element != nil; element = element.next {
if element.value == value {
if list.equal(element.value, value) {
found = true
break
}
@ -166,7 +174,7 @@ func (list *List[T]) IndexOf(value T) int {
return -1
}
for index, element := range list.Values() {
if element == value {
if list.equal(element, value) {
return index
}
}

@ -18,7 +18,7 @@ package maps
import "github.com/emirpasic/gods/v2/containers"
// Map interface that all maps implement
type Map[K comparable, V any] interface {
type Map[K any, V any] interface {
Put(key K, value V)
Get(key K) (value V, found bool)
Remove(key K)
@ -33,7 +33,7 @@ type Map[K comparable, V any] interface {
}
// BidiMap interface that all bidirectional maps implement (extends the Map interface)
type BidiMap[K comparable, V comparable] interface {
type BidiMap[K any, V any] interface {
GetKey(value V) (key K, found bool)
Map[K, V]

@ -13,7 +13,7 @@ import (
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator[K comparable, V any] struct {
type Iterator[K any, V any] struct {
iterator *rbt.Iterator[K, V]
}

@ -8,6 +8,7 @@ import (
"encoding/json"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/internal/treeenc"
)
// Assert Serialization implementation
@ -21,15 +22,15 @@ func (m *Map[K, V]) ToJSON() ([]byte, error) {
// FromJSON populates the map from the input JSON representation.
func (m *Map[K, V]) FromJSON(data []byte) error {
var elements map[K]V
var elements map[treeenc.KeyUnmarshaler[K]]V
err := json.Unmarshal(data, &elements)
if err != nil {
return err
}
m.Clear()
for key, value := range elements {
m.Put(key, value)
for ku, value := range elements {
m.Put(*ku.Key, value)
}
return nil

@ -32,7 +32,7 @@ import (
var _ maps.BidiMap[string, int] = (*Map[string, int])(nil)
// Map holds the elements in two red-black trees.
type Map[K, V comparable] struct {
type Map[K, V any] struct {
forwardMap redblacktree.Tree[K, V]
inverseMap redblacktree.Tree[V, K]
}
@ -46,7 +46,7 @@ func New[K, V cmp.Ordered]() *Map[K, V] {
}
// NewWith instantiates a bidirectional map.
func NewWith[K, V comparable](keyComparator utils.Comparator[K], valueComparator utils.Comparator[V]) *Map[K, V] {
func NewWith[K, V any](keyComparator utils.Comparator[K], valueComparator utils.Comparator[V]) *Map[K, V] {
return &Map[K, V]{
forwardMap: *redblacktree.NewWith[K, V](keyComparator),
inverseMap: *redblacktree.NewWith[V, K](valueComparator),

@ -13,7 +13,7 @@ import (
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator[K comparable, V any] struct {
type Iterator[K any, V any] struct {
iterator *rbt.Iterator[K, V]
}

@ -25,7 +25,7 @@ import (
var _ maps.Map[string, int] = (*Map[string, int])(nil)
// Map holds the elements in a red-black tree
type Map[K comparable, V any] struct {
type Map[K any, V any] struct {
tree *rbt.Tree[K, V]
}
@ -35,7 +35,7 @@ func New[K cmp.Ordered, V any]() *Map[K, V] {
}
// NewWith instantiates a tree map with the custom comparator.
func NewWith[K comparable, V any](comparator utils.Comparator[K]) *Map[K, V] {
func NewWith[K any, V any](comparator utils.Comparator[K]) *Map[K, V] {
return &Map[K, V]{tree: rbt.NewWith[K, V](comparator)}
}

@ -21,7 +21,7 @@ import (
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in an array-list
type Queue[T comparable] struct {
type Queue[T any] struct {
list *arraylist.List[T]
}
@ -30,6 +30,11 @@ func New[T comparable]() *Queue[T] {
return &Queue[T]{list: arraylist.New[T]()}
}
// NewWith instantiates a new empty queue with the custom equal function.
func NewWith[T comparable](equal func(a, b T) bool) *Queue[T] {
return &Queue[T]{list: arraylist.NewWith(equal)}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue[T]) Enqueue(value T) {
queue.list.Add(value)

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
queue *Queue[T]
index int
}

@ -22,7 +22,7 @@ import (
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds values in a slice.
type Queue[T comparable] struct {
type Queue[T any] struct {
values []T
start int
end int
@ -33,7 +33,7 @@ type Queue[T comparable] struct {
// New instantiates a new empty queue with the specified size of maximum number of elements that it can hold.
// This max size of the buffer cannot be changed.
func New[T comparable](maxSize int) *Queue[T] {
func New[T any](maxSize int) *Queue[T] {
if maxSize < 1 {
panic("Invalid maxSize, should be at least 1")
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
queue *Queue[T]
index int
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
queue *Queue[T]
index int
}

@ -21,7 +21,7 @@ import (
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in a singly-linked-list
type Queue[T comparable] struct {
type Queue[T any] struct {
list *singlylinkedlist.List[T]
}
@ -30,6 +30,11 @@ func New[T comparable]() *Queue[T] {
return &Queue[T]{list: singlylinkedlist.New[T]()}
}
// NewWith instantiates a new empty queue with the custom equal function.
func NewWith[T any](equal func(a, b T) bool) *Queue[T] {
return &Queue[T]{list: singlylinkedlist.NewWith(equal)}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue[T]) Enqueue(value T) {
queue.list.Add(value)

@ -13,7 +13,7 @@ import (
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
iterator *binaryheap.Iterator[T]
}

@ -29,7 +29,7 @@ import (
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in an array-list
type Queue[T comparable] struct {
type Queue[T any] struct {
heap *binaryheap.Heap[T]
Comparator utils.Comparator[T]
}
@ -39,7 +39,7 @@ func New[T cmp.Ordered]() *Queue[T] {
}
// NewWith instantiates a new empty queue with the custom comparator.
func NewWith[T comparable](comparator utils.Comparator[T]) *Queue[T] {
func NewWith[T any](comparator utils.Comparator[T]) *Queue[T] {
return &Queue[T]{heap: binaryheap.NewWith(comparator), Comparator: comparator}
}

@ -13,7 +13,7 @@ package queues
import "github.com/emirpasic/gods/v2/containers"
// Queue interface that all queues implement
type Queue[T comparable] interface {
type Queue[T any] interface {
Enqueue(value T)
Dequeue() (value T, ok bool)
Peek() (value T, ok bool)

@ -14,7 +14,7 @@ import (
)
// Set interface that all sets implement
type Set[T comparable] interface {
type Set[T any] interface {
Add(elements ...T)
Remove(elements ...T)
Contains(elements ...T) bool

@ -13,7 +13,7 @@ import (
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
index int
iterator *rbt.Iterator[T, struct{}]
tree *rbt.Tree[T, struct{}]

@ -24,7 +24,7 @@ import (
var _ sets.Set[int] = (*Set[int])(nil)
// Set holds elements in a red-black tree
type Set[T comparable] struct {
type Set[T any] struct {
tree *rbt.Tree[T, struct{}]
}
@ -35,7 +35,7 @@ func New[T cmp.Ordered](values ...T) *Set[T] {
}
// NewWith instantiates a new empty set with the custom comparator.
func NewWith[T comparable](comparator utils.Comparator[T], values ...T) *Set[T] {
func NewWith[T any](comparator utils.Comparator[T], values ...T) *Set[T] {
set := &Set[T]{tree: rbt.NewWith[T, struct{}](comparator)}
if len(values) > 0 {
set.Add(values...)

@ -21,7 +21,7 @@ import (
var _ stacks.Stack[int] = (*Stack[int])(nil)
// Stack holds elements in an array-list
type Stack[T comparable] struct {
type Stack[T any] struct {
list *arraylist.List[T]
}
@ -30,6 +30,11 @@ func New[T comparable]() *Stack[T] {
return &Stack[T]{list: arraylist.New[T]()}
}
// NewWith instantiates a new empty stack with the custom equals function.
func NewWith[T any](equal func(a, b T) bool) *Stack[T] {
return &Stack[T]{list: arraylist.NewWith[T](equal)}
}
// Push adds a value onto the top of the stack
func (stack *Stack[T]) Push(value T) {
stack.list.Add(value)

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
stack *Stack[T]
index int
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
stack *Stack[T]
index int
}

@ -21,15 +21,20 @@ import (
var _ stacks.Stack[int] = (*Stack[int])(nil)
// Stack holds elements in a singly-linked-list
type Stack[T comparable] struct {
type Stack[T any] struct {
list *singlylinkedlist.List[T]
}
// New nnstantiates a new empty stack
// New instantiates a new empty stack.
func New[T comparable]() *Stack[T] {
return &Stack[T]{list: singlylinkedlist.New[T]()}
}
// NewWith instantiates a new empty stack with the custom equal function.
func NewWith[T any](equal func(a, b T) bool) *Stack[T] {
return &Stack[T]{list: singlylinkedlist.NewWith(equal)}
}
// Push adds a value onto the top of the stack
func (stack *Stack[T]) Push(value T) {
stack.list.Prepend(value)

@ -21,14 +21,14 @@ import (
var _ trees.Tree[int] = (*Tree[string, int])(nil)
// Tree holds elements of the AVL tree.
type Tree[K comparable, V any] struct {
type Tree[K any, V any] struct {
Root *Node[K, V] // Root node
Comparator utils.Comparator[K] // Key comparator
size int // Total number of keys in the tree
}
// Node is a single element within the tree
type Node[K comparable, V any] struct {
type Node[K any, V any] struct {
Key K
Value V
Parent *Node[K, V] // Parent node
@ -42,7 +42,7 @@ func New[K cmp.Ordered, V any]() *Tree[K, V] {
}
// NewWith instantiates an AVL tree with the custom comparator.
func NewWith[K comparable, V any](comparator utils.Comparator[K]) *Tree[K, V] {
func NewWith[K any, V any](comparator utils.Comparator[K]) *Tree[K, V] {
return &Tree[K, V]{Comparator: comparator}
}
@ -287,7 +287,7 @@ func (tree *Tree[K, V]) remove(key K, qp **Node[K, V]) bool {
return false
}
func removeMin[K comparable, V any](qp **Node[K, V], minKey *K, minVal *V) bool {
func removeMin[K any, V any](qp **Node[K, V], minKey *K, minVal *V) bool {
q := *qp
if q.Children[0] == nil {
*minKey = q.Key
@ -305,7 +305,7 @@ func removeMin[K comparable, V any](qp **Node[K, V], minKey *K, minVal *V) bool
return false
}
func putFix[K comparable, V any](c int8, t **Node[K, V]) bool {
func putFix[K any, V any](c int8, t **Node[K, V]) bool {
s := *t
if s.b == 0 {
s.b = c
@ -326,7 +326,7 @@ func putFix[K comparable, V any](c int8, t **Node[K, V]) bool {
return false
}
func removeFix[K comparable, V any](c int8, t **Node[K, V]) bool {
func removeFix[K any, V any](c int8, t **Node[K, V]) bool {
s := *t
if s.b == 0 {
s.b = c
@ -355,14 +355,14 @@ func removeFix[K comparable, V any](c int8, t **Node[K, V]) bool {
return true
}
func singlerot[K comparable, V any](c int8, s *Node[K, V]) *Node[K, V] {
func singlerot[K any, V any](c int8, s *Node[K, V]) *Node[K, V] {
s.b = 0
s = rotate(c, s)
s.b = 0
return s
}
func doublerot[K comparable, V any](c int8, s *Node[K, V]) *Node[K, V] {
func doublerot[K any, V any](c int8, s *Node[K, V]) *Node[K, V] {
a := (c + 1) / 2
r := s.Children[a]
s.Children[a] = rotate(-c, s.Children[a])
@ -384,7 +384,7 @@ func doublerot[K comparable, V any](c int8, s *Node[K, V]) *Node[K, V] {
return p
}
func rotate[K comparable, V any](c int8, s *Node[K, V]) *Node[K, V] {
func rotate[K any, V any](c int8, s *Node[K, V]) *Node[K, V] {
a := (c + 1) / 2
r := s.Children[a]
s.Children[a] = r.Children[a^1]
@ -442,7 +442,7 @@ func (n *Node[K, V]) walk1(a int) *Node[K, V] {
return p
}
func output[K comparable, V any](node *Node[K, V], prefix string, isTail bool, str *string) {
func output[K any, V any](node *Node[K, V], prefix string, isTail bool, str *string) {
if node.Children[1] != nil {
newPrefix := prefix
if isTail {

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator[K comparable, V any] struct {
type Iterator[K any, V any] struct {
tree *Tree[K, V]
node *Node[K, V]
position position

@ -8,6 +8,7 @@ import (
"encoding/json"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/internal/treeenc"
)
// Assert Serialization implementation
@ -16,25 +17,25 @@ var _ containers.JSONDeserializer = (*Tree[string, int])(nil)
// ToJSON outputs the JSON representation of the tree.
func (tree *Tree[K, V]) ToJSON() ([]byte, error) {
elements := make(map[K]V)
elements := make(map[*treeenc.KeyMarshaler[K]]V)
it := tree.Iterator()
for it.Next() {
elements[it.Key()] = it.Value()
elements[&treeenc.KeyMarshaler[K]{Key: it.Key()}] = it.Value()
}
return json.Marshal(&elements)
}
// FromJSON populates the tree from the input JSON representation.
func (tree *Tree[K, V]) FromJSON(data []byte) error {
elements := make(map[K]V)
elements := make(map[treeenc.KeyUnmarshaler[K]]V)
err := json.Unmarshal(data, &elements)
if err != nil {
return err
}
tree.Clear()
for key, value := range elements {
tree.Put(key, value)
for ku, value := range elements {
tree.Put(*ku.Key, value)
}
return nil

@ -25,7 +25,7 @@ import (
var _ trees.Tree[int] = (*Heap[int])(nil)
// Heap holds elements in an array-list
type Heap[T comparable] struct {
type Heap[T any] struct {
list *arraylist.List[T]
Comparator utils.Comparator[T]
}
@ -36,8 +36,9 @@ func New[T cmp.Ordered]() *Heap[T] {
}
// NewWith instantiates a new empty heap tree with the custom comparator.
func NewWith[T comparable](comparator utils.Comparator[T]) *Heap[T] {
return &Heap[T]{list: arraylist.New[T](), Comparator: comparator}
func NewWith[T any](comparator utils.Comparator[T]) *Heap[T] {
equal := func(a, b T) bool { return comparator(a, b) == 0 }
return &Heap[T]{list: arraylist.NewWith[T](equal), Comparator: comparator}
}
// Push adds a value onto the heap and bubbles it up accordingly.

@ -12,7 +12,7 @@ import (
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator[T comparable] struct {
type Iterator[T any] struct {
heap *Heap[T]
index int
}

@ -30,7 +30,7 @@ import (
var _ trees.Tree[int] = (*Tree[string, int])(nil)
// Tree holds elements of the B-tree
type Tree[K comparable, V any] struct {
type Tree[K any, V any] struct {
Root *Node[K, V] // Root node
Comparator utils.Comparator[K] // Key comparator
size int // Total number of keys in the tree
@ -38,14 +38,14 @@ type Tree[K comparable, V any] struct {
}
// Node is a single element within the tree
type Node[K comparable, V any] struct {
type Node[K any, V any] struct {
Parent *Node[K, V]
Entries []*Entry[K, V] // Contained keys in node
Children []*Node[K, V] // Children nodes
}
// Entry represents the key-value pair contained within nodes
type Entry[K comparable, V any] struct {
type Entry[K any, V any] struct {
Key K
Value V
}
@ -56,7 +56,7 @@ func New[K cmp.Ordered, V any](order int) *Tree[K, V] {
}
// NewWith instantiates a B-tree with the order (maximum number of children) and a custom key comparator.
func NewWith[K comparable, V any](order int, comparator utils.Comparator[K]) *Tree[K, V] {
func NewWith[K any, V any](order int, comparator utils.Comparator[K]) *Tree[K, V] {
if order < 3 {
panic("Invalid order, should be at least 3")
}
@ -411,7 +411,7 @@ func (tree *Tree[K, V]) splitRoot() {
tree.Root = newRoot
}
func setParent[K comparable, V any](nodes []*Node[K, V], parent *Node[K, V]) {
func setParent[K any, V any](nodes []*Node[K, V], parent *Node[K, V]) {
for _, node := range nodes {
node.Parent = parent
}

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator[K comparable, V any] struct {
type Iterator[K any, V any] struct {
tree *Tree[K, V]
node *Node[K, V]
entry *Entry[K, V]

@ -8,6 +8,7 @@ import (
"encoding/json"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/internal/treeenc"
)
// Assert Serialization implementation
@ -16,25 +17,25 @@ var _ containers.JSONDeserializer = (*Tree[string, int])(nil)
// ToJSON outputs the JSON representation of the tree.
func (tree *Tree[K, V]) ToJSON() ([]byte, error) {
elements := make(map[K]V)
elements := make(map[*treeenc.KeyMarshaler[K]]V)
it := tree.Iterator()
for it.Next() {
elements[it.Key()] = it.Value()
elements[&treeenc.KeyMarshaler[K]{Key: it.Key()}] = it.Value()
}
return json.Marshal(&elements)
}
// FromJSON populates the tree from the input JSON representation.
func (tree *Tree[K, V]) FromJSON(data []byte) error {
elements := make(map[K]V)
elements := make(map[treeenc.KeyUnmarshaler[K]]V)
err := json.Unmarshal(data, &elements)
if err != nil {
return err
}
tree.Clear()
for key, value := range elements {
tree.Put(key, value)
for ku, value := range elements {
tree.Put(*ku.Key, value)
}
return err

@ -10,7 +10,7 @@ import "github.com/emirpasic/gods/v2/containers"
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator[K comparable, V any] struct {
type Iterator[K any, V any] struct {
tree *Tree[K, V]
node *Node[K, V]
position position

@ -29,14 +29,14 @@ const (
)
// Tree holds elements of the red-black tree
type Tree[K comparable, V any] struct {
type Tree[K any, V any] struct {
Root *Node[K, V]
size int
Comparator utils.Comparator[K]
}
// Node is a single element within the tree
type Node[K comparable, V any] struct {
type Node[K any, V any] struct {
Key K
Value V
color color
@ -51,7 +51,7 @@ func New[K cmp.Ordered, V any]() *Tree[K, V] {
}
// NewWith instantiates a red-black tree with the custom comparator.
func NewWith[K comparable, V any](comparator utils.Comparator[K]) *Tree[K, V] {
func NewWith[K any, V any](comparator utils.Comparator[K]) *Tree[K, V] {
return &Tree[K, V]{Comparator: comparator}
}
@ -292,7 +292,7 @@ func (node *Node[K, V]) String() string {
return fmt.Sprintf("%v", node.Key)
}
func output[K comparable, V any](node *Node[K, V], prefix string, isTail bool, str *string) {
func output[K any, V any](node *Node[K, V], prefix string, isTail bool, str *string) {
if node.Right != nil {
newPrefix := prefix
if isTail {
@ -537,7 +537,7 @@ func (tree *Tree[K, V]) deleteCase6(node *Node[K, V]) {
}
}
func nodeColor[K comparable, V any](node *Node[K, V]) color {
func nodeColor[K any, V any](node *Node[K, V]) color {
if node == nil {
return black
}

@ -8,6 +8,7 @@ import (
"encoding/json"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/internal/treeenc"
)
// Assert Serialization implementation
@ -16,22 +17,22 @@ var _ containers.JSONDeserializer = (*Tree[string, int])(nil)
// ToJSON outputs the JSON representation of the tree.
func (tree *Tree[K, V]) ToJSON() ([]byte, error) {
elements := make(map[K]V)
elements := make(map[*treeenc.KeyMarshaler[K]]V)
it := tree.Iterator()
for it.Next() {
elements[it.Key()] = it.Value()
elements[&treeenc.KeyMarshaler[K]{Key: it.Key()}] = it.Value()
}
return json.Marshal(&elements)
}
// FromJSON populates the tree from the input JSON representation.
func (tree *Tree[K, V]) FromJSON(data []byte) error {
elements := make(map[K]V)
elements := make(map[treeenc.KeyUnmarshaler[K]]V)
err := json.Unmarshal(data, &elements)
if err == nil {
tree.Clear()
for key, value := range elements {
tree.Put(key, value)
for ku, value := range elements {
tree.Put(*ku.Key, value)
}
}
return err

Loading…
Cancel
Save