gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/container/queue.go (about)

     1  package container
     2  
     3  import _ "unsafe"
     4  
     5  //go:linkname goPanicIndex runtime.goPanicIndex
     6  func goPanicIndex(x int, y int)
     7  
     8  //go:linkname goPanicSliceAcap runtime.goPanicSliceAcap
     9  func goPanicSliceAcap(x int, y int)
    10  
    11  //go:linkname goPanicSliceB runtime.goPanicSliceB
    12  func goPanicSliceB(x int, y int)
    13  
    14  type Queue[E any] struct {
    15  	raw  []E
    16  	head int
    17  	tail int
    18  	len  int
    19  	cap  int
    20  }
    21  
    22  func NewQueue[E any](cap int) *Queue[E] {
    23  	return &Queue[E]{
    24  		raw: make([]E, cap, cap),
    25  		cap: cap,
    26  	}
    27  }
    28  
    29  func (q *Queue[E]) Init(cap int) {
    30  	*q = Queue[E]{
    31  		raw: make([]E, cap, cap),
    32  		cap: cap,
    33  	}
    34  }
    35  
    36  func (q *Queue[E]) IsNil() bool {
    37  	return q.raw == nil
    38  }
    39  
    40  // Len 返回队列的长度
    41  func (q *Queue[E]) Len() int {
    42  	return q.len
    43  }
    44  
    45  // Cap 返回队列的容量
    46  func (q *Queue[E]) Cap() int {
    47  	return q.cap
    48  }
    49  
    50  // Empty 判断队列是否为空
    51  func (q *Queue[E]) Empty() bool {
    52  	return q.len == 0
    53  }
    54  
    55  // Full 判断队列是否为满
    56  func (q *Queue[E]) Full() bool {
    57  	return q.len == q.cap
    58  }
    59  
    60  func (q *Queue[E]) checkIndex(i int) {
    61  	if i >= q.len || i < 0 {
    62  		goPanicIndex(i, q.len)
    63  	}
    64  }
    65  
    66  func (q *Queue[E]) tailIndex() int {
    67  	tail := q.tail - 1
    68  	if tail < 0 {
    69  		tail = q.cap - 1
    70  	}
    71  	return tail
    72  }
    73  
    74  func (q *Queue[E]) rawIndex(i int) int {
    75  	if i += q.head; i >= q.cap {
    76  		return i - q.cap
    77  	}
    78  	return i
    79  }
    80  
    81  // Get 获取队列指定索引位置的元素
    82  func (q *Queue[E]) Get(i int) E {
    83  	q.checkIndex(i)
    84  	return q.raw[q.rawIndex(i)]
    85  }
    86  
    87  // Use 获取队列指定索引位置的元素指针
    88  func (q *Queue[E]) Use(i int) *E {
    89  	q.checkIndex(i)
    90  	return &q.raw[q.rawIndex(i)]
    91  }
    92  
    93  // Head 获取队列头部的元素,返回值 exist 为 false 表示队列为空
    94  func (q *Queue[E]) Head() (e E, exist bool) {
    95  	if q.len > 0 {
    96  		return q.raw[q.head], true
    97  	}
    98  	return
    99  }
   100  
   101  // UseHead 获取队列头部的元素指针,返回 nil 表示队列为空
   102  func (q *Queue[E]) UseHead() *E {
   103  	if q.len > 0 {
   104  		return &q.raw[q.head]
   105  	}
   106  	return nil
   107  }
   108  
   109  // Tail 获取队列尾部的元素,返回值 exist 为 false 表示队列为空
   110  func (q *Queue[E]) Tail() (e E, exist bool) {
   111  	if q.len > 0 {
   112  		return q.raw[q.tailIndex()], true
   113  	}
   114  	return
   115  }
   116  
   117  // UseTail 获取队列尾部的元素指针,返回 nil 表示队列为空
   118  func (q *Queue[E]) UseTail() *E {
   119  	if q.len > 0 {
   120  		return &q.raw[q.tailIndex()]
   121  	}
   122  	return nil
   123  }
   124  
   125  // Slice 获取队列空间指定范围内对应的切片,返回值 prefix, suffix 代表队列空间的前半部分(在范
   126  // 围内头部指针后的空间)和后半部分(在范围内头部指针前的空间)
   127  func (q *Queue[E]) Slice(start, end int) (prefix, suffix []E) {
   128  	if end < 0 {
   129  		end = q.len
   130  	} else if end > q.cap {
   131  		goPanicSliceAcap(end, q.cap)
   132  	}
   133  	if start < 0 {
   134  		start = 0
   135  	} else if start > end {
   136  		goPanicSliceB(start, end)
   137  	}
   138  	if start += q.head; start >= q.cap {
   139  		start -= q.cap
   140  		end += q.head - q.cap
   141  		return nil, q.raw[start:end]
   142  	} else if end += q.head; end > q.cap {
   143  		end -= q.cap
   144  		return q.raw[start:], q.raw[:end]
   145  	} else {
   146  		return q.raw[start:end], nil
   147  	}
   148  }
   149  
   150  // Copy 拷贝队列指定位置后的元素到指定切片,返回拷贝元素的个数
   151  func (q *Queue[E]) Copy(dst []E, start int) (n int) {
   152  	if start < 0 {
   153  		start = 0
   154  	} else if start > q.len {
   155  		goPanicSliceB(start, q.len)
   156  	}
   157  	end := start + len(dst)
   158  	if end > q.len {
   159  		end = q.len
   160  	}
   161  	if start += q.head; start >= q.cap {
   162  		start -= q.cap
   163  		end += q.head - q.cap
   164  		return copy(dst, q.raw[start:end])
   165  	} else if end += q.head; end > q.cap {
   166  		end -= q.cap
   167  		n = copy(dst, q.raw[start:])
   168  		n += copy(dst[n:], q.raw[:end])
   169  		return
   170  	} else {
   171  		return copy(dst, q.raw[start:end])
   172  	}
   173  }
   174  
   175  // Range 遍历队列中的所有元素,fn 为遍历函数,遍历函数返回 false 则终止遍历,并使得此函数返回
   176  // false。若遍历过程中没有因遍历函数终止遍历(即遍历完所有元素),则此函数返回 true
   177  func (q *Queue[E]) Range(fn func(i int, e E) bool) bool {
   178  	head := q.head
   179  	for i := 0; i < q.len; i++ {
   180  		if !fn(i, q.raw[head]) {
   181  			return false
   182  		}
   183  		if head++; head == q.cap {
   184  			head = 0
   185  		}
   186  	}
   187  	return true
   188  }
   189  
   190  func (q *Queue[E]) tailGrow() {
   191  	if q.tail++; q.tail == q.cap {
   192  		q.tail = 0
   193  	}
   194  	q.len++
   195  }
   196  
   197  func (q *Queue[E]) headGrow() {
   198  	if q.head--; q.head < 0 {
   199  		q.head = q.cap - 1
   200  	}
   201  	q.len++
   202  }
   203  
   204  // Append 在队列尾部添加元素,队列满则不执行任何操作
   205  func (q *Queue[E]) Append(e E) {
   206  	if q.len == q.cap {
   207  		return
   208  	}
   209  	q.raw[q.tail] = e
   210  	q.tailGrow()
   211  }
   212  
   213  // Append 在队列尾部添加元素,队列满则抛出错误
   214  func (q *Queue[E]) MustAppend(e E) {
   215  	if q.len == q.cap {
   216  		goPanicSliceAcap(q.len+1, q.cap)
   217  	}
   218  	q.raw[q.tail] = e
   219  	q.tailGrow()
   220  }
   221  
   222  // Push 在队列尾部添加元素,添加成功返回 true,由于队列满添加失败返回 false
   223  func (q *Queue[E]) Push(e E) bool {
   224  	if q.len == q.cap {
   225  		return false
   226  	}
   227  	q.raw[q.tail] = e
   228  	q.tailGrow()
   229  	return true
   230  }
   231  
   232  // Alloc 在队列尾部申请一个元素的空间,申请成功返回此元素空间的地址,由于队列满申请失败返回 nil
   233  func (q *Queue[E]) Alloc() (p *E) {
   234  	if q.len == q.cap {
   235  		return nil
   236  	}
   237  	p = &q.raw[q.tail]
   238  	q.tailGrow()
   239  	return
   240  }
   241  
   242  // Unshift 在队列头部添加元素,添加成功返回 true,由于队列满添加失败返回 false
   243  func (q *Queue[E]) Unshift(e E) bool {
   244  	if q.len == q.cap {
   245  		return false
   246  	}
   247  	q.headGrow()
   248  	q.raw[q.head] = e
   249  	return true
   250  }
   251  
   252  // UnshiftAlloc 在队列头部申请一个元素的空间,申请成功返回此元素空间的地址,由于队列满申请失败
   253  // 返回 nil
   254  func (q *Queue[E]) UnshiftAlloc() *E {
   255  	if q.len == q.cap {
   256  		return nil
   257  	}
   258  	q.headGrow()
   259  	return &q.raw[q.head]
   260  }
   261  
   262  // Pop 移除队列尾部的一个元素,返回被移除的元素以及是否有元素被移除
   263  func (q *Queue[E]) Pop() (e E, ok bool) {
   264  	if q.len == 0 {
   265  		return
   266  	}
   267  	if q.tail--; q.tail < 0 {
   268  		q.tail = q.cap - 1
   269  	}
   270  	e, ok = q.raw[q.tail], true
   271  	q.len--
   272  	return
   273  }
   274  
   275  // Shift 移除队列头部的一个元素,返回被移除的元素以及是否有元素被移除
   276  func (q *Queue[E]) Shift() (e E, ok bool) {
   277  	if q.len == 0 {
   278  		return
   279  	}
   280  	e, ok = q.raw[q.head], true
   281  	if q.head++; q.head == q.cap {
   282  		q.head = 0
   283  	}
   284  	q.len--
   285  	return
   286  }
   287  
   288  // ShiftTo 将队列头部开始的多个元素移除到指定切片中,返回移除元素的个数
   289  func (q *Queue[E]) ShiftTo(dst []E) (n int) {
   290  	end := len(dst)
   291  	if end > q.len {
   292  		end = q.len
   293  	}
   294  	if end += q.head; end > q.cap {
   295  		end -= q.cap
   296  		n = copy(dst, q.raw[q.head:])
   297  		n += copy(dst[n:], q.raw[:end])
   298  	} else {
   299  		n = copy(dst, q.raw[q.head:end])
   300  	}
   301  	q.len -= n
   302  	q.head = end
   303  	return
   304  }
   305  
   306  // ShiftAll 将所有元素移除到切片中,并返回此切片
   307  func (q *Queue[E]) ShiftAll() []E {
   308  	es := make([]E, q.len)
   309  	q.ShiftTo(es)
   310  	return es
   311  }
   312  
   313  // Set 设置指定索引位置的元素
   314  func (q *Queue[E]) Set(i int, e E) {
   315  	q.checkIndex(i)
   316  	q.raw[q.rawIndex(i)] = e
   317  }
   318  
   319  // Swap 交换指定索引位置的元素
   320  func (q *Queue[E]) Swap(i, j int) {
   321  	q.checkIndex(i)
   322  	q.checkIndex(j)
   323  	i, j = q.rawIndex(i), q.rawIndex(j)
   324  	q.raw[i], q.raw[j] = q.raw[j], q.raw[i]
   325  }
   326  
   327  func (q *Queue[E]) Removes(n int) int {
   328  	if n > q.len {
   329  		n = q.len
   330  	}
   331  	if q.tail -= n; q.tail < 0 {
   332  		q.tail += q.cap
   333  	}
   334  	q.len -= n
   335  	return n
   336  }
   337  
   338  func (q *Queue[E]) ShiftRemoves(n int) int {
   339  	if n > q.len {
   340  		n = q.len
   341  	}
   342  	if q.head += n; q.head >= q.cap {
   343  		q.head -= q.cap
   344  	}
   345  	q.len -= n
   346  	return n
   347  }
   348  
   349  // Clear 清空队列
   350  func (q *Queue[E]) Clear() {
   351  	q.head = q.tail
   352  	q.len = 0
   353  }
   354  
   355  // Clear 重置队列。与清空队列类似,但会重置头部指针和尾部指针到队列空间的起始处
   356  func (q *Queue[E]) Reset() {
   357  	q.head, q.tail = 0, 0
   358  	q.len = 0
   359  }