gitee.com/h79/goutils@v1.22.10/common/queue/capacity.go (about) 1 package queue 2 3 import "time" 4 5 var _ Queue = (*Capacity)(nil) 6 7 // Capacity 固定长度的队列 8 type Capacity struct { 9 l []IPriority 10 location *time.Location 11 count int 12 } 13 14 func NewCapacity(capacity int) *Capacity { 15 if capacity <= 0 { 16 capacity = minCapacity 17 } 18 if capacity > maxCapacity { 19 capacity = maxCapacity 20 } 21 return &Capacity{ 22 location: time.Local, 23 l: make([]IPriority, capacity), 24 } 25 } 26 27 func (sq *Capacity) SetLocation(l *time.Location) { 28 sq.location = l 29 } 30 31 func (sq *Capacity) Len() int { 32 return sq.count 33 } 34 35 func (sq *Capacity) Push(elem any) error { 36 if sq.count == len(sq.l) { 37 sq.resize() 38 } 39 p := NewPriorityItem(elem, WithUnixNano(sq.location)) 40 index := sq.getInsertIndex(p.PValue(), 0, sq.count-1) 41 copy(sq.l[index+1:], sq.l[index:]) 42 sq.l[index] = p 43 sq.count++ 44 return nil 45 } 46 47 func (sq *Capacity) Add(elem any) error { 48 return sq.Push(elem) 49 } 50 51 func (sq *Capacity) Peek() any { 52 if sq.Empty() { 53 return nil 54 } 55 return sq.l[0].GValue() 56 } 57 58 // Get index -1 refers to the last. 59 func (sq *Capacity) Get(index int) any { 60 if index < 0 || index >= sq.count { 61 return nil 62 } 63 return sq.l[index].GValue() 64 } 65 66 // Find return index -1 not found. 67 func (sq *Capacity) Find(fn IndexFunc) (any, int) { 68 for i := 0; i < sq.count; i++ { 69 if fn(sq.l[i], i) { 70 return sq.l[i], i 71 } 72 } 73 return nil, -1 74 } 75 76 func (sq *Capacity) Foreach(fn IndexFunc) { 77 for i := 0; i < sq.count; i++ { 78 if fn(sq.l[i], i) { 79 return 80 } 81 } 82 } 83 84 func (sq *Capacity) Pop() any { 85 if sq.Empty() { 86 return nil 87 } 88 ret := sq.l[0] 89 copy(sq.l[0:], sq.l[1:]) 90 sq.count-- 91 if sq.count < 0 { 92 sq.count = 0 93 } else { 94 sq.l[sq.count] = nil 95 } 96 return ret.GValue() 97 } 98 99 func (sq *Capacity) Empty() bool { 100 return sq.count <= 0 101 } 102 103 func (sq *Capacity) ToList() []any { 104 var ( 105 buf = make([]any, sq.count) 106 ) 107 for i := 0; i < sq.count; i++ { 108 buf[i] = sq.Get(i) 109 } 110 return buf 111 } 112 113 func (sq *Capacity) resize() { 114 if sq.count >= maxCapacity { 115 return 116 } 117 size := sq.count << 1 118 if size > maxCapacity { 119 size = maxCapacity 120 } 121 newBuf := make([]IPriority, size) 122 123 copy(newBuf, sq.l[:sq.count]) 124 125 sq.l = newBuf 126 } 127 128 func (sq *Capacity) getInsertIndex(priority int64, leftIndex, rightIndex int) (index int) { 129 if sq.count <= 0 { 130 // 如果当前优先级切片没有元素,则插入的index就是0 131 return 0 132 } 133 134 length := rightIndex - leftIndex 135 if sq.l[leftIndex].PValue() >= priority { 136 // 如果当前切片中最小的元素都超过了插入的优先级,则插入位置应该是最左边 137 return leftIndex 138 } 139 140 if sq.l[rightIndex].PValue() <= priority { 141 // 如果当前切片中最大的元素都没超过插入的优先级,则插入位置应该是最右边 142 return rightIndex + 1 143 } 144 145 if length == 1 && sq.l[leftIndex].PValue() < priority && sq.l[rightIndex].PValue() >= priority { 146 // 如果插入的优先级刚好在仅有的两个优先级之间,则中间的位置就是插入位置 147 return leftIndex + 1 148 } 149 150 middleVal := sq.l[leftIndex+length/2].PValue() 151 152 // 这里用二分法递归的方式,一直寻找正确的插入位置 153 if priority <= middleVal { 154 return sq.getInsertIndex(priority, leftIndex, leftIndex+length/2) 155 } 156 return sq.getInsertIndex(priority, leftIndex+length/2, rightIndex) 157 }