github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/ds/set_link.go (about)

     1  package ds
     2  
     3  import (
     4  	"github.com/15mga/kiwi/util"
     5  )
     6  
     7  type (
     8  	setLinkOption[KT comparable, VT any] struct {
     9  		valToKey    func(VT) KT
    10  		spawnElem   func() *SetLinkElem[VT]
    11  		recycleElem func(*SetLinkElem[VT])
    12  	}
    13  	DLinkOption[KT comparable, VT any] func(o *setLinkOption[KT, VT])
    14  )
    15  
    16  func SetLinkValToKey[KT comparable, VT any](valToKey func(VT) KT) DLinkOption[KT, VT] {
    17  	return func(o *setLinkOption[KT, VT]) {
    18  		o.valToKey = valToKey
    19  	}
    20  }
    21  
    22  func SetLinkSpawnElem[KT comparable, VT any](spawn func() *SetLinkElem[VT]) DLinkOption[KT, VT] {
    23  	return func(o *setLinkOption[KT, VT]) {
    24  		o.spawnElem = spawn
    25  	}
    26  }
    27  
    28  func SetLinkRecycleElem[KT comparable, VT any](recycle func(*SetLinkElem[VT])) DLinkOption[KT, VT] {
    29  	return func(o *setLinkOption[KT, VT]) {
    30  		o.recycleElem = recycle
    31  	}
    32  }
    33  
    34  func NewSetLink[KT comparable, VT any](cap int, opts ...DLinkOption[KT, VT]) *SetLink[KT, VT] {
    35  	opt := &setLinkOption[KT, VT]{
    36  		spawnElem: func() *SetLinkElem[VT] {
    37  			return &SetLinkElem[VT]{}
    38  		},
    39  		recycleElem: func(elem *SetLinkElem[VT]) {},
    40  	}
    41  	for _, o := range opts {
    42  		o(opt)
    43  	}
    44  	return &SetLink[KT, VT]{
    45  		option:    opt,
    46  		keyToNode: make(map[KT]*SetLinkElem[VT], cap),
    47  	}
    48  }
    49  
    50  // SetLink 元素唯一双向链表
    51  type SetLink[KT comparable, VT any] struct {
    52  	option    *setLinkOption[KT, VT]
    53  	head      *SetLinkElem[VT]
    54  	tail      *SetLinkElem[VT]
    55  	keyToNode map[KT]*SetLinkElem[VT]
    56  	count     int
    57  }
    58  
    59  func (l *SetLink[KT, VT]) Get(key KT) (VT, bool) {
    60  	v, ok := l.keyToNode[key]
    61  	if ok {
    62  		return v.Value, true
    63  	}
    64  	return util.Default[VT](), false
    65  }
    66  
    67  // Push 推入元素,如果已存在返回false
    68  func (l *SetLink[KT, VT]) Push(val VT) bool {
    69  	key := l.option.valToKey(val)
    70  	_, ok := l.keyToNode[key]
    71  	if ok {
    72  		return false
    73  	}
    74  	l.push(key, val)
    75  	return true
    76  }
    77  
    78  func (l *SetLink[KT, VT]) push(key KT, val VT) {
    79  	node := l.option.spawnElem()
    80  	node.Value = val
    81  	l.keyToNode[key] = node
    82  	if l.count == 0 {
    83  		l.head = node
    84  		l.tail = node
    85  	} else {
    86  		node.prevNode = l.tail
    87  		l.tail.nextNode = node
    88  		l.tail = node
    89  	}
    90  	l.count++
    91  }
    92  
    93  func (l *SetLink[KT, VT]) NewOrUpdate(key KT, update func(VT), new func() VT) (exist bool) {
    94  	v, ok := l.keyToNode[key]
    95  	if ok {
    96  		update(v.Value)
    97  		return true
    98  	}
    99  	l.push(key, new())
   100  	return false
   101  }
   102  
   103  // Del 测试弹出一个符合条件的即停止
   104  func (l *SetLink[KT, VT]) Del(test func(VT) bool) (VT, bool) {
   105  	for node := l.head; node != nil; node = node.nextNode {
   106  		if test(node.Value) {
   107  			v := node.Value
   108  			l.removeNode(node)
   109  			return v, true
   110  		}
   111  	}
   112  	return util.Default[VT](), false
   113  }
   114  
   115  func (l *SetLink[KT, VT]) Pop() (VT, bool) {
   116  	if l.count == 0 {
   117  		return util.Default[VT](), false
   118  	}
   119  	firstNode := l.head
   120  	v := firstNode.Value
   121  	l.head = firstNode.nextNode
   122  	if l.option.recycleElem != nil {
   123  		firstNode.Dispose()
   124  		l.option.recycleElem(firstNode)
   125  	}
   126  	delete(l.keyToNode, l.option.valToKey(v))
   127  	return v, true
   128  }
   129  
   130  func (l *SetLink[KT, VT]) removeNode(node *SetLinkElem[VT]) {
   131  	if l.head == node {
   132  		if l.tail == node {
   133  			l.head = nil
   134  			l.tail = nil
   135  		} else {
   136  			l.head = node.nextNode
   137  			l.head.prevNode = nil
   138  		}
   139  	} else if l.tail == node {
   140  		prevNode := node.prevNode
   141  		prevNode.nextNode = nil
   142  		l.tail = prevNode
   143  	} else {
   144  		prevNode := node.prevNode
   145  		nextNode := node.nextNode
   146  		prevNode.nextNode = nextNode
   147  		nextNode.prevNode = prevNode
   148  	}
   149  	delete(l.keyToNode, l.option.valToKey(node.Value))
   150  	l.count--
   151  	if l.option.recycleElem != nil {
   152  		node.Dispose()
   153  		l.option.recycleElem(node)
   154  	}
   155  }
   156  
   157  func (l *SetLink[KT, VT]) Remove(val VT) {
   158  	l.RemoveByKey(l.option.valToKey(val))
   159  }
   160  
   161  func (l *SetLink[KT, VT]) RemoveByKey(key KT) {
   162  	node, ok := l.keyToNode[key]
   163  	if !ok {
   164  		return
   165  	}
   166  	l.removeNode(node)
   167  }
   168  
   169  func (l *SetLink[KT, VT]) Iter(fn func(VT)) {
   170  	if l.count == 0 {
   171  		return
   172  	}
   173  	for n := l.head; n != nil; n = n.nextNode {
   174  		fn(n.Value)
   175  	}
   176  }
   177  
   178  func (l *SetLink[KT, VT]) Any(fn func(VT) bool) bool {
   179  	if l.count == 0 {
   180  		return false
   181  	}
   182  	for n := l.head; n != nil; n = n.nextNode {
   183  		if fn(n.Value) {
   184  			return true
   185  		}
   186  	}
   187  	return false
   188  }
   189  
   190  func (l *SetLink[KT, VT]) Values() []VT {
   191  	if l.count == 0 {
   192  		return nil
   193  	}
   194  	values := make([]VT, l.count)
   195  	i := 0
   196  	for n := l.head; n != nil; n = n.nextNode {
   197  		values[i] = n.Value
   198  		i++
   199  	}
   200  	return values
   201  }
   202  
   203  func (l *SetLink[KT, VT]) Count() int {
   204  	return l.count
   205  }
   206  
   207  type SetLinkElem[T any] struct {
   208  	Value    T
   209  	prevNode *SetLinkElem[T]
   210  	nextNode *SetLinkElem[T]
   211  }
   212  
   213  func (n *SetLinkElem[T]) Dispose() {
   214  	n.prevNode = nil
   215  	n.nextNode = nil
   216  }