Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增数据结构:栈 #53

Merged
merged 2 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,18 @@
- [x] Map相关操作
- HasKey 是否拥有某个Key。
- MapKeys 将一个Map的所有Key转换成数组返回。
- [x] 自定义Set(拥有的元素不可重复,类似于Java中的HashSet),添加的元素必须是可比较的,即实现了标准接口中的comparable,这也可以理解,如果元素不可比较,怎么知道是否重复是否已经存在了呢?
- [x] 数据结构:Set(拥有的元素不可重复,类似于Java中的HashSet),添加的元素必须是可比较的,即实现了标准接口中的comparable,这也可以理解,如果元素不可比较,怎么知道是否重复是否已经存在了呢?
- Add 添加元素。
- Remove 删除元素。
- Clear 清空所有元素。
- Contains 是否在已经存在的元素中。
- Len 获得Set集合中元素的数量。
- Empty 判断Set元素是否是空的。
- [x] 数据结构:Stack(栈),先进后出,后进先出。
- Push 入栈。
- Pop 出栈。
- Peek 查看栈顶元素。
- Size 获得栈中元素的数量。
- [x] Slice切片相关
- SlicePagination 切片分页,返回一个分好页的二维数组,可指定页大小。
- Contains 包含某个元素。
Expand All @@ -71,6 +76,7 @@
- Intersection 两个切片的交集。
- Union 两个切片的合集,如果遇到重复元素,只保留1个。
- Diff 两个切片的差集,以第一个参数为基准。
- SplitCounter 根据给定总数和页大小,生成一个二维切片。许多时候我们需要这样快速完成分页,直接往其中填写内容,这就非常方便。
- [x] 结构体相关操作
- JoinStructsField 将任意结构体切片中的指定字段的值使用英文逗号拼接成一个字符串,例如:用户列表中,所有用户ID拼成一个字符串。
- PickStructsField 将任意结构体切片中的指定字段的值提取出来形成一个保持原类型的数组,例如:用户列表中,所有用户ID提取成一个用户ID数组。
Expand Down
4 changes: 2 additions & 2 deletions snowflake.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (

const (
epoch = int64(1577808000000) // 设置起始时间(时间戳/毫秒):2020-01-01 00:00:00,有效期69年
timestampBits = uint(41) // 时间戳占用位数
timestampBits41 = uint(41) // 时间戳占用位数
datacenterIdBits = uint(2) // 数据中心id所占位数
workerIdBits = uint(7) // 机器id所占位数
sequenceBits = uint(12) // 序列所占的位数
timestampMax = int64(-1 ^ (-1 << timestampBits)) // 时间戳最大值
timestampMax = int64(-1 ^ (-1 << timestampBits41)) // 时间戳最大值
datacenterIdMax = int64(-1 ^ (-1 << datacenterIdBits)) // 支持的最大数据中心id数量
workerIdMax = int64(-1 ^ (-1 << workerIdBits)) // 支持的最大机器id数量
sequenceMask = int64(-1 ^ (-1 << sequenceBits)) // 支持的最大序列id数量
Expand Down
43 changes: 43 additions & 0 deletions stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package kgo

import (
"errors"
"reflect"
)

type Stack[T any] struct {
elements []any
}

// NewStack 创建一个新的栈
func NewStack[T any]() *Stack[T] {
return &Stack[T]{}
}

// Push 向栈中添加元素
func (s *Stack[T]) Push(element T) {
s.elements = append(s.elements, element)
}

// Pop 从栈中移除并返回栈顶元素
func (s *Stack[T]) Pop() (T, error) {
if len(s.elements) == 0 {
return reflect.Zero(reflect.TypeOf(new(T))).Interface().(T), errors.New("stack is empty")
}
element := s.elements[len(s.elements)-1]
s.elements = s.elements[:len(s.elements)-1]
return element.(T), nil
}

// Peek 返回栈顶元素但不移除它
func (s *Stack[T]) Peek() (T, error) {
if len(s.elements) == 0 {
return reflect.Zero(reflect.TypeOf(new(T))).Interface().(T), errors.New("stack is empty")
}
return s.elements[len(s.elements)-1].(T), nil
}

// Size 返回栈中元素的数量
func (s *Stack[T]) Size() int {
return len(s.elements)
}
62 changes: 62 additions & 0 deletions stack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package kgo

import "testing"

func TestNewStack(t *testing.T) {
stack := NewStack[int]()
if stack != nil {
t.Log("stack is not nil")
} else {
t.Errorf("stack is nil")
}
}

func TestStack_Push(t *testing.T) {
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
if stack.Size() != 3 {
t.Errorf("stack size is not 3")
} else {
t.Log("stack size is 3")
}
}

func TestStack_Pop(t *testing.T) {
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
element, err := stack.Pop()
if err != nil {
t.Errorf("pop error: %s", err)
} else if element != 3 {
t.Errorf("pop element is not 3")
}
}

func TestStack_Peek(t *testing.T) {
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
element, err := stack.Peek()
if err != nil {
t.Errorf("peek error: %s", err)
} else if element != 3 {
t.Errorf("peek element is not 3")
}
}

func TestStack_Size(t *testing.T) {
stack := NewStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
if stack.Size() != 3 {
t.Errorf("stack size is not 3")
} else {
t.Log("stack size is 3")
}
}
Loading