From 38d75633d9e7cf88c42096f1518f2f5e53fe87cc Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Sun, 27 Mar 2022 10:23:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=B9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- collections/circlequeue.go | 55 +++++++++++++++++++++++++ collections/circlequeue_test.go | 22 ++++++++++ collections/queue.go | 71 ++++++++++++++++++++++++++++++++ collections/queue_test.go | 1 + collections/stack.go | 73 +++++++++++++++++++++++++++++++++ collections/stack_test.go | 24 +++++++++++ 6 files changed, 246 insertions(+) create mode 100644 collections/circlequeue.go create mode 100644 collections/circlequeue_test.go create mode 100644 collections/queue.go create mode 100644 collections/queue_test.go create mode 100644 collections/stack.go create mode 100644 collections/stack_test.go diff --git a/collections/circlequeue.go b/collections/circlequeue.go new file mode 100644 index 0000000..1b18703 --- /dev/null +++ b/collections/circlequeue.go @@ -0,0 +1,55 @@ +package collections + +import "fmt" + +type CircleQueue struct { + data []interface{} + cap int + front int + rear int +} + +func NewCircleQueue(cap int) *CircleQueue { + cap++ + + return &CircleQueue{ + data: make([]interface{}, cap), + cap: cap, + } +} + +func (q *CircleQueue) Push(data interface{}) bool { + if (q.rear+1)%q.cap == q.front { + return false + } + + q.data[q.rear] = data + q.rear = (q.rear + 1) % q.cap + return true +} +func (q *CircleQueue) Pop() interface{} { + if q.rear == q.front { + return nil + } + + data := q.data[q.front] + q.data[q.front] = nil + q.front = (q.front + 1) % q.cap + return data +} + +func (q *CircleQueue) Size() int { + return (q.rear - q.front + q.cap) % q.cap +} + +func (q *CircleQueue) IsFull() bool { + return (q.rear+1)%q.cap == q.front +} + +func (q *CircleQueue) IsEmpty() bool { + return q.front == q.rear +} + +func (q *CircleQueue) Show() string { + return fmt.Sprintf("%v", q.data) +} diff --git a/collections/circlequeue_test.go b/collections/circlequeue_test.go new file mode 100644 index 0000000..c8218ef --- /dev/null +++ b/collections/circlequeue_test.go @@ -0,0 +1,22 @@ +package collections + +import "testing" + +func TestCircleQueue(t *testing.T) { + q := NewCircleQueue(10) + + t.Log("Size:", q.Size()) + for i := 0; i < 10; i++ { + t.Log(q.Push(i)) + } + + t.Log("Size:", q.Size()) + t.Log("IsFull:", q.IsFull()) + t.Log("Show:", q.Show()) + + q.Pop() + q.Push(11) + q.Pop() + + t.Log("Show:", q.Show()) +} diff --git a/collections/queue.go b/collections/queue.go new file mode 100644 index 0000000..4312c8b --- /dev/null +++ b/collections/queue.go @@ -0,0 +1,71 @@ +package collections + +import "sync" + +// 数组队列,先进先出 +type ArrayQueue struct { + array []interface{} // 底层切片 + size int // 队列的元素数量 + lock sync.Mutex // 为了并发安全使用的锁 +} + +func NewArrayQueue[T any]() *ArrayQueue { + return &ArrayQueue{} +} + +// 入队 +func (queue *ArrayQueue) Add(v interface{}) { + queue.lock.Lock() + defer queue.lock.Unlock() + + // 放入切片中,后进的元素放在数组最后面 + queue.array = append(queue.array, v) + + // 队中元素数量+1 + queue.size = queue.size + 1 +} + +// 出队 +func (queue *ArrayQueue) Remove() interface{} { + queue.lock.Lock() + defer queue.lock.Unlock() + + // 队中元素已空 + if queue.size == 0 { + panic("empty") + } + + // 队列最前面元素 + v := queue.array[0] + + /* 直接原位移动,但缩容后继的空间不会被释放 + for i := 1; i < queue.size; i++ { + // 从第一位开始进行数据移动 + queue.array[i-1] = queue.array[i] + } + // 原数组缩容 + queue.array = queue.array[0 : queue.size-1] + */ + + // 创建新的数组,移动次数过多 + newArray := make([]interface{}, queue.size-1) + for i := 1; i < queue.size; i++ { + // 从老数组的第一位开始进行数据移动 + newArray[i-1] = queue.array[i] + } + queue.array = newArray + + // 队中元素数量-1 + queue.size = queue.size - 1 + return v +} + +// 栈大小 +func (queue *ArrayQueue) Size() int { + return queue.size +} + +// 栈是否为空 +func (queue *ArrayQueue) IsEmpty() bool { + return queue.size == 0 +} diff --git a/collections/queue_test.go b/collections/queue_test.go new file mode 100644 index 0000000..0224625 --- /dev/null +++ b/collections/queue_test.go @@ -0,0 +1 @@ +package collections diff --git a/collections/stack.go b/collections/stack.go new file mode 100644 index 0000000..05de5aa --- /dev/null +++ b/collections/stack.go @@ -0,0 +1,73 @@ +package collections + +import "sync" + +type ArrayStack struct { + array []interface{} // 底层切片 + size int // 栈的元素数量 + lock sync.Mutex // 为了并发安全使用的锁 +} + +func NewArrayStack[T any]() *ArrayStack { + return &ArrayStack{} +} + +// 入栈 +func (stack *ArrayStack) Push(v interface{}) { + stack.lock.Lock() + defer stack.lock.Unlock() + + // 放入切片中,后进的元素放在数组最后面 + stack.array = append(stack.array, v) + + // 栈中元素数量+1 + stack.size = stack.size + 1 +} + +func (stack *ArrayStack) Pop() interface{} { + stack.lock.Lock() + defer stack.lock.Unlock() + + if stack.size == 0 { + panic("empty") + } + + // 栈顶元素 + v := stack.array[stack.size-1] + + // 切片收缩,但可能占用空间越来越大 + //stack.array = stack.array[0 : stack.size-1] + + // 创建新的数组,空间占用不会越来越大,但可能移动元素次数过多 + newArray := make([]interface{}, stack.size-1, stack.size-1) + for i := 0; i < stack.size-1; i++ { + newArray[i] = stack.array[i] + } + stack.array = newArray + + // 栈中元素数量-1 + stack.size = stack.size - 1 + return v +} + +// 获取栈顶元素 +func (stack *ArrayStack) Peek() interface{} { + // 栈中元素已空 + if stack.size == 0 { + panic("empty") + } + + // 栈顶元素值 + v := stack.array[stack.size-1] + return v +} + +// 栈大小 +func (stack *ArrayStack) Size() int { + return stack.size +} + +// 栈是否为空 +func (stack *ArrayStack) IsEmpty() bool { + return stack.size == 0 +} diff --git a/collections/stack_test.go b/collections/stack_test.go new file mode 100644 index 0000000..a396bf3 --- /dev/null +++ b/collections/stack_test.go @@ -0,0 +1,24 @@ +package collections_test + +import ( + "testing" + + "github.com/charlienet/go-mixed/collections" +) + +func TestStack(t *testing.T) { + arrayStack := new(collections.ArrayStack) + arrayStack.Push("cat") + arrayStack.Push("dog") + arrayStack.Push("hen") + + t.Log("size:", arrayStack.Size()) + t.Log("pop:", arrayStack.Pop()) + t.Log("pop:", arrayStack.Pop()) + t.Log("size:", arrayStack.Size()) + arrayStack.Push("drag") + t.Log("pop:", arrayStack.Pop()) + arrayStack.Push("test") + s := arrayStack.Pop().(string) + t.Log(s) +}