From 72c06a01cf8e0042196748004b977144228a612d Mon Sep 17 00:00:00 2001 From: hlccd <56643462+hlccd@users.noreply.github.com> Date: Sat, 23 Oct 2021 12:33:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86=E7=8E=AF=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0,=E4=BF=9D=E8=AF=81=E4=BA=86=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E6=97=B6=E7=9A=84=E6=95=B0=E6=8D=AE=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E6=80=A7,=E4=BF=AE=E6=94=B9=E4=BA=86=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E4=B8=AD=E6=B3=A8=E9=87=8A=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- goSTL/data_structure/list/list.go | 3 +- goSTL/data_structure/list/node.go | 6 +- goSTL/data_structure/ring/node.go | 170 +++++++++++++++++++ goSTL/data_structure/ring/ring.go | 271 ++++++++++++++++++++++++++++++ 4 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 goSTL/data_structure/ring/node.go create mode 100644 goSTL/data_structure/ring/ring.go diff --git a/goSTL/data_structure/list/list.go b/goSTL/data_structure/list/list.go index 1b0913a..b083c72 100644 --- a/goSTL/data_structure/list/list.go +++ b/goSTL/data_structure/list/list.go @@ -1,6 +1,6 @@ package list -//@Title deque +//@Title list //@Description // list链表容器包 // 链表将所有结点通过指针的方式串联起来,从而使得其整体保持一个线性状态 @@ -313,6 +313,7 @@ func (l *list) Get(idx uint64) (e interface{}) { //@receiver l *list 接收者的list指针 //@param idx uint64 被修改的结点位置(从0开始) //@param e interface{} 修改后当元素 +//@return nil func (l *list) Set(idx uint64, e interface{}) { if l == nil { l = New() diff --git a/goSTL/data_structure/list/node.go b/goSTL/data_structure/list/node.go index 50dbfed..05c933d 100644 --- a/goSTL/data_structure/list/node.go +++ b/goSTL/data_structure/list/node.go @@ -6,7 +6,7 @@ package list // 该部分包含了链表的节点 // 链表的增删都通过节点的增删完成 // 结点间可插入其前后节点,并同时将两结点建立连接 -// 增删之后会返回对应的首尾节点以辅助deque容器仍持有首尾节点 +// 增删之后会返回对应的首尾节点以辅助list容器仍持有首尾节点 // 为保证效率问题,设定了一定的冗余量,即每个节点设定2^10的空间以存放元素 //链表的node节点结构体 @@ -18,7 +18,7 @@ type node struct { next *node //后结点指针 } -//list链表容器接口 +//node结点容器接口 //存放了node容器可使用的函数 //对应函数介绍见下方 @@ -115,7 +115,7 @@ func (n *node) insertNext(next *node) { n.next = next } -//@title insertNext +//@title erase //@description // 以node结点做接收者 // 销毁该结点 diff --git a/goSTL/data_structure/ring/node.go b/goSTL/data_structure/ring/node.go new file mode 100644 index 0000000..6bf20c0 --- /dev/null +++ b/goSTL/data_structure/ring/node.go @@ -0,0 +1,170 @@ +package ring + +//@Title ring +//@Description +// ring环容器包 +// 该部分包含了环的节点 +// 环的增删都通过节点的增删完成 +// 结点间可插入其前后节点,并同时将两结点建立连接 + +//环的node节点结构体 +//pre和next是该节点的前后两个节点的指针 +//用以保证环整体是相连的 +type node struct { + data interface{} //结点所承载的元素 + pre *node //前结点指针 + next *node //后结点指针 +} + +//node结点容器接口 +//存放了node容器可使用的函数 +//对应函数介绍见下方 + +type noder interface { + preNode() (m *node) //返回前结点指针 + nextNode() (m *node) //返回后结点指针 + insertPre(pre *node) //在该结点前插入结点并建立连接 + insertNext(next *node) //在该结点后插入结点并建立连接 + erase() //删除该结点,并使该结点前后两结点建立连接 + value() (e interface{}) //返回该结点所承载的元素 + setValue(e interface{}) //修改该结点承载元素为e +} + +//@title newNode +//@description +// 新建一个自环结点并返回其指针 +// 初始首结点的前后结点指针都为自身 +//@receiver nil +//@param nil +//@return n *node 新建的node指针 +func newNode(e interface{}) (n *node) { + n = &node{ + data: e, + pre: nil, + next: nil, + } + n.pre = n + n.next = n + return n +} + +//@title preNode +//@description +// 以node结点做接收者 +// 返回该结点的前结点 +//@receiver n *node 接收者的node指针 +//@param nil +//@return pre *node 该结点的前结点指针 +func (n *node) preNode() (pre *node) { + if n == nil { + return + } + return n.pre +} + +//@title nextNode +//@description +// 以node结点做接收者 +// 返回该结点的后结点 +//@receiver n *node 接收者的node指针 +//@param nil +//@return next *node 该结点的后结点指针 +func (n *node) nextNode() (next *node) { + if n == nil { + return + } + return n.next +} + +//@title insertPre +//@description +// 以node结点做接收者 +// 对该结点插入前结点 +// 并建立前结点和该结点之间的连接 +//@receiver n *node 接收者的node指针 +//@param pre *node 该结点的前结点指针 +//@return nil +func (n *node) insertPre(pre *node) { + if n == nil || pre == nil { + return + } + pre.next = n + pre.pre = n.pre + if n.pre != nil { + n.pre.next = pre + } + n.pre = pre +} + +//@title insertNext +//@description +// 以node结点做接收者 +// 对该结点插入后结点 +// 并建立后结点和该结点之间的连接 +//@receiver n *node 接收者的node指针 +//@param next *node 该结点的后结点指针 +//@return nil +func (n *node) insertNext(next *node) { + if n == nil || next == nil { + return + } + next.pre = n + next.next = n.next + if n.next != nil { + n.next.pre = next + } + n.next = next +} + +//@title erase +//@description +// 以node结点做接收者 +// 销毁该结点 +// 同时建立该节点前后节点之间的连接 +//@receiver n *node 接收者的node指针 +//@param nil +//@return nil +func (n *node) erase() { + if n == nil { + return + } + if n.pre == nil && n.next == nil { + return + } else if n.pre == nil { + n.next.pre = nil + } else if n.next == nil { + n.pre.next = nil + } else { + n.pre.next = n.next + n.next.pre = n.pre + } + n = nil +} + +//@title value +//@description +// 以node结点做接收者 +// 返回该结点所要承载的元素 +//@receiver n *node 接收者的node指针 +//@param nil +//@return e interface{} 该节点所承载的元素e +func (n *node) value() (e interface{}) { + if n == nil { + return nil + } + return n.data +} + +//@title setValue +//@description +// 以node结点做接收者 +// 对该结点设置其承载的元素 +//@receiver n *node 接收者的node指针 +//@param e interface{} 该节点所要承载的元素e +//@return nil +func (n *node) setValue(e interface{}) { + if n == nil { + return + } + n.data = e +} diff --git a/goSTL/data_structure/ring/ring.go b/goSTL/data_structure/ring/ring.go new file mode 100644 index 0000000..8603347 --- /dev/null +++ b/goSTL/data_structure/ring/ring.go @@ -0,0 +1,271 @@ +package ring + +//@Title ring +//@Description +// ring环容器包 +// 环将所有结点通过指针的方式串联起来,从而使得其整体保持一个线性状态 +// 不同于链表首尾不相连的情况,环将首尾结点连接起来,从而摒弃孤立的首尾结点 +// 可以利用其中的任何一个结点遍历整个环,也可以在任何位置进行插入 +// 增删结点需要同步修改其相邻的元素的前后指针以保证其整体是联通的 +// 可接纳不同类型的元素 +// 通过并发控制锁保证了在高并发过程中的数据一致性 + +import ( + "github.com/hlccd/goSTL/utils/iterator" + "sync" +) + +//ring环结构体 +//包含环的头尾节点指针 +//当增删结点时只需要移动到对应位置进行操作即可 +//当一个节点进行增删时需要同步修改其临接结点的前后指针 +//结构体中记录该环中当前所持有的结点的指针即可 +//同时记录该环中存在多少元素即size +//使用并发控制锁以保证数据一致性 +type ring struct { + now *node //环当前持有的结点指针 + size uint64 //当前存储的元素个数 + mutex sync.Mutex //并发控制锁 +} + +//ring环容器接口 +//存放了ring容器可使用的函数 +//对应函数介绍见下方 + +type ringer interface { + Iterator() (i *Iterator.Iterator) //创建一个包含环中所有元素的迭代器并返回其指针 + Size() (size uint64) //返回环所承载的元素个数 + Clear() //清空该环 + Empty() (b bool) //判断该环是否位空 + Insert(e interface{}) //向环当前位置后方插入元素e + Erase() //删除当前结点并持有下一结点 + Value() (e interface{}) //返回当前持有结点的元素 + Set(e interface{}) //在当前结点设置其承载的元素为e + Next() //持有下一节点 + Pre() //持有上一结点 +} + +//@title New +//@description +// 新建一个ring环容器并返回 +// 初始持有的结点不存在,即为nil +// 初始size为0 +//@receiver nil +//@param nil +//@return r *ring 新建的ring指针 +func New() (r *ring) { + return &ring{ + now: nil, + size: 0, + mutex: sync.Mutex{}, + } +} + +//@title Iterator +//@description +// 以ring环容器做接收者 +// 将ring环容器中所承载的元素放入迭代器中 +// 从该结点开始向后遍历获取全部承载的元素 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return i *iterator.Iterator 新建的Iterator迭代器指针 +func (r *ring) Iterator() (i *Iterator.Iterator) { + if r == nil { + r = New() + } + r.mutex.Lock() + //将所有元素复制出来放入迭代器中 + tmp := make([]interface{}, r.size, r.size) + //从当前结点开始向后遍历 + for n, idx := r.now, uint64(0); n != nil && idx < r.size; n, idx = n.nextNode(), idx+1 { + tmp[idx] = n.value() + } + i = Iterator.New(&tmp) + r.mutex.Unlock() + return i +} + +//@title Size +//@description +// 以ring环容器做接收者 +// 返回该容器当前含有元素的数量 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return num int 容器中所承载的元素数量 +func (r *ring) Size() (size uint64) { + if r == nil { + r = New() + } + return r.size +} + +//@title Clear +//@description +// 以ring环容器做接收者 +// 将该容器中所承载的元素清空 +// 将该容器的当前持有的结点置为nil,长度初始为0 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return nil +func (r *ring) Clear() { + if r == nil { + r = New() + } + r.mutex.Lock() + //销毁环 + r.now = nil + r.size = 0 + r.mutex.Unlock() +} + +//@title Empty +//@description +// 以ring环容器做接收者 +// 判断该ring环容器是否含有元素 +// 该判断过程通过size进行判断,size为0则为true,否则为false +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return b bool 该容器是空的吗? +func (r *ring) Empty() (b bool) { + if r == nil { + r = New() + } + return r.size == 0 +} + +//@title Insert +//@description +// 以ring环容器做接收者 +// 通过环中当前持有的结点进行添加 +// 如果环为建立,则新建一个自环结点设为环 +// 存在持有的结点,则在其后方添加即可 +//@receiver r *ring 接收者的ring指针 +//@param e interface{} 待插入元素 +//@return nil +func (r *ring) Insert(e interface{}) { + if r == nil { + r = New() + } + r.mutex.Lock() + //新建自环结点 + n := newNode(e) + if r.size == 0 { + //原本无环,设为新环 + r.now = n + } else { + //持有结点,在后方插入 + r.now.insertNext(n) + } + r.size++ + r.mutex.Unlock() +} + +//@title Erase +//@description +// 以ring环容器做接收者 +// 先判断是否仅持有一个结点 +// 若仅有一个结点,则直接销毁环 +// 否则将当前持有结点设为下一节点,并前插原持有结点的前结点即可 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return nil +func (r *ring) Erase() { + if r == nil { + r = New() + } + if r.size == 0 { + return + } + r.mutex.Lock() + //删除开始 + if r.size == 1 { + //环内仅有一个结点,销毁环即可 + r.now = nil + } else { + //环内还有其他结点,将持有结点后移一位 + //后移后将当前结点前插原持有结点的前结点 + r.now = r.now.nextNode() + r.now.insertPre(r.now.preNode().preNode()) + } + r.size-- + r.mutex.Unlock() +} + +//@title Get +//@description +// 以ring环容器做接收者 +// 获取环中当前持有节点所承载的元素 +// 若环中持有的结点不存在,直接返回nil +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return e interface{} 获取的元素 +func (r *ring) Value() (e interface{}) { + if r == nil { + r = New() + } + if r.now == nil { + //无持有结点,直接返回nil + return nil + } + return r.now.value() +} + +//@title Set +//@description +// 以ring环容器做接收者 +// 修改当前持有结点所承载的元素 +// 若未持有结点,直接结束即可 +//@receiver r *ring 接收者的ring指针 +//@param e interface{} 修改后当元素 +//@return nil +func (r *ring) Set(e interface{}) { + if r == nil { + r = New() + } + if r.now == nil { + return + } + r.mutex.Lock() + r.now.setValue(e) + r.mutex.Unlock() +} + +//@title Next +//@description +// 以ring环容器做接收者 +// 将当前持有的结点后移一位 +// 若当前无持有结点,则直接结束 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return nil +func (r *ring) Next() { + if r == nil { + r = New() + } + if r.now == nil { + return + } + r.mutex.Lock() + r.now = r.now.nextNode() + r.mutex.Unlock() +} + +//@title Pre +//@description +// 以ring环容器做接收者 +// 将当前持有的结点前移一位 +// 若当前无持有结点,则直接结束 +//@receiver r *ring 接收者的ring指针 +//@param nil +//@return nil +func (r *ring) Pre() { + if r == nil { + r = New() + } + if r.size == 0 { + return + } + r.mutex.Lock() + r.now = r.now.preNode() + r.mutex.Unlock() +}