mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-04 06:54:45 +08:00
新增循环队列
This commit is contained in:
159
util/queue/squeue.go
Normal file
159
util/queue/squeue.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package queue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
这是一个循环队列
|
||||||
|
*/
|
||||||
|
type SQueue[ElementType any] struct {
|
||||||
|
elements []ElementType
|
||||||
|
head int
|
||||||
|
tail int
|
||||||
|
locker sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
//游标,通过该游标获取数据
|
||||||
|
type SCursor[ElementType any] struct {
|
||||||
|
pos int
|
||||||
|
squeue *SQueue[ElementType]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSQueue[ElementType any](maxElementNum int) *SQueue[ElementType]{
|
||||||
|
queue := &SQueue[ElementType]{}
|
||||||
|
queue.elements = make([]ElementType,maxElementNum+1)
|
||||||
|
|
||||||
|
return queue
|
||||||
|
}
|
||||||
|
|
||||||
|
//游标移动到队首
|
||||||
|
func (s *SCursor[ElementType]) First(){
|
||||||
|
s.squeue.locker.RLock()
|
||||||
|
defer s.squeue.locker.RUnlock()
|
||||||
|
s.pos = s.squeue.head
|
||||||
|
}
|
||||||
|
|
||||||
|
//从当前位置移动游标,注意如果在多协程读或者pop时,可能会导致游标失效
|
||||||
|
func (s *SCursor[ElementType]) Next() (elem ElementType,ret bool){
|
||||||
|
s.squeue.locker.RLock()
|
||||||
|
defer s.squeue.locker.RUnlock()
|
||||||
|
|
||||||
|
if s.pos == s.squeue.tail {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.pos++
|
||||||
|
s.pos = (s.pos)%(len(s.squeue.elements))
|
||||||
|
return s.squeue.elements[s.pos],true
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取队列元数个数
|
||||||
|
func (s *SQueue[ElementType]) Len() int {
|
||||||
|
s.locker.RLock()
|
||||||
|
defer s.locker.RUnlock()
|
||||||
|
|
||||||
|
if s.head <= s.tail {
|
||||||
|
return s.head - s.tail
|
||||||
|
}
|
||||||
|
|
||||||
|
//(len(s.elements)-1-s.head)+(s.tail+1)
|
||||||
|
return len(s.elements)-s.head+s.tail
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取游标,默认是队首
|
||||||
|
func (s *SQueue[ElementType]) GetCursor() (cur SCursor[ElementType]){
|
||||||
|
s.locker.RLock()
|
||||||
|
defer s.locker.RUnlock()
|
||||||
|
|
||||||
|
cur.squeue = s
|
||||||
|
cur.pos = s.head
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取指定位置的游标
|
||||||
|
func (s *SQueue[ElementType]) GetPosCursor(pos int) (cur SCursor[ElementType],ret bool){
|
||||||
|
s.locker.RLock()
|
||||||
|
defer s.locker.RUnlock()
|
||||||
|
|
||||||
|
if s.head < s.tail {
|
||||||
|
if pos<=s.head || pos>s.tail{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true
|
||||||
|
cur.squeue = s
|
||||||
|
cur.pos = pos
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos >s.tail && pos <=s.head {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.squeue = s
|
||||||
|
cur.pos = pos
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//从队首移除掉指定数量元素
|
||||||
|
func (s *SQueue[ElementType]) RemoveElement(elementNum int) (removeNum int) {
|
||||||
|
s.locker.Lock()
|
||||||
|
defer s.locker.Unlock()
|
||||||
|
|
||||||
|
for ;s.head == s.tail && removeNum >= elementNum;{
|
||||||
|
removeNum++
|
||||||
|
s.head++
|
||||||
|
s.head = s.head%len(s.elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//从队首Pop元素
|
||||||
|
func (s *SQueue[ElementType]) Pop() (elem ElementType,ret bool){
|
||||||
|
s.locker.Lock()
|
||||||
|
defer s.locker.Unlock()
|
||||||
|
|
||||||
|
if s.head == s.tail {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.head++
|
||||||
|
s.head = s.head%len(s.elements)
|
||||||
|
return s.elements[s.head],true
|
||||||
|
}
|
||||||
|
|
||||||
|
//从队尾Push数据
|
||||||
|
func (s *SQueue[ElementType]) Push(elem ElementType) bool {
|
||||||
|
s.locker.Lock()
|
||||||
|
defer s.locker.Unlock()
|
||||||
|
|
||||||
|
nextPos := (s.tail+1) % len(s.elements)
|
||||||
|
if nextPos == s.head {
|
||||||
|
//is full
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
s.tail = nextPos
|
||||||
|
s.elements[s.tail] = elem
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断队列是否为空
|
||||||
|
func (s *SQueue[ElementType]) IsEmpty() bool{
|
||||||
|
s.locker.RLock()
|
||||||
|
defer s.locker.RUnlock()
|
||||||
|
|
||||||
|
return s.head == s.tail
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断队列是否已满
|
||||||
|
func (s *SQueue[ElementType]) IsFull() bool{
|
||||||
|
s.locker.RLock()
|
||||||
|
defer s.locker.RUnlock()
|
||||||
|
|
||||||
|
nextPos := (s.tail+1) % len(s.elements)
|
||||||
|
return nextPos == s.head
|
||||||
|
}
|
||||||
|
|
||||||
52
util/queue/syncqueue_test.go
Normal file
52
util/queue/syncqueue_test.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package queue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Example(t *testing.T) {
|
||||||
|
//1.创建阶列
|
||||||
|
queue := NewSQueue[int](5)
|
||||||
|
|
||||||
|
//2.判断是否为空
|
||||||
|
t.Log("is empty :", queue.IsEmpty())
|
||||||
|
t.Log("is full :", queue.IsFull())
|
||||||
|
|
||||||
|
//3.游标使用
|
||||||
|
cursor := queue.GetCursor()
|
||||||
|
cursor.First()
|
||||||
|
for {
|
||||||
|
elem, ret := cursor.Next()
|
||||||
|
if ret == false {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t.Log("elem:", elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
//4.push数据
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
t.Log("push:", queue.Push(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("is empty :", queue.IsEmpty())
|
||||||
|
t.Log("is full :", queue.IsFull())
|
||||||
|
|
||||||
|
//5.游标遍历
|
||||||
|
cursor.First()
|
||||||
|
for {
|
||||||
|
elem, ret := cursor.Next()
|
||||||
|
if ret == false {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t.Log("elem:", elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
//pop数据所有
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
elem, ret := queue.Pop()
|
||||||
|
t.Log("pop:", elem, "-", ret, " len:", queue.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("is empty :", queue.IsEmpty())
|
||||||
|
t.Log("is full :", queue.IsFull())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user