├── README.md ├── algorithm ├── hash.go └── singleFlight │ └── singleFlight.go ├── blog ├── 数据结构STL——golang实现一致性哈希consistentHash.md ├── 数据结构STL——golang实现二叉搜索树Binary Search Tree.md ├── 数据结构STL——golang实现优先队列priority_queue.md ├── 数据结构STL——golang实现位图bitmap.md ├── 数据结构STL——golang实现前缀基数树radix.md ├── 数据结构STL——golang实现双向队列deque.md ├── 数据结构STL——golang实现向量vector.md ├── 数据结构STL——golang实现哈希映射hashMap.md ├── 数据结构STL——golang实现堆heap(完全二叉树).md ├── 数据结构STL——golang实现字典查找树trie.md ├── 数据结构STL——golang实现布隆过滤器bloomFilter.md ├── 数据结构STL——golang实现平衡二叉查找树avlTree.md ├── 数据结构STL——golang实现最近最少使用链lru.md ├── 数据结构STL——golang实现栈stack.md ├── 数据结构STL——golang实现树堆Treap.md ├── 数据结构STL——golang实现比较器comparator.md ├── 数据结构STL——golang实现独立请求singleFlight.md ├── 数据结构STL——golang实现环ring.md ├── 数据结构STL——golang实现迭代器iterator.md ├── 数据结构STL——golang实现链表list.md └── 数据结构STL——golang实现队列queue.md ├── data_structure ├── avlTree │ ├── avlTree.go │ └── node.go ├── bitmap │ └── bitmap.go ├── bloomFilter │ └── bloomFilter.go ├── bsTree │ ├── bsTree.go │ └── node.go ├── cbTree │ ├── cbTree.go │ └── node.go ├── consistentHash │ └── consistentHash.go ├── deque │ ├── deque.go │ ├── deque_test.go │ └── node.go ├── hashMap │ └── hashMap.go ├── heap │ ├── heap.go │ └── node.go ├── list │ ├── list.go │ └── node.go ├── lru │ └── lru.go ├── priority_queue │ └── priority_queue.go ├── queue │ └── queue.go ├── radix │ ├── node.go │ └── radix.go ├── ring │ ├── node.go │ └── ring.go ├── stack │ └── stack.go ├── treap │ ├── node.go │ └── treap.go ├── trie │ ├── node.go │ └── trie.go └── vector │ └── vector.go └── utils ├── comparator ├── bound.go ├── comparator.go ├── nth_element.go ├── search.go └── sort.go └── iterator └── Iterator.go /README.md: -------------------------------------------------------------------------------- 1 | 使用时请先将整体下载解压后,将解压得到的目录下的goSTL放入本机内的src的github.com目录下使用即可 2 | 3 | 4 | 所有介绍可参考blog文件夹下的文件,也可参考下方列出的网址 5 | 6 | ## goSTL 7 | #### 比较器:comparator 8 | 参考:https://zhuanlan.zhihu.com/p/422888284 9 | 10 | #### 迭代器:iterator 11 | 参考:https://zhuanlan.zhihu.com/p/422978077 12 | 13 | #### 位图:bitmap 14 | 参考:https://zhuanlan.zhihu.com/p/423253110 15 | 16 | #### 向量:vector 17 | 参考:https://zhuanlan.zhihu.com/p/423688716 18 | 19 | #### 队列:queue 20 | 参考:https://zhuanlan.zhihu.com/p/423805926 21 | 22 | #### 双向队列:deque 23 | 参考:https://zhuanlan.zhihu.com/p/424225817 24 | 25 | #### 链表:list 26 | 参考:https://zhuanlan.zhihu.com/p/424603940 27 | 28 | #### 环:ring 29 | 参考:https://zhuanlan.zhihu.com/p/424860909 30 | 31 | #### 栈:stack 32 | 参考:https://zhuanlan.zhihu.com/p/424967178 33 | 34 | #### 优先队列:priority_queue 35 | 参考:https://zhuanlan.zhihu.com/p/425095786 36 | 37 | #### 二叉搜索树:Binary Search Tree 38 | 参考:https://zhuanlan.zhihu.com/p/425215493 39 | 40 | #### 堆的完全二叉搜实现:heap 41 | 参考:https://zhuanlan.zhihu.com/p/425943809 42 | 43 | #### 树堆:treap 44 | 参考:https://zhuanlan.zhihu.com/p/444445554 45 | 46 | #### 平衡二叉查找树:avlTree 47 | 参考:https://zhuanlan.zhihu.com/p/446547869 48 | 49 | #### 哈希映射:hashMap 50 | 参考:https://zhuanlan.zhihu.com/p/447063415 51 | 52 | #### 字典查找树:trie 53 | 参考:https://zhuanlan.zhihu.com/p/447352512 54 | 55 | #### 最近最少使用链:lru 56 | 参考:https://zhuanlan.zhihu.com/p/449813097 57 | 58 | #### 前缀基数树:radix 59 | 参考:https://zhuanlan.zhihu.com/p/450050034 60 | 61 | #### 一致性哈希:consistentHash 62 | 参考:https://zhuanlan.zhihu.com/p/450283390 63 | 64 | #### 布隆过滤器:bloomFilter 65 | 参考:https://zhuanlan.zhihu.com/p/450995290 66 | 67 | 68 | #### 独立请求:singleFlight 69 | 参考:https://zhuanlan.zhihu.com/p/451018160 70 | -------------------------------------------------------------------------------- /algorithm/hash.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | //@Title algorithm 4 | //@Description 5 | // hash函数 6 | // 定义了一个hash函数类型,该类型可传入一个key并返回其hash值 7 | // 该包内定义了一些自带类型的hash函数 8 | // 当使用自定义的数据结构时若不传入hash函数则使用默认的hash函数 9 | // 若传入类型非系统自带类型,则返回nil同时对数据的插入失败 10 | 11 | type Hasher func(key interface{}) uint64 12 | 13 | func GetHash(e interface{}) (hash Hasher) { 14 | if e == nil { 15 | return nil 16 | } 17 | switch e.(type) { 18 | case bool: 19 | return boolHash 20 | case int: 21 | return intHash 22 | case int8: 23 | return int8Hash 24 | case uint8: 25 | return uint8Hash 26 | case int16: 27 | return int16Hash 28 | case uint16: 29 | return uint16Hash 30 | case int32: 31 | return int32Hash 32 | case uint32: 33 | return uint32Hash 34 | case int64: 35 | return int64Hash 36 | case uint64: 37 | return uint64Hash 38 | case float32: 39 | return float32Hash 40 | case float64: 41 | return float64Hash 42 | case complex64: 43 | return complex64Hash 44 | case complex128: 45 | return complex128Hash 46 | case string: 47 | return stringHash 48 | } 49 | return nil 50 | } 51 | func boolHash(key interface{}) uint64 { 52 | if key.(bool) { 53 | return 1 54 | } 55 | return 0 56 | } 57 | func intHash(key interface{}) uint64 { 58 | return uint64(key.(int) * key.(int) / 2) 59 | } 60 | func int8Hash(key interface{}) uint64 { 61 | return uint64(key.(int8) * key.(int8) / 2) 62 | } 63 | func uint8Hash(key interface{}) uint64 { 64 | return uint64(key.(uint8) * key.(uint8) / 2) 65 | } 66 | func int16Hash(key interface{}) uint64 { 67 | return uint64(key.(int16) * key.(int16) / 2) 68 | } 69 | func uint16Hash(key interface{}) uint64 { 70 | return uint64(key.(uint16) * key.(uint16) / 2) 71 | } 72 | func int32Hash(key interface{}) uint64 { 73 | return uint64(key.(int32) * key.(int32) / 2) 74 | } 75 | func uint32Hash(key interface{}) uint64 { 76 | return uint64(key.(uint32) * key.(uint32) / 2) 77 | } 78 | func int64Hash(key interface{}) uint64 { 79 | return uint64(key.(int64) * key.(int64) / 2) 80 | } 81 | func uint64Hash(key interface{}) uint64 { 82 | return uint64(key.(uint64) * key.(uint64) / 2) 83 | } 84 | func float32Hash(key interface{}) uint64 { 85 | return uint64(key.(float32) * key.(float32) / 2) 86 | } 87 | func float64Hash(key interface{}) uint64 { 88 | return uint64(key.(float64) * key.(float64) / 2) 89 | } 90 | func complex64Hash(key interface{}) uint64 { 91 | r := uint64(real(key.(complex64))) 92 | i := uint64(imag(key.(complex64))) 93 | return uint64Hash(r) + uint64Hash(i) 94 | } 95 | func complex128Hash(key interface{}) uint64 { 96 | r := uint64(real(key.(complex64))) 97 | i := uint64(imag(key.(complex64))) 98 | return uint64Hash(r) + uint64Hash(i) 99 | } 100 | func stringHash(key interface{}) uint64 { 101 | bs := []byte(key.(string)) 102 | ans := uint64(0) 103 | for i := range bs { 104 | ans += uint64(bs[i] * 251) 105 | } 106 | return ans 107 | } 108 | -------------------------------------------------------------------------------- /algorithm/singleFlight/singleFlight.go: -------------------------------------------------------------------------------- 1 | package singleFlight 2 | 3 | //@Title singleFlight 4 | //@Description 5 | // 单次请求-single flight 6 | // 利用可重入锁避免对于一个同类的请求进行多次从而导致的缓存击穿的问题 7 | // 缓存击穿: 8 | // 缓存在某个时间点过期的时候 9 | // 恰好在这个时间点对这个Key有大量的并发请求过来 10 | // 这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存 11 | // 这个时候大并发的请求可能会瞬间把后端DB压垮。 12 | 13 | import "sync" 14 | 15 | //呼叫请求结构体 16 | type call struct { 17 | wg sync.WaitGroup //可重入锁 18 | val interface{} //请求结果 19 | err error //错误反馈 20 | } 21 | 22 | //一组请求工作 23 | //每一类请求对应一个call,利用其内部的可重入锁避免一类请求在短时间内频繁执行 24 | //请求组工作由使用者自行分配空间来实现 25 | type Group struct { 26 | m map[string]*call //一类请求与同一类呼叫的映射表 27 | mu sync.Mutex //并发控制锁,保证线程安全 28 | } 29 | 30 | //@title Do 31 | //@description 32 | // 以请求组做接收者 33 | // 传入一个请求类的key和请求调用函数fn 34 | // 请求时候需要等待之前有的同类请求先完成在进行 35 | // 防止击穿缓存,对同一个key进行请求时需要分别进行,利用可重入锁实现 36 | // 请求完成后返回结果和错误信息即可 37 | //@receiver g *Group 接受者请求组的指针 38 | //@param key string 请求的关键词key 39 | //@param fn func() (interface{}, error) 请求执行函数 40 | //@return v interface{} 请求执行得到的结果 41 | //@return err error 执行请求后的错误信息 42 | func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error) { 43 | g.mu.Lock() 44 | if g.m == nil { 45 | g.m = make(map[string]*call) 46 | } 47 | //判断以key为关键词的该类请求是否存在 48 | if c, ok := g.m[key]; ok { 49 | g.mu.Unlock() 50 | // 如果请求正在进行中,则等待 51 | c.wg.Wait() 52 | return c.val, c.err 53 | } 54 | //该类请求不存在,创建个请求 55 | c := new(call) 56 | // 发起请求前加锁,并将请求添加到请求组内以表示该类请求正在处理 57 | c.wg.Add(1) 58 | g.m[key] = c 59 | g.mu.Unlock() 60 | //调用请求函数获取内容 61 | c.val, c.err = fn() 62 | //请求结束 63 | c.wg.Done() 64 | g.mu.Lock() 65 | //从请求组中删除该呼叫请求 66 | delete(g.m, key) 67 | g.mu.Unlock() 68 | return c.val, c.err 69 | } 70 | 71 | //@title DoChan 72 | //@description 73 | // 以请求组做接收者 74 | // 传入一个请求类的key和请求调用函数fn 75 | // 请求时候需要等待之前有的同类请求先完成在进行 76 | // 防止击穿缓存,对同一个key进行请求时需要分别进行,利用可重入锁实现 77 | // 返回一个channel,利用fn函数获取到的数据将会传入其中 78 | // 可利用channel做超时控制 79 | //@receiver g *Group 接受者请求组的指针 80 | //@param key string 请求的关键词key 81 | //@param fn func() (interface{}, error) 请求执行函数 82 | //@return ch chan interface{} 执行结果将会传入其中,可做超时控制 83 | func (g *Group) DoChan(key string, fn func() (interface{}, error)) (ch chan interface{}) { 84 | ch = make(chan interface{}, 1) 85 | g.mu.Lock() 86 | if g.m == nil { 87 | g.m = make(map[string]*call) 88 | } 89 | if _, ok := g.m[key]; ok { 90 | g.mu.Unlock() 91 | return ch 92 | } 93 | c := new(call) 94 | c.wg.Add(1) // 发起请求前加锁 95 | g.m[key] = c // 添加到 g.m,表明 key 已经有对应的请求在处理 96 | g.mu.Unlock() 97 | go func() { 98 | c.val, c.err = fn() // 调用 fn,发起请求 99 | c.wg.Done() // 请求结束 100 | g.mu.Lock() 101 | delete(g.m, key) // 更新 g.m 102 | ch <- c.val 103 | g.mu.Unlock() 104 | }() 105 | return ch 106 | } 107 | 108 | //@title ForgetUnshared 109 | //@description 110 | // 以请求组做接收者 111 | // 传入一个请求类的key 112 | // 如果该key存在于请求组内,则将其删除即可 113 | // 从而实现遗忘该类请求的目的 114 | //@receiver g *Group 接受者请求组的指针 115 | //@param key string 请求的关键词key 116 | //@return nil 117 | func (g *Group) ForgetUnshared(key string) { 118 | g.mu.Lock() 119 | _, ok := g.m[key] 120 | if ok { 121 | delete(g.m, key) 122 | } 123 | g.mu.Unlock() 124 | } 125 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现位图bitmap.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此可以**极大的节省存储空间**。 6 | 7 | ### 原理 8 | 9 | ​ 对于计算机来说,它可以分配的最小单位是**一个字节即8位**,一位有且仅有**1和0**两种表示可能。而如果要表示0~7八个数字在某一个集合内是否存在,比如表示{0,3,5}在集合中是否存在,可以使用一个字节进行存储,即对应位为1的表示存在,为0的表示不存在,即: 10 | 11 | 12 | 13 | | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 14 | | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 15 | 16 | 而如果要表示超过8个的元素是否存在的话,仅仅使用一个字节是远远不够的。 17 | 18 | ​ 为了解决这个问题,可以选择使用包含更多字节的基本元素,比如**uint64**,选用uint64而不是int64的原因是因为,在计算机内部存储数字采用补码的形式,对于一个数字如果不是非负整数的话,它需要有一位去标注这个数字是否为负数,而在使用bitmap的时候,使用基本类型仅仅是为了使用它的位,至于是否是负数并不重要,既然如此,舍弃掉正负数标志位就可以多利用一位进行表示。 19 | 20 | ​ 除此之外,还可以选择多个基本元素进行叠加,即多组混合表示,以表示{0,3,5,8,14,15}为例: 21 | 22 | | **1** | **0** | **0** | **1** | **0** | **1** | **0** | **0** | 23 | | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | 24 | | **1** | **0** | **0** | **0** | **0** | **0** | **1** | **1** | 25 | 26 | ​ 即一第一行为0~7,第二行及以后为n*8+(0~7)进行表示,而对于golang实现来说,可以选择用uint64的切片进行表示,即在换算时候对于一个数字num,它所属的行(从0开始)为: 27 | $$ 28 | num/64 29 | $$ 30 | ​ 它所属的列(从0开始)为: 31 | $$ 32 | num%64 33 | $$ 34 | 35 | ### 用处 36 | 37 | ​ bitmap由于其本身的有序性和唯一性,一来可以实现**快速排序**:即对于一组无需且**稠密**的数字,可以将其放入bitmap中,然后再遍历获取出来,从而使得其元素是单调递增的;而来可以实现**去重**:由于bitmap是使用bit进行表示一个元素是否存在其中,而bit有且仅有1和0两种情况,所以在一个位置插入多个元素时,它表示的都是1,从而可以实现插入多个保留一个的去重;三来可以极大的**节省存储空间**:由于对基本类型数组的下标赋予了一定的含义,导致可以利用其含义来表示一个数字,而不是去存储一个数字,即要表示一个2^16的数字时候,原本需要16位,现在只需要1位即可实现。 38 | 39 | ### 实现 40 | 41 | #### 结构定义 42 | 43 | ​ 由上文可知,所要使用的bitmap内部其实是存储的uint64的切片,同时增加一个zero,,即 44 | 45 | ```go 46 | type bitmap struct { 47 | bits []uint64 48 | } 49 | ``` 50 | 51 | ##### 接口集合 52 | 53 | ```go 54 | type bitmaper interface { 55 | Insert(num uint) //在num位插入元素 56 | Delete(num uint) //删除第num位 57 | Check(num uint) (b bool) //检查第num位是否有元素 58 | All() (nums []uint) //返回所有存储的元素的下标 59 | Clear() //清空 60 | } 61 | ``` 62 | 63 | #### New 64 | 65 | 创建部分主要做的就是返回一个初始化后的bitmap指针 66 | 67 | ```go 68 | func New() (bm *bitmap) { 69 | return &bitmap{ 70 | bits: make([]uint64, 0, 0), 71 | } 72 | } 73 | ``` 74 | 75 | #### Insert 76 | 77 | ​ 对于bitmap的插入来说,会出现两种情况,第一种是要插入的位恰好可以在位图中容纳,此时将对应位设为1即可,并不需要对位图进行扩容,实现起来十分简单,找到对应位即可,第二章就是要插入的位超过了位图可容纳的范围,次数就需要一个扩容策略对其进行扩容以保证插入的值在位图内可以存储。 78 | 79 | ##### 扩容策略 80 | 81 | ​ 对于bitmap扩容来说,它的扩容主要是由于新要插入的位超出了位图所能表示的位,从而需要对位图进行扩增以满足其范围,而扩容则可以采取**两种策略**: 82 | 83 | 1. **固定扩容**:对于要扩容的位图,进行一个固定的量进行扩容,该方案的好处实现简单,但坏处也明显,如果固定扩容后还是不足以覆盖还需要再次扩容,同时如果扩容太大也会需要更多的空间; 84 | 2. **按需扩容**:对于要扩容的位图,按照它需要扩容的范围来进行扩容,该方案的好处是几乎可以恰好容纳需要存储的位,但如果存在连续的几个较短的扩容出现时,即先扩容到64->128>256>512>1024这种情况时,需要连续的扩容复制,会浪费一定的性能。 85 | 86 | 对此,我们可以考虑将两种方案结合起来,即当要增加的范围并不太大的时候,**牺牲一定量的空间**进行固定扩容,从而避免连续的小范围扩容多次出现降低性能,而对于大范围扩容时,则使用按需扩容,以此来提高单次扩容速度。 87 | 88 | ​ 本次实现中,固定扩容采用一次增加**2^10个uint64**。 89 | 90 | ```go 91 | func (bm *bitmap) Insert(num uint) { 92 | //bm不存在时直接结束 93 | if bm == nil { 94 | return 95 | } 96 | //开始插入 97 | if num/64+1 > uint(len(bm.bits)) { 98 | //当前冗余量小于num位,需要扩增 99 | var tmp []uint64 100 | //通过冗余扩增减少扩增次数 101 | if num/64+1 < uint(len(bm.bits)+1024) { 102 | //入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 103 | tmp = make([]uint64, len(bm.bits)+1024) 104 | } else { 105 | //直接增加到可以容纳第num位的位置 106 | tmp = make([]uint64, num/64+1) 107 | } 108 | //将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的 109 | copy(tmp, bm.bits) 110 | bm.bits = tmp 111 | } 112 | //将第num位设为1即实现插入 113 | bm.bits[num/64] ^= 1 << (num % 64) 114 | } 115 | ``` 116 | 117 | #### Delete 118 | 119 | ​ 对于位图的删除,会出现三种情况,第一种是要删除的范围不在位图范围内,直接忽略即可;第二种是在位图范围内,且位图尾部存在连续为0的uint64时,此时就需要执行**缩容策略**。 120 | 121 | ##### 缩容策略 122 | 123 | ​ 对于缩容策略,同样采取三种方案: 124 | 125 | 1. **固定缩容**:从尾部删除固定数量的为0的组,该方案删除的量是固定的,优点在于尾部量很多时可以慢慢减少,剩下的可当作冗余量避免多次增加,缺点是缓慢减少需要一定时间开销 126 | 2. **按需缩容**:当存在需要删除的组时,直接进行删除,优点的空间利用率更高,缺点是冗余基本没有,同时删除过于频繁 127 | 3. **折半删除**:当需要删除的组超过一半时,删掉一半即可,该方案删除切合slice底层实现,但在普遍场景来说,可能并不会经常使用。 128 | 129 | 为此,可以选择将三种结合起来,当总组数很长时,且需要删除的量过多,可以使用固定缩容,留出一定余量,当删除量不多时,且需要删除的量超过了总组数的一半时,在进行按需删除,即把要删除的全部删完。 130 | 131 | ​ 为了避免固定扩容和固定缩容循环出现,对两者数值进行错位,由于固定扩容选择的是1024,所以固定缩容选为256。 132 | 133 | ```go 134 | func (bm *bitmap) Delete(num uint) { 135 | //bm不存在时直接结束 136 | if bm == nil { 137 | return 138 | } 139 | //num超出范围,直接结束 140 | if num/64+1 > uint(len(bm.bits)) { 141 | return 142 | } 143 | //将第num位设为0 144 | bm.bits[num/64] &^= 1 << (num % 64) 145 | if bm.bits[len(bm.bits)-1] == 0 { 146 | //最后一组为0,可能进行缩容 147 | //从后往前遍历判断可缩容内容是否小于总组数 148 | i := len(bm.bits) - 1 149 | for ; i >= 0; i-- { 150 | if bm.bits[i] == 0 && i!=len(bm.bits)-1024{ 151 | continue 152 | } else { 153 | //不为0或到1024个时即可返回 154 | break 155 | } 156 | } 157 | if i <= len(bm.bits)/2 || i==len(bm.bits)-1024 { 158 | //小于总组数一半或超过1023个,进行缩容 159 | bm.bits = bm.bits[:i+1] 160 | } 161 | } else { 162 | return 163 | } 164 | } 165 | ``` 166 | 167 | #### Check 168 | 169 | 检查第num位是否存在于位图种,不存在返回false,存在返回true,超出范围也返回false。 170 | 171 | ```go 172 | func (bm *bitmap) Check(num uint) (b bool) { 173 | //bm不存在时直接返回false并结束 174 | if bm == nil { 175 | return false 176 | } 177 | //num超出范围,直接返回false并结束 178 | if num/64+1 > uint(len(bm.bits)) { 179 | return false 180 | } 181 | //判断第num是否为1,为1返回true,否则为false 182 | if bm.bits[num/64]&(1<<(num%64)) > 0 { 183 | return true 184 | } 185 | return false 186 | } 187 | ``` 188 | 189 | #### All 190 | 191 | 返回所有在位图种存在的元素的下标,同时保证其为单调递增序列。 192 | 193 | ```go 194 | func (bm *bitmap) All() (nums []uint) { 195 | //对要返回的集合进行初始化,以避免返回nil 196 | nums=make([]uint,0,0) 197 | //bm不存在时直接返回并结束 198 | if bm == nil { 199 | return nums 200 | } 201 | //分组遍历判断某下标的元素是否存在于位图中,即其值是否为1 202 | for j := 0; j < len(bm.bits); j++ { 203 | for i := 0; i < 64; i++ { 204 | if bm.bits[j]&(1< 0 { 205 | //该元素存在,添加入结果集合内 206 | nums = append(nums, uint(j*64+i)) 207 | } 208 | } 209 | } 210 | return nums 211 | } 212 | ``` 213 | 214 | #### Clear 215 | 216 | 清空初始化位图。 217 | 218 | ```go 219 | func (bm *bitmap) Clear() { 220 | if bm == nil { 221 | return 222 | } 223 | bm.bits = make([]uint64, 0, 0) 224 | } 225 | ``` 226 | 227 | ### 使用示例 228 | 229 | ```go 230 | package main 231 | 232 | import ( 233 | "fmt" 234 | "github.com/hlccd/goSTL/data_structure/bitmap" 235 | ) 236 | func main() { 237 | var nums []uint 238 | bm:=bitmap.New() 239 | bm.Insert(1) 240 | bm.Insert(2) 241 | bm.Insert(3) 242 | bm.Insert(64) 243 | bm.Insert(128) 244 | bm.Insert(256) 245 | bm.Insert(320) 246 | nums=bm.All() 247 | for i:=0;i< len(nums);i++{ 248 | fmt.Println(nums[i]) 249 | } 250 | bm.Delete(320) 251 | fmt.Println() 252 | nums=bm.All() 253 | for i:=0;i< len(nums);i++{ 254 | fmt.Println(nums[i]) 255 | } 256 | bm.Delete(256) 257 | fmt.Println() 258 | nums=bm.All() 259 | for i:=0;i< len(nums);i++{ 260 | fmt.Println(nums[i]) 261 | } 262 | bm.Delete(128) 263 | fmt.Println() 264 | nums=bm.All() 265 | for i:=0;i< len(nums);i++{ 266 | fmt.Println(nums[i]) 267 | } 268 | bm.Clear() 269 | fmt.Println() 270 | nums=bm.All() 271 | for i:=0;i< len(nums);i++{ 272 | fmt.Println(nums[i]) 273 | } 274 | } 275 | 276 | ``` 277 | 278 | #### 结果 279 | 280 | > 1 281 | > 2 282 | > 3 283 | > 64 284 | > 128 285 | > 256 286 | > 320 287 | > 288 | > 1 289 | > 2 290 | > 3 291 | > 64 292 | > 128 293 | > 256 294 | > 295 | > 1 296 | > 2 297 | > 3 298 | > 64 299 | > 128 300 | > 301 | > 1 302 | > 2 303 | > 3 304 | > 64 305 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现布隆过滤器bloomFilter.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ 布隆过滤器(bloom filter),它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于**寻找**一个元素是否在一个集合中,但由于元素的通过hash映射转化到集合内的,所以存在误差,即可以百分百判断其不存在,但不能确定其一定存在。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的**误识别率**和**删除困难**。 6 | 7 | ### 原理 8 | 9 | ​ 如果想要判断一个元素是不是在一个集合里,除了可以将所有元素保存起来,通过比较确定外,也可以通过将元素转化为一个hash值放入哈希表内,通过hash函数将元素转化为hash值,该方案可以通过**位图**的形式存贮,当判断其是否存在的时候只需要在位图上找到这个点是否为1即可判断其是否存在。极大的提高了空间利用率同时减小了时间开销,但带来了一定的**识别错误率**,识别错误主要由hash冲突导致。 10 | 11 | ​ 相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常熟级别。另外,布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。同时,布隆过滤器可以用来表示全集,这是其他数据结构所不能实现的。布隆过滤器可以表示全集,其它任何数据结构都不能。 12 | 13 | ​ 对于出现hash冲突的情况来说,它是会出现错误识别的,当然,一般来说并不会有很多。对于此类问题,可以通过建立白名单的方式去存储可能误判的元素,即对hash使用开放寻址法,但一般来说并不需要。 14 | 15 | ​ 同时,考虑到识别错误的问题,删除的操作几乎是不应当实现的,所以本次实现中主要实现**添加和查找**操作,当然也包含清空操作。 16 | 17 | ### 实现 18 | 19 | ​ bloomFilter布隆过滤器结构体,包含其用于存储的uint64元素切片,选用uint64是为了更多的利用bit位。 20 | 21 | ```go 22 | type bloomFilteror interface { 23 | Insert(v interface{}) //向布隆过滤器中插入v 24 | Check(v interface{}) (b bool) //检查该值是否存在于布隆过滤器中,该校验存在误差 25 | Clear() //清空该布隆过滤器 26 | } 27 | ``` 28 | 29 | #### 接口 30 | 31 | ```go 32 | type bloomFilteror interface { 33 | Insert(v interface{}) //向布隆过滤器中插入v 34 | Check(v interface{}) (b bool) //检查该值是否存在于布隆过滤器中,该校验存在误差 35 | Clear() //清空该布隆过滤器 36 | } 37 | ``` 38 | 39 | #### hash 40 | 41 | ​ 传入一个虚拟节点id和实际结点,计算出它的hash值,逐层访问并利用素数131计算其hash值随后返回。 42 | 43 | ​ 该hash函数可自行传入,也可使用库内函数 44 | 45 | ```go 46 | type Hash func(v interface{}) (h uint32) 47 | 48 | func hash(v interface{}) (h uint32) { 49 | h = uint32(0) 50 | s := fmt.Sprintf("131-%v-%v", v,v) 51 | bs := []byte(s) 52 | for i := range bs { 53 | h += uint32(bs[i]) * 131 54 | } 55 | return h 56 | } 57 | ``` 58 | 59 | #### New 60 | 61 | ​ 新建一个bloomFilter布隆过滤器容器并返回,初始bloomFilter的切片数组为空。 62 | 63 | ```go 64 | func New(h Hash) (bf *bloomFilter) { 65 | if h == nil { 66 | h = hash 67 | } 68 | return &bloomFilter{ 69 | bits: make([]uint64, 0, 0), 70 | hash: h, 71 | } 72 | } 73 | ``` 74 | 75 | #### Insert 76 | 77 | ​ 以bloomFilter布隆过滤器容器做接收者,先将待插入的value计算得到其哈希值hash,再向布隆过滤器中第hash位插入一个元素(下标从0开始),当hash大于当前所能存储的位范围时,需要进行扩增,若要插入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64,否则则直接增加到可以容纳第hash位的位置,以此可以提高冗余量,避免多次增加。 78 | 79 | ```go 80 | func (bf *bloomFilter) Insert(v interface{}) { 81 | //bm不存在时直接结束 82 | if bf == nil { 83 | return 84 | } 85 | //开始插入 86 | h := bf.hash(v) 87 | if h/64+1 > uint32(len(bf.bits)) { 88 | //当前冗余量小于num位,需要扩增 89 | var tmp []uint64 90 | //通过冗余扩增减少扩增次数 91 | if h/64+1 < uint32(len(bf.bits)+1024) { 92 | //入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 93 | tmp = make([]uint64, len(bf.bits)+1024) 94 | } else { 95 | //直接增加到可以容纳第num位的位置 96 | tmp = make([]uint64, h/64+1) 97 | } 98 | //将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的 99 | copy(tmp, bf.bits) 100 | bf.bits = tmp 101 | } 102 | //将第num位设为1即实现插入 103 | bf.bits[h/64] ^= 1 << (h % 64) 104 | } 105 | ``` 106 | 107 | #### Check 108 | 109 | ​ 以bloomFilter布隆过滤器容器做接收者,将待查找的值做哈希计算得到哈希值h,检验第h位在位图中是否存在,当h大于当前所能存储的位范围时,直接返回false,否则判断第h为是否为1,为1返回true,否则返回false,利用布隆过滤器做判断存在误差,即返回true可能也不存在,但返回false则必然不存在。 110 | 111 | ```go 112 | func (bf *bloomFilter) Check(v interface{}) (b bool) { 113 | //bf不存在时直接返回false并结束 114 | if bf == nil { 115 | return false 116 | } 117 | h := bf.hash(v) 118 | //h超出范围,直接返回false并结束 119 | if h/64+1 > uint32(len(bf.bits)) { 120 | return false 121 | } 122 | //判断第num是否为1,为1返回true,否则为false 123 | if bf.bits[h/64]&(1<<(h%64)) > 0 { 124 | return true 125 | } 126 | return false 127 | } 128 | ``` 129 | 130 | #### Clear 131 | 132 | ​ 以bloomFilter布隆过滤器容器做接收者,清空整个布隆过滤器。 133 | 134 | ```go 135 | func (bf *bloomFilter) Clear() { 136 | if bf == nil { 137 | return 138 | } 139 | bf.bits = make([]uint64, 0, 0) 140 | } 141 | ``` 142 | 143 | ### 使用示例 144 | 145 | ```go 146 | package main 147 | 148 | import ( 149 | "fmt" 150 | "github.com/hlccd/goSTL/data_structure/bloomFilter" 151 | ) 152 | 153 | func hash(v interface{}) uint32 { 154 | return uint32(v.(int)) 155 | } 156 | func main() { 157 | bf := bloomFilter.New(nil) 158 | for i := 0; i < 10; i++ { 159 | bf.Insert(i) 160 | } 161 | for i := 0; i < 15; i++ { 162 | fmt.Println(i,bf.Check(i)) 163 | } 164 | } 165 | ``` 166 | 167 | > 0 true 168 | > 1 true 169 | > 2 true 170 | > 3 true 171 | > 4 true 172 | > 5 true 173 | > 6 true 174 | > 7 true 175 | > 8 true 176 | > 9 true 177 | > 10 false 178 | > 11 false 179 | > 12 false 180 | > 13 false 181 | > 14 false 182 | 183 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现最近最少使用链lru.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ LRU-Least Recently Used,最近最少使用链结构,相对于仅考虑时间因素的FIFO和仅考虑访问频率的LFU,LRU算法可以认为是相对平衡的一种淘汰算法,LRU认为,如果数据最近被访问过,那么将来被访问的概率也会更高,LRU 算法的实现非常简单,维护一个队列,如果某条记录被访问了,则移动到队尾,那么队首则是最近最少访问的数据,淘汰该条记录即可。 6 | 7 | ​ 它适用于作为一个cache缓存,去保存带有索引的数据,对于其要存储的数据值来说,通过实现一个Len()的函数的泛型来表示。 8 | 9 | ### 原理 10 | 11 | ​ 本次实现过程中,采用双向链表的形式做为用于存储值的队列,同时利用map建立key和存储值的链表结点之间的联系。 12 | 13 | ​ 该方案可以加快从队列中找到对应的值并做修改,同时也便于将最近访问的value移到队首。 14 | 15 | ​ 本次实现不做定时淘汰,若要实现定时淘汰可自行创建一个协程同时添加一个map去保存其上次访问时间去完成定时淘汰即可。 16 | 17 | ​ 对于LRU的修改策略来说: 18 | 19 | - 初次添加/访问,直接放到队首 20 | - 添加后若容量超过上限值则移除最远访问的value,即队尾元素,移除过程直至使用容量低于上限值时才结束 21 | - 再次访问时从map中找到刚刚访问的结点随后将其移动到队首 22 | - 删除时直接利用map找到对应的结点进行删除即可 23 | 24 | ### 实现 25 | 26 | ​ LRU链结构体,包含了该LRU结构中能承载的byte数上限和当前已承载的数量,以链表的形式存储承载元素,使用map建立key索引和链表结点之间的联系,链表结点中存放其value,onRemove函数是用于在删除时的执行,可用于将数据持久化,使用并发控制所保证线程安全。 27 | 28 | ```go 29 | type LRU struct { 30 | maxBytes int64 //所能承载的最大byte数量 31 | nowBytes int64 //当前承载的byte数 32 | ll *list.List //用于存储的链表 33 | cache map[string]*list.Element //链表元素与key的映射表 34 | onRemove func(key string, value Value) //删除元素时的执行函数 35 | mutex sync.Mutex //并发控制锁 36 | } 37 | ``` 38 | 39 | ​ 索引结构体,保存了一个待存储值的索引和值,value值为一个interface{},需要实现它的长度函数即Len()。 40 | 41 | ```go 42 | type indexes struct { 43 | key string //索引 44 | value Value //存储值 45 | } 46 | ``` 47 | 48 | ​ 存储值的函数。 49 | 50 | ```go 51 | type Value interface { 52 | Len() int //用于计算该存储值所占用的长度 53 | } 54 | ``` 55 | 56 | #### 接口 57 | 58 | ```go 59 | type lruer interface { 60 | Size() (num int64) //返回lru中当前存放的byte数 61 | Cap() (num int64) //返回lru能存放的byte树的最大值 62 | Clear() //清空lru,将其中存储的所有元素都释放 63 | Empty() (b bool) //判断该lru中是否存储了元素 64 | Insert(key string, value Value) //向lru中插入以key为索引的value 65 | Erase(key string) //从lru中删除以key为索引的值 66 | Get(key string) (value Value, ok bool) //从lru中获取以key为索引的value和是否获取成功? 67 | } 68 | ``` 69 | 70 | #### New 71 | 72 | ​ 以LRU链容器做接收者,返回该LRU链当前所存储的byte数。 73 | 74 | ```go 75 | func (l *LRU) Size() (num int64) { 76 | if l == nil { 77 | return 0 78 | } 79 | return l.nowBytes 80 | } 81 | ``` 82 | 83 | #### Cap 84 | 85 | ​ 以LRU链容器做接收者,返回该LRU链能存储的最大byte数。 86 | 87 | ```go 88 | func (l *LRU) Cap() (num int64) { 89 | if l == nil { 90 | return 0 91 | } 92 | return l.maxBytes 93 | } 94 | ``` 95 | 96 | #### Clear 97 | 98 | ​ 以LRU链容器做接收者,将LRU链中的所有承载的元素清除,同时将map清空,将当前存储的byte数清零。 99 | 100 | ```go 101 | func (l *LRU) Clear() { 102 | if l == nil { 103 | return 104 | } 105 | l.mutex.Lock() 106 | l.ll = list.New() 107 | l.cache = make(map[string]*list.Element) 108 | l.nowBytes = 0 109 | l.mutex.Unlock() 110 | } 111 | ``` 112 | 113 | #### Empty 114 | 115 | ​ 以LRU链容器做接收者,判断该LRU链中是否存储了元素,没存储则返回true,LRU不存在也返回true,否则返回false。 116 | 117 | ```go 118 | func (l *LRU) Empty() (b bool) { 119 | if l == nil { 120 | return true 121 | } 122 | return l.nowBytes <= 0 123 | } 124 | ``` 125 | 126 | #### Insert 127 | 128 | ​ 以LRU链容器做接收者,向该LRU中插入以key为索引的value,若已经存在则将其放到队尾,若空间充足且不存在则直接插入队尾,若空间不足则淘汰队首元素再将其插入队尾,插入完成后将当前已存的byte数增加。 129 | 130 | ```go 131 | func (l *LRU) Insert(key string, value Value) { 132 | l.mutex.Lock() 133 | //利用map从已存的元素中寻找 134 | if ele, ok := l.cache[key]; ok { 135 | //该key已存在,直接替换即可 136 | l.ll.MoveToFront(ele) 137 | kv := ele.Value.(*indexes) 138 | //此处是一个替换,即将cache中的value替换为新的value,同时根据实际存储量修改其当前存储的实际大小 139 | l.nowBytes += int64(value.Len()) - int64(kv.value.Len()) 140 | kv.value = value 141 | } else { 142 | //该key不存在,需要进行插入 143 | ele := l.ll.PushFront(&indexes{key, value}) 144 | l.cache[key] = ele 145 | //此处是一个增加操作,即原本不存在,所以直接插入即可,同时在当前数值范围内增加对应的占用空间 146 | l.nowBytes += int64(len(key)) + int64(value.Len()) 147 | } 148 | //添加完成后根据删除掉尾部一部分数据以保证实际使用空间小于设定的空间上限 149 | for l.maxBytes != 0 && l.maxBytes < l.nowBytes { 150 | //删除队尾元素 151 | //删除后执行创建时传入的删除执行函数 152 | ele := l.ll.Back() 153 | if ele != nil { 154 | l.ll.Remove(ele) 155 | kv := ele.Value.(*indexes) 156 | //删除最末尾的同时将其占用空间减去 157 | delete(l.cache, kv.key) 158 | l.nowBytes -= int64(len(kv.key)) + int64(kv.value.Len()) 159 | if l.onRemove != nil { 160 | //删除后的回调函数,可用于持久化该部分数据 161 | l.onRemove(kv.key, kv.value) 162 | } 163 | } 164 | } 165 | l.mutex.Unlock() 166 | } 167 | ``` 168 | 169 | #### Erase 170 | 171 | ​ 以LRU链容器做接收者,从LRU链中删除以key为索引的value,如果不存在则直接结束,删除完成后将其占用的byte数减去,删除后执行函数回调函数,一般用于持久化。 172 | 173 | ```go 174 | func (l *LRU) Erase(key string) { 175 | l.mutex.Lock() 176 | if ele, ok := l.cache[key]; ok { 177 | l.ll.Remove(ele) 178 | kv := ele.Value.(*indexes) 179 | //删除的同时将其占用空间减去 180 | delete(l.cache, kv.key) 181 | l.nowBytes -= int64(len(kv.key)) + int64(kv.value.Len()) 182 | if l.onRemove != nil { 183 | //删除后的回调函数,可用于持久化该部分数据 184 | l.onRemove(kv.key, kv.value) 185 | } 186 | } 187 | l.mutex.Unlock() 188 | } 189 | ``` 190 | 191 | #### Get 192 | 193 | ​ 以LRU链容器做接收者,从LRU链中寻找以key为索引的value,找到对应的value后将其移到首部,随后返回其value,如果没找到以key为索引的value,直接结束即可。 194 | 195 | ```go 196 | func (l *LRU) Get(key string) (value Value, ok bool) { 197 | l.mutex.Lock() 198 | if ele, ok := l.cache[key]; ok { 199 | //找到了value,将其移到链表首部 200 | l.ll.MoveToFront(ele) 201 | kv := ele.Value.(*indexes) 202 | l.mutex.Unlock() 203 | return kv.value, true 204 | } 205 | l.mutex.Unlock() 206 | return nil, false 207 | } 208 | ``` 209 | 210 | ### 使用示例 211 | 212 | ```go 213 | package main 214 | 215 | import ( 216 | "fmt" 217 | lru2 "github.com/hlccd/goSTL/data_structure/lru" 218 | ) 219 | 220 | type Value struct { 221 | Bytes []byte 222 | } 223 | 224 | func (v Value) Len() int { 225 | return len(v.Bytes) 226 | } 227 | func main() { 228 | space :=0 229 | lru := lru2.New(2<<10, nil) 230 | for i := 0; i < 10000; i++ { 231 | v := Value{Bytes: []byte(string(i))} 232 | lru.Insert(string(i), v) 233 | space +=v.Len() 234 | } 235 | fmt.Println("应该占用空间:",space) 236 | fmt.Println("LRU中存放的byte数量:",lru.Size()) 237 | fmt.Println("LRU的byte数量上限:",lru.Cap()) 238 | lru.Erase(string(9999)) 239 | fmt.Println("删除后的LRU中存放的byte数量:",lru.Size()) 240 | fmt.Println("从LRU中找9998") 241 | if v,ok:=lru.Get(string(9998));ok{ 242 | fmt.Println(string(v.(Value).Bytes)) 243 | fmt.Println(string(9998)) 244 | } 245 | fmt.Println("从LRU中找1") 246 | if v,ok:=lru.Get(string(1));ok{ 247 | fmt.Println(string(v.(Value).Bytes)) 248 | fmt.Println(string(1)) 249 | } 250 | } 251 | ``` 252 | 253 | > 应该占用空间: 27824 254 | > LRU中存放的byte数量: 2046 255 | > LRU的byte数量上限: 2048 256 | > 删除后的LRU中存放的byte数量: 2040 257 | > 从LRU中找9998 258 | > ✎ 259 | > ✎ 260 | > 从LRU中找1 261 | > 262 | > 263 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现栈stack.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ 栈(stack)是一个**线性容器**,但不同于其他容器的特点在于,栈是仅仅支持从顶部插入和从顶部删除的操作,即**单向删除和添加**。 6 | 7 | ​ 对于stack的实现,考虑到它是一个线性容器,并且其中的元素仅可通过顶部添加和删除即单项增删,所以可以考虑其**底层使用动态数组**的形式实现,考虑到动态数组需要自行对分配空间进行操作,同时它也类似于vector进行单项操作的情况,所以它的扩容缩容策略同vector一样,但不同点在于它只能使用单侧增删,所以不需要考虑从中间插入的一些情况。 8 | 9 | ### 原理 10 | 11 | ​ 对于一个栈来说,可以将其看作是一个**木桶**,你要在这个容器里放入一些元素,就只能从已有元素的顶部放入,而不是插入的原有的元素之间去,当你要删除元素的时候,也只能从顶部一个一个删除。 12 | 13 | ​ 它是可以动态的对元素进行添加和修改的,而如果说每一次增删元素都使得数组恰好可以容纳所有元素的话,那它在以后的每一次增删的过程中都需要去**重新分配空间**,并将原有的元素复制到新数组中,如果按照这样来操作的话,每次删减都会需要花费大量的时间去进行,将会极大的降低其性能。 14 | 15 | ​ 为了提高效率,可以选择牺牲一定的空间作为冗余量,即**时空权衡**,通过每次扩容时多分配一定的空间,这样在后续添加时就可以减少扩容次数,而在删除元素时,如果冗余量不多时,可以选择不进行缩容,仅将顶部指针下移一位即可,,这样可以极大减少的由于容量不足或超出导致的扩容缩容造成的时间开销。 16 | 17 | #### 扩容策略 18 | 19 | ​ 对于动态数组扩容来说,由于其添加是线性且连续的,虽然stack一次只会添加一个,但为了减少频繁分配空间造成的时间浪费,选择多保留一些冗余空间以方便后续增删操作。 20 | 21 | ​ stack的扩容主要由两种方案: 22 | 23 | **同vector的扩容策略** 24 | 25 | 1. 固定扩容:固定的去增加一定量的空间,该方案时候在数组较大时添加空间,可以避免直接翻倍导致的**冗余过量**问题,到由于增加量是固定的,如果需要一次扩容很多量的话就会比较缓慢。 26 | 2. 翻倍扩容:将原有容量直接翻倍,该方案适合在数组不太大的适合添加空间,可以提高扩容量,增加扩容效率,但数组太大时使用的话会导致一次性增加太多空间,进而造成空间的浪费。 27 | 28 | #### 缩容策略 29 | 30 | ​ 对于动态数组的缩容来说,同扩容类似,由于元素的减少只会是线性且连续的,即每一次只会减少一个,不会存在由于一个元素被删去导致其他已使用的空间也需要被释放。所以stack的缩容方案和stack的扩容方案十分类似,即是它的逆过程: 31 | 32 | **同vector的缩容策略** 33 | 34 | 1. 固定缩容:释放一个固定的空间,该方案适合在当前数组较大的时候进行,可以减缓需要缩小的量,当空间较大的时候如果采取折半缩减的话;将可能在绝大多数时间内都不会被采用,从而造成空间浪费。 35 | 2. 折半缩容:将当前容量进行折半,该方案适合数组不太大的适合进行缩容,可以更快的缩小容量,但对于较大的空间来说并不会频繁使用到。 36 | 37 | ### 实现 38 | 39 | ​ stack栈结构体,包含动态数组和该数组的顶部指针,顶部指针指向实际顶部元素的下一位置,当删除节点时仅仅需要下移顶部指针一位即可,当新增结点时优先利用冗余空间,当冗余空间不足时先倍增空间至2^16,超过后每次增加2^16的空间,删除结点后如果冗余超过2^16,则释放掉,删除后若冗余量超过使用量,也释放掉冗余空间。 40 | 41 | ```go 42 | type stack struct { 43 | data []interface{} //用于存储元素的动态数组 44 | top uint64 //顶部指针 45 | cap uint64 //动态数组的实际空间 46 | mutex sync.Mutex //并发控制锁 47 | } 48 | ``` 49 | 50 | #### 接口 51 | 52 | ```go 53 | type stacker interface { 54 | Iterator() (i *Iterator.Iterator) //返回一个包含栈中所有元素的迭代器 55 | Size() (num uint64) //返回该栈中元素的使用空间大小 56 | Clear() //清空该栈容器 57 | Empty() (b bool) //判断该栈容器是否为空 58 | Push(e interface{}) //将元素e添加到栈顶 59 | Pop() //弹出栈顶元素 60 | Top() (e interface{}) //返回栈顶元素 61 | } 62 | ``` 63 | 64 | #### New 65 | 66 | ​ 新建一个stack栈容器并返回,初始stack的动态数组容量为1,初始stack的顶部指针置0,容量置1。 67 | 68 | ```go 69 | func New() (s *stack) { 70 | return &stack{ 71 | data: make([]interface{}, 1, 1), 72 | top: 0, 73 | cap: 1, 74 | mutex: sync.Mutex{}, 75 | } 76 | } 77 | ``` 78 | 79 | #### Iterator 80 | 81 | ​ 以stack栈容器做接收者,将stack栈容器中不使用空间释放掉,返回一个包含容器中所有使用元素的迭代器。 82 | 83 | ```go 84 | func (s *stack) Iterator() (i *Iterator.Iterator) { 85 | if s == nil { 86 | s = New() 87 | } 88 | s.mutex.Lock() 89 | if s.data == nil { 90 | //data不存在,新建一个 91 | s.data = make([]interface{}, 1, 1) 92 | s.top = 0 93 | s.cap = 1 94 | } else if s.top < s.cap { 95 | //释放未使用的空间 96 | tmp := make([]interface{}, s.top, s.top) 97 | copy(tmp, s.data) 98 | s.data = tmp 99 | } 100 | //创建迭代器 101 | i = Iterator.New(&s.data) 102 | s.mutex.Unlock() 103 | return i 104 | } 105 | ``` 106 | 107 | #### Size 108 | 109 | ​ 以stack栈容器做接收者吗,返回该容器当前含有元素的数量。 110 | 111 | ```go 112 | func (s *stack) Size() (num uint64) { 113 | if s == nil { 114 | s = New() 115 | } 116 | return s.top 117 | } 118 | ``` 119 | 120 | #### Clear 121 | 122 | ​ 以stack栈容器做接收者,将该容器中所承载的元素清空,将该容器的尾指针置0。 123 | 124 | ```go 125 | func (s *stack) Clear() { 126 | if s == nil { 127 | s = New() 128 | } 129 | s.mutex.Lock() 130 | s.data = make([]interface{}, 0, 0) 131 | s.top = 0 132 | s.cap = 1 133 | s.mutex.Unlock() 134 | } 135 | ``` 136 | 137 | #### Empty 138 | 139 | ​ 以stack栈容器做接收者,判断该stack栈容器是否含有元素,如果含有元素则不为空,返回false, 如果不含有元素则说明为空,返回true,如果容器不存在,返回true,该判断过程通过顶部指针数值进行判断,当顶部指针数值为0时说明不含有元素,当顶部指针数值大于0时说明含有元素。 140 | 141 | ```go 142 | func (s *stack) Empty() (b bool) { 143 | if s == nil { 144 | return true 145 | } 146 | return s.Size() == 0 147 | } 148 | ``` 149 | 150 | #### Push 151 | 152 | ​ 以stack栈容器做接收者,在容器顶部插入元素,若存储冗余空间,则在顶部指针位插入元素,随后上移顶部指针,否则进行扩容,扩容后获得冗余空间重复上一步即可。 153 | 154 | ​ 固定扩容值设为2^16,翻倍扩容上限也为2^16。 155 | 156 | ```go 157 | func (s *stack) Push(e interface{}) { 158 | if s == nil { 159 | s = New() 160 | } 161 | s.mutex.Lock() 162 | if s.top < s.cap { 163 | //还有冗余,直接添加 164 | s.data[s.top] = e 165 | } else { 166 | //冗余不足,需要扩容 167 | if s.cap <= 65536 { 168 | //容量翻倍 169 | if s.cap == 0 { 170 | s.cap = 1 171 | } 172 | s.cap *= 2 173 | } else { 174 | //容量增加2^16 175 | s.cap += 65536 176 | } 177 | //复制扩容前的元素 178 | tmp := make([]interface{}, s.cap, s.cap) 179 | copy(tmp, s.data) 180 | s.data = tmp 181 | s.data[s.top] = e 182 | } 183 | s.top++ 184 | s.mutex.Unlock() 185 | } 186 | ``` 187 | 188 | #### Pop 189 | 190 | ​ 以stack栈容器做接收者,弹出容器顶部元素,同时顶部指针下移一位,当顶部指针小于容器切片实际使用空间的一半时,重新分配空间释放未使用部分,若容器为空,则不进行弹出。 191 | 192 | ```go 193 | func (s *stack) Pop() { 194 | if s == nil { 195 | s = New() 196 | return 197 | } 198 | if s.Empty() { 199 | return 200 | } 201 | s.mutex.Lock() 202 | s.top-- 203 | if s.cap-s.top >= 65536 { 204 | //容量和实际使用差值超过2^16时,容量直接减去2^16 205 | s.cap -= 65536 206 | tmp := make([]interface{}, s.cap, s.cap) 207 | copy(tmp, s.data) 208 | s.data = tmp 209 | } else if s.top*2 < s.cap { 210 | //实际使用长度是容量的一半时,进行折半缩容 211 | s.cap /= 2 212 | tmp := make([]interface{}, s.cap, s.cap) 213 | copy(tmp, s.data) 214 | s.data = tmp 215 | } 216 | s.mutex.Unlock() 217 | } 218 | ``` 219 | 220 | #### Top 221 | 222 | ​ 以stack栈容器做接收者,返回该容器的顶部元素,若该容器当前为空,则返回nil。 223 | 224 | ```go 225 | func (s *stack) Top() (e interface{}) { 226 | if s == nil { 227 | return nil 228 | } 229 | if s.Empty() { 230 | return nil 231 | } 232 | s.mutex.Lock() 233 | e = s.data[s.top-1] 234 | s.mutex.Unlock() 235 | return e 236 | } 237 | ``` 238 | 239 | ### 使用示例 240 | 241 | ```go 242 | package main 243 | 244 | import ( 245 | "fmt" 246 | "github.com/hlccd/goSTL/data_structure/stack" 247 | "sync" 248 | ) 249 | 250 | func main() { 251 | s := stack.New() 252 | wg := sync.WaitGroup{} 253 | for i := 0; i < 10; i++ { 254 | wg.Add(1) 255 | go func(num int) { 256 | s.Push(num) 257 | wg.Done() 258 | }(i) 259 | } 260 | wg.Wait() 261 | fmt.Println("使用迭代器遍历全部:") 262 | for i := s.Iterator(); i.HasNext(); i.Next() { 263 | fmt.Println(i.Value()) 264 | } 265 | fmt.Println("使用size变删除边遍历:") 266 | size:=s.Size() 267 | for i := uint64(0); i < size; i++ { 268 | fmt.Println(s.Top()) 269 | s.Pop() 270 | } 271 | } 272 | ``` 273 | 274 | 注:由于过程中的增删过程是并发执行的,所以其结果和下方示例并不完全相同 275 | 276 | > 使用迭代器遍历全部: 277 | > 9 278 | > 3 279 | > 4 280 | > 5 281 | > 6 282 | > 7 283 | > 8 284 | > 0 285 | > 1 286 | > 2 287 | > 使用size变删除边遍历: 288 | > 2 289 | > 1 290 | > 0 291 | > 8 292 | > 7 293 | > 6 294 | > 5 295 | > 4 296 | > 3 297 | > 9 298 | 299 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现独立请求singleFlight.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ singleFlight,独立请求,用于做并发控制,常用于防止**缓存击穿**。 6 | 7 | ​ 对于缓存来说,它一般会有一个过期时间,过期后进行删除,当在删除后的短时间内,如果突然出现了一大批对该数据的并发请求,次数他们都没有从缓存中读取到数据,然后集体涌入数据库中进行IO,引起数据库过载造成故障。 8 | 9 | ​ 为了解决这个问题,可以通过给一组相同的请求添加一个**可重入锁**,即对于拥有同一个关键词的请求来说,可以视为一组相同的请求,此时,只允许其中一个进行请求,对其他进行阻塞操作,当请求结束后获取的数据放入缓存中,其他请求再从缓存中读取即可(**为了防止缓存击穿,可以考虑对返回的nil也进行存储**),这样也就可以避免一大堆相同请求都涌入数据库进行操作导致的压力过载。 10 | 11 | ### 原理 12 | 13 | ​ 实现原理也是相对比较简单的,主要是利用**map**和**可重入锁**(golang中可利用WaitGroup)。 14 | 15 | ​ 当一类拥有相同key的请求发起时,先向map中添加该类请求,随后将可重入锁加一,其他同类请求直接进入阻塞。 16 | 17 | ​ 当请求结束后返回数据,同时将数据放入到请求的结构体内以供同类请求进行使用。 18 | 19 | ​ 本次实现主要有两种形式,第一种是返回数据和错误信息,该方案可用于时间较短的情况,即持续阻塞直到数据返回的情况,但可能会出现由于长期等待导致的阻塞。第二种是直接返回一个channel,当数据获取成功后再向channel中放入数据即可,该方案可用于进行超时控制。 20 | 21 | ### 实现 22 | 23 | ​ 呼叫请求结构体。 24 | 25 | ```go 26 | type call struct { 27 | wg sync.WaitGroup //可重入锁 28 | val interface{} //请求结果 29 | err error //错误反馈 30 | } 31 | ``` 32 | 33 | ​ 一组请求工作,每一类请求对应一个call,利用其内部的可重入锁避免一类请求在短时间内频繁执行,请求组工作由使用者自行分配空间来实现。 34 | 35 | ```go 36 | type Group struct { 37 | m map[string]*call //一类请求与同一类呼叫的映射表 38 | mu sync.Mutex //并发控制锁,保证线程安全 39 | } 40 | ``` 41 | 42 | #### Do 43 | 44 | ​ 以请求组做接收者,传入一个请求类的key和请求调用函数fn,请求时候需要等待之前有的同类请求先完成在进行,防止击穿缓存,对同一个key进行请求时需要分别进行,利用可重入锁实现,请求完成后返回结果和错误信息即可。 45 | 46 | ```go 47 | func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error) { 48 | g.mu.Lock() 49 | if g.m == nil { 50 | g.m = make(map[string]*call) 51 | } 52 | //判断以key为关键词的该类请求是否存在 53 | if c, ok := g.m[key]; ok { 54 | g.mu.Unlock() 55 | // 如果请求正在进行中,则等待 56 | c.wg.Wait() 57 | return c.val, c.err 58 | } 59 | //该类请求不存在,创建个请求 60 | c := new(call) 61 | // 发起请求前加锁,并将请求添加到请求组内以表示该类请求正在处理 62 | c.wg.Add(1) 63 | g.m[key] = c 64 | g.mu.Unlock() 65 | //调用请求函数获取内容 66 | c.val, c.err = fn() 67 | //请求结束 68 | c.wg.Done() 69 | g.mu.Lock() 70 | //从请求组中删除该呼叫请求 71 | delete(g.m, key) 72 | g.mu.Unlock() 73 | return c.val, c.err 74 | } 75 | ``` 76 | 77 | #### DoChan 78 | 79 | ​ 以请求组做接收者,传入一个请求类的key和请求调用函数fn,请求时候需要等待之前有的同类请求先完成在进行,防止击穿缓存,对同一个key进行请求时需要分别进行,利用可重入锁实现,返回一个channel,利用fn函数获取到的数据将会传入其中,可利用channel做超时控制。 80 | 81 | ```go 82 | func (g *Group) DoChan(key string, fn func() (interface{}, error)) (ch chan interface{}) { 83 | ch = make(chan interface{}, 1) 84 | g.mu.Lock() 85 | if g.m == nil { 86 | g.m = make(map[string]*call) 87 | } 88 | if _, ok := g.m[key]; ok { 89 | g.mu.Unlock() 90 | return ch 91 | } 92 | c := new(call) 93 | c.wg.Add(1) // 发起请求前加锁 94 | g.m[key] = c // 添加到 g.m,表明 key 已经有对应的请求在处理 95 | g.mu.Unlock() 96 | go func() { 97 | c.val, c.err = fn() // 调用 fn,发起请求 98 | c.wg.Done() // 请求结束 99 | g.mu.Lock() 100 | delete(g.m, key) // 更新 g.m 101 | ch <- c.val 102 | g.mu.Unlock() 103 | }() 104 | return ch 105 | } 106 | ``` 107 | 108 | #### ForgetUnshared 109 | 110 | ​ 以请求组做接收者,传入一个请求类的key,如果该key存在于请求组内,则将其删除即可,从而实现遗忘该类请求的目的。 111 | 112 | ```go 113 | func (g *Group) ForgetUnshared(key string) { 114 | g.mu.Lock() 115 | _, ok := g.m[key] 116 | if ok { 117 | delete(g.m, key) 118 | } 119 | g.mu.Unlock() 120 | } 121 | ``` 122 | 123 | ### 使用示例 124 | 125 | ```go 126 | package main 127 | 128 | import ( 129 | "fmt" 130 | "github.com/hlccd/goSTL/algorithm/singleFlight" 131 | "sync" 132 | "time" 133 | ) 134 | var mu sync.Mutex 135 | var num = 0 136 | 137 | func get() (interface{}, error) { 138 | mu.Lock() 139 | num++ 140 | e:=num 141 | mu.Unlock() 142 | return e, nil 143 | } 144 | func main() { 145 | wg := sync.WaitGroup{} 146 | sf := singleFlight.Group{} 147 | for i := 0; i < 10; i++ { 148 | wg.Add(1) 149 | go func() { 150 | fmt.Println(sf.Do("hlccd", get)) 151 | wg.Done() 152 | }() 153 | if i == 5 { 154 | sf.ForgetUnshared("hlccd") 155 | } 156 | } 157 | wg.Wait() 158 | ch1 := sf.DoChan("hlccd", func() (interface{}, error) { 159 | time.Sleep(1 * time.Second) 160 | return 1, nil 161 | }) 162 | ch2 := sf.DoChan("hlccd", func() (interface{}, error) { 163 | time.Sleep(1 * time.Second) 164 | return 2, nil 165 | }) 166 | ch3 := sf.DoChan("hlccd", func() (interface{}, error) { 167 | time.Sleep(1 * time.Second) 168 | return 3, nil 169 | }) 170 | select { 171 | case p := <-ch1: 172 | fmt.Println(p) 173 | case p := <-ch2: 174 | fmt.Println(p) 175 | case p := <-ch3: 176 | fmt.Println(p) 177 | case <-time.After(3*time.Second): 178 | fmt.Println("超时") 179 | } 180 | } 181 | ``` 182 | 183 | 注:该过程是个并发的随即情况 184 | 185 | > 1 186 | > 2 187 | > 7 188 | > 2 189 | > 8 190 | > 3 191 | > 5 192 | > 4 193 | > 9 194 | > 1 195 | -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现迭代器iterator.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### Iterator 4 | 5 | #### 概述 6 | 7 | iterator模式:提供一种方法,使之能依次访问容器内的各个元素,而又不暴露该聚合物内部的表述方式。 8 | STL的中心思想是将算法与数据结构分离,彼此独立设计,最后在用iterator将他们结合在一起,获得最大的适配性。 9 | 10 | 由于golang官方未实现泛型,而interface存在可以替换为任意结构的特性,故而可以**使用interface实现泛型**。 11 | 12 | 一个迭代器需要包括其存储的元素序列以及内部存储一个该迭代器当前指向的元素下标。 13 | 14 | ```go 15 | //Iterator迭代器 16 | //包含泛型切片和该迭代器当前指向元素的下标 17 | //可通过下标和泛型切片长度来判断是否可以前移或后移 18 | //当index不小于0时迭代器可前移 19 | //当index小于data的长度时可后移 20 | type Iterator struct { 21 | data *[]interface{} //该迭代器中存放的元素集合的指针 22 | index int //该迭代器当前指向的元素下标,-1即不存在元素 23 | } 24 | ``` 25 | 26 | 对于一个迭代器,它需要执行的主要方法有:返回该首尾迭代器,获取指向某位的迭代器,获取指定位置的元素,判断能否前后移动以及进行前后移动。 27 | 28 | ```go 29 | type Iteratorer interface { 30 | Begin() (I *Iterator) //将该迭代器设为位于首节点并返回新迭代器 31 | End() (I *Iterator) //将该迭代器设为位于尾节点并返回新迭代器 32 | Get(idx int) (I *Iterator) //将该迭代器设为位于第idx节点并返回该迭代器 33 | Value() (e interface{}) //返回该迭代器下标所指元素 34 | HasNext() (b bool) //判断该迭代器是否可以后移 35 | Next() (b bool) //将该迭代器后移一位 36 | HasPre() (b bool) //判罚该迭代器是否可以前移 37 | Pre() (b bool) //将该迭代器前移一位 38 | } 39 | ``` 40 | 41 | #### 接口实现 42 | 43 | ##### New 44 | 45 | 对于迭代器的初始化,需要传入一个所要承载的元素集合的指针,可以自己选择性传入一个index下标。该函数会返回一个承载了该元素集合的迭代器。 46 | 47 | ```go 48 | func New(data *[]interface{}, Idx ...int) (i *Iterator) { 49 | //迭代器下标 50 | var idx int 51 | if len(Idx) <= 0 { 52 | //没有传入下标,则将下标设为0 53 | idx = 0 54 | } else { 55 | //有传入下标,则将传入下标第一个设为迭代器下标 56 | idx = Idx[0] 57 | } 58 | if len((*data)) > 0 { 59 | //如果元素集合非空,则判断下标是否超过元素集合范围 60 | if idx >= len((*data)) { 61 | //如果传入下标超过元素集合范围则寻找最近的下标值 62 | idx = len((*data)) - 1 63 | } 64 | } else { 65 | //如果元素集合为空则将下标设为-1 66 | idx = -1 67 | } 68 | //新建并返回迭代器 69 | return &Iterator{ 70 | data: data, 71 | index: idx, 72 | } 73 | } 74 | ``` 75 | 76 | ##### Bgein 77 | 78 | 以原有的迭代器做接受器,返回一个承载相同元素但下标位于首位的迭代器。 79 | 80 | ```go 81 | func (i *Iterator) Begin() (I *Iterator) { 82 | if i == nil { 83 | //迭代器为空,直接结束 84 | return nil 85 | } 86 | if len((*i.data)) == 0 { 87 | //迭代器元素集合为空,下标设为-1 88 | i.index = -1 89 | } else { 90 | //迭代器元素集合非空,下标设为0 91 | i.index = 0 92 | } 93 | //返回修改后的新指针 94 | return &Iterator{ 95 | data: i.data, 96 | index: i.index, 97 | } 98 | } 99 | ``` 100 | 101 | ##### End 102 | 103 | 以原有的迭代器做接受器,返回一个承载相同元素但下标位于末尾的迭代器。 104 | 105 | ```go 106 | func (i *Iterator) End() (I *Iterator) { 107 | if i == nil { 108 | //迭代器为空,直接返回 109 | return nil 110 | } 111 | if len((*i.data)) == 0 { 112 | //元素集合为空,下标设为-1 113 | i.index = -1 114 | } else { 115 | //元素集合非空,下标设为最后一个元素的下标 116 | i.index = len((*i.data)) - 1 117 | } 118 | //返回修改后的该指针 119 | return &Iterator{ 120 | data: i.data, 121 | index: i.index, 122 | } 123 | } 124 | ``` 125 | 126 | ##### Get 127 | 128 | ​ 以原有的迭代器做接受器,返回一个承载相同元素但下标为自己传入的idx的迭代器,当idx不在元素集合的范围内时,下标设为距离idx最近的值,即小于0设为首位,大于元素集合长度则设为尾部,其他情况设为idx。 129 | 130 | ```go 131 | func (i *Iterator) Get(idx int) (I *Iterator) { 132 | if i == nil { 133 | //迭代器为空,直接返回 134 | return nil 135 | } 136 | if idx <= 0 { 137 | //预设下标超过元素集合范围,将下标设为最近元素的下标,此状态下为首元素下标 138 | idx = 0 139 | } else if idx >= len((*i.data))-1 { 140 | //预设下标超过元素集合范围,将下标设为最近元素的下标,此状态下为尾元素下标 141 | idx = len((*i.data)) - 1 142 | } 143 | if len((*i.data)) > 0 { 144 | //元素集合非空,迭代器下标设为预设下标 145 | i.index = idx 146 | } else { 147 | //元素集合为空,迭代器下标设为-1 148 | i.index = -1 149 | } 150 | //返回修改后的迭代器指针 151 | return i 152 | } 153 | ``` 154 | 155 | ##### Value 156 | 157 | 以原有的迭代器做接受器,返回该迭代器当前下标指向的元素 158 | 159 | ```go 160 | func (i *Iterator) Value() (e interface{}) { 161 | if i == nil { 162 | //迭代器为nil,返回nil 163 | return nil 164 | } 165 | if len((*i.data)) == 0 { 166 | //元素集合为空,返回nil 167 | return nil 168 | } 169 | if i.index <= 0 { 170 | //下标超过元素集合范围下限,最近元素为首元素 171 | i.index = 0 172 | } 173 | if i.index >= len((*i.data)) { 174 | //下标超过元素集合范围上限,最近元素为尾元素 175 | i.index = len((*i.data)) - 1 176 | } 177 | //返回下标指向元素 178 | return (*i.data)[i.index] 179 | } 180 | ``` 181 | 182 | ##### HasNext 183 | 184 | 以原有的迭代器做接受器,判断该迭代器是否可以进行后移,可以则返回true否则返回false。 185 | 186 | ```go 187 | func (i *Iterator) HasNext() (b bool) { 188 | if i == nil { 189 | //迭代器为nil时不能后移 190 | return false 191 | } 192 | if len((*i.data)) == 0 { 193 | //元素集合为空时不能后移 194 | return false 195 | } 196 | //下标到达元素集合上限时不能后移,否则可以后移 197 | return i.index < len((*i.data)) 198 | } 199 | ``` 200 | 201 | ##### Next 202 | 203 | ​ 以原有的迭代器做接受器,将迭代器下标后移,当满足后移条件时进行后移同时返回true,当不满足后移条件时将下标设为尾元素下标同时返回false,当迭代器为nil时返回false。 204 | 205 | ```go 206 | func (i *Iterator) Next() (b bool) { 207 | if i == nil { 208 | //迭代器为nil时返回false 209 | return false 210 | } 211 | if i.HasNext() { 212 | //满足后移条件时进行后移 213 | i.index++ 214 | return true 215 | } 216 | if len((*i.data)) == 0 { 217 | //元素集合为空时下标设为-1同时返回false 218 | i.index = -1 219 | return false 220 | } 221 | //不满足后移条件时将下标设为尾元素下标并返回false 222 | i.index = len((*i.data)) - 1 223 | return false 224 | } 225 | ``` 226 | 227 | ##### HasPre 228 | 229 | 以原有的迭代器做接受器,判断该迭代器是否可以进行前移,可以则返回true否则返回false。 230 | 231 | ```go 232 | func (i *Iterator) End() (I *Iterator) { 233 | if i == nil { 234 | //迭代器为空,直接返回 235 | return nil 236 | } 237 | if len((*i.data)) == 0 { 238 | //元素集合为空,下标设为-1 239 | i.index = -1 240 | } else { 241 | //元素集合非空,下标设为最后一个元素的下标 242 | i.index = len((*i.data)) - 1 243 | } 244 | //返回修改后的该指针 245 | return &Iterator{ 246 | data: i.data, 247 | index: i.index, 248 | } 249 | } 250 | ``` 251 | 252 | ##### Pre 253 | 254 | ​ 以原有的迭代器做接受器,将迭代器下标前移,当满足前移条件时进行前移同时返回true,当不满足前移条件时将下标设为首元素下标同时返回false,当迭代器为nil时返回false,当元素集合为空时下标设为-1同时返回false。 255 | 256 | ```go 257 | func (i *Iterator) Pre() (b bool) { 258 | if i == nil { 259 | //迭代器为nil时返回false 260 | return false 261 | } 262 | if i.HasPre() { 263 | //满足后移条件时进行前移 264 | i.index-- 265 | return true 266 | } 267 | if len((*i.data)) == 0 { 268 | //元素集合为空时下标设为-1同时返回false 269 | i.index = -1 270 | return false 271 | } 272 | //不满足后移条件时将下标设为尾元素下标并返回false 273 | i.index = 0 274 | return false 275 | } 276 | ``` 277 | 278 | #### 使用示例 279 | 280 | ```go 281 | package main 282 | 283 | import ( 284 | "fmt" 285 | "github.com/hlccd/goSTL/utils/iterator" 286 | ) 287 | 288 | func main() { 289 | var arr =make([]interface{},0,0) 290 | arr=append(arr,5) 291 | arr=append(arr,3) 292 | arr=append(arr,2) 293 | arr=append(arr,4) 294 | arr=append(arr,1) 295 | arr=append(arr,4) 296 | arr=append(arr,3) 297 | arr=append(arr,1) 298 | arr=append(arr,5) 299 | arr=append(arr,2) 300 | i:=Iterator.New(&arr) 301 | fmt.Println("begin") 302 | for i:=i.Begin();i.HasNext();i.Next(){ 303 | fmt.Println(i.Value()) 304 | } 305 | fmt.Println() 306 | fmt.Println("end") 307 | for i:=i.End();i.HasPre();i.Pre(){ 308 | fmt.Println(i.Value()) 309 | } 310 | fmt.Println() 311 | fmt.Println("get4") 312 | for i:=i.Get(4);i.HasNext();i.Next(){ 313 | fmt.Println(i.Value()) 314 | } 315 | fmt.Println() 316 | } 317 | ``` 318 | 319 | ##### 示例结果 320 | 321 | > begin 322 | > 5 323 | > 3 324 | > 2 325 | > 4 326 | > 1 327 | > 4 328 | > 3 329 | > 1 330 | > 5 331 | > 2 332 | > 333 | > end 334 | > 2 335 | > 5 336 | > 1 337 | > 3 338 | > 4 339 | > 1 340 | > 4 341 | > 2 342 | > 3 343 | > 5 344 | > 345 | > get4 346 | > 1 347 | > 4 348 | > 3 349 | > 1 350 | > 5 351 | > 2 -------------------------------------------------------------------------------- /blog/数据结构STL——golang实现队列queue.md: -------------------------------------------------------------------------------- 1 | github仓库存储地址:https://github.com/hlccd/goSTL 2 | 3 | ### 概述 4 | 5 | ​ 队列(queue)是一个封装了动态大小数组的顺序容器。除了可以包含任意类型的元素外,更主要是的它满足**FIFO**的先进先出模式,对于一些排队问题可以考虑使用队列来存储。 6 | 7 | ​ 对于queue的实现,由于它也是一个线性容器,底层依然可以考虑使用动态数组来实现,但它和vector仍有一定的不同,vector的冗余量主要是在尾部,毕竟vector要实现随机读取的话中间和首部不能有空余量,而对于queue来说,它的添加只在尾部,而首部仅仅只做删除,所以除了在尾部留有一定的空间做添加之外,也可以在首部删除后留有不多的余量以**避免多次分配空间**。 8 | 9 | ### 原理 10 | 11 | ​ 对于一个queue来说,它可以**在尾部添加元素**,**在首部删除元素**。而同vector一样,如果每次增删都要重新分配空间,将会极大的降低效率,所以可以考虑对前后都留有一定的冗余,以此来减少分配空间和复制的次数,从而减少时间开销。 12 | 13 | ​ 对于首部的冗余来说,它的存在主要是为了减少删除后就重新分配空间并复制,同时对于尾部添加时,如果尾部冗余不足可以将使用的元素整体前移到首部,即将首部冗余挪到尾部去,从而减少了空间分配的次数。 14 | 15 | ​ 对于尾部的冗余来说,它存在的目的和vector类似,仅仅是为了后续元素时更快而已。 16 | 17 | ​ 和vector一样,都是通过设置一定量的冗余来换取操作次数的减少,从而提高效率减少时间损耗。 18 | 19 | #### 扩容策略 20 | 21 | ​ 对于queue的动态数组扩容来说,由于其添加是线性且连续的,即每一次只会增加一个,并且每一次都只会在它的尾部,不像vector一样可能在数组的任意位置进行添加,同时由于首部也有冗余,所以它的扩容也需要考虑首部的情况。 22 | 23 | ​ queue的扩容主要由三种方案: 24 | 25 | 1. 利用首部:**严格来说其实并没有进行扩容**,而是将承载的元素前移到首部,即将首部的冗余平移到最后进行利用。 26 | 2. 固定扩容:固定的去增加一定量的空间,该方案时候在数组较大时添加空间,可以避免直接翻倍导致的**冗余过量**问题,到由于增加量是固定的,如果需要一次扩容很多量的话就会比较缓慢。(同vector) 27 | 3. 翻倍扩容:将原有容量直接翻倍,该方案适合在数组不太大的适合添加空间,可以提高扩容量,增加扩容效率,但数组太大时使用的话会导致一次性增加太多空间,进而造成空间的浪费。(同vector) 28 | 29 | #### 缩容策略 30 | 31 | ​ 对于queue的数组来说,它的缩容不同于扩容,由于删除元素只会在首部进行,所以缩容其实也只会在首部进行,考虑到首部并不会进行添加,所以也不需要冗余太多的量进行减缓,即可以将设定上限减少一些,如(2^10): 32 | 33 | 1. 固定缩容:释放一个固定的空间,该方案适合在当前数组较大的时候进行,可以减缓需要缩小的量,当首部冗余超过上限时进行缩容,**一次性全部释放即可**。 34 | 2. 折半缩容:当**首部冗余超过了实际承载的元素的数量**时,需要对首部进行缩容,同前者一样,不需要考虑首部添加的问题,即采用对首部冗余全部释放的方式。 35 | 36 | ### 实现 37 | 38 | ​ queue底层同样使用动态数组实现,同时,由于首部只做删除,尾部只做添加,而首尾两侧都有一定的冗余,所以需要对两侧都进行记录,也可以根据尾部下标减首部下标得出实际承载元素的量,与此同时,需要引入cap以记录实际分配的空间大小,也可以根据cap和end计算出尾部冗余量。同时,为了解决在高并发情况下的数据不一致问题,引入了并发控制锁。 39 | 40 | ```go 41 | type queue struct { 42 | data []interface{} //泛型切片 43 | begin uint64 //首节点下标 44 | end uint64 //尾节点下标 45 | cap uint64 //容量 46 | mutex sync.Mutex //并发控制锁 47 | } 48 | ``` 49 | 50 | #### 接口 51 | 52 | ```go 53 | type queuer interface { 54 | Iterator() (i *Iterator.Iterator) //返回包含队列中所有元素的迭代器 55 | Size() (num uint64) //返回该队列中元素的使用空间大小 56 | Clear() //清空该队列 57 | Empty() (b bool) //判断该队列是否为空 58 | Push(e interface{}) //将元素e添加到该队列末尾 59 | Pop() (e interface{}) //将该队列首元素弹出并返回 60 | Front() (e interface{}) //获取该队列首元素 61 | Back() (e interface{}) //获取该队列尾元素 62 | } 63 | ``` 64 | 65 | #### New 66 | 67 | ​ 创建一个queue容器并初始化,同时返回其指针。 68 | 69 | ```go 70 | func New() (q *queue) { 71 | return &queue{ 72 | data: make([]interface{}, 1, 1), 73 | begin: 0, 74 | end: 0, 75 | cap: 1, 76 | mutex: sync.Mutex{}, 77 | } 78 | } 79 | ``` 80 | 81 | #### Iterator 82 | 83 | ​ 将队列中承载元素传入迭代器中,不清除队列中的冗余量。返回迭代器指针,用于遍历队列。 84 | 85 | ```go 86 | func (q *queue) Iterator() (i *Iterator.Iterator) { 87 | if q == nil { 88 | q=New() 89 | } 90 | q.mutex.Lock() 91 | tmp:=make([]interface{},q.end-q.begin,q.end-q.begin) 92 | copy(tmp, q.data[q.begin:q.end]) 93 | i = Iterator.New(&tmp) 94 | q.mutex.Unlock() 95 | return i 96 | } 97 | ``` 98 | 99 | #### Size 100 | 101 | ​ 返回queue中当前所包含的元素个数,由于其数值必然是非负整数,所以选用了**uint64**。 102 | 103 | ```go 104 | func (q *queue) Size() (num uint64) { 105 | if q == nil { 106 | q = New() 107 | } 108 | return q.end - q.begin 109 | } 110 | ``` 111 | 112 | #### Clear 113 | 114 | ​ 清空了queue中所承载的所有元素。 115 | 116 | ```go 117 | func (q *queue) Clear() { 118 | if q == nil { 119 | q = New() 120 | } 121 | q.mutex.Lock() 122 | q.data = make([]interface{}, 1, 1) 123 | q.begin = 0 124 | q.end = 0 125 | q.cap = 1 126 | q.mutex.Unlock() 127 | } 128 | ``` 129 | 130 | #### Empty 131 | 132 | ​ 判断queue中是否为空,通过Size()是否为0进行判断。 133 | 134 | ```go 135 | func (q *queue) Empty() (b bool) { 136 | if q == nil { 137 | q = New() 138 | } 139 | return q.Size() <= 0 140 | } 141 | ``` 142 | 143 | #### Push 144 | 145 | ​ 以queue为接受器,向queue尾部添加一个元素,添加元素会出现两种情况,第三种是还有冗余量,此时**直接覆盖**以len为下标指向的位置即可,另一种情况是没有冗余量了,需要对动态数组进行**扩容**,此时就需要利用扩容策略。另一种是尾部没有冗余量,但首部仍有冗余量,此时可以将承载元素前移,把首部冗余量”借“过来使用。 146 | 147 | ​ 扩容策略上文已做描述,可返回参考,该实现过程种将两者进行了结合使用,可参考下方注释。 148 | 149 | ​ 固定扩容值设为2^16,翻倍扩容上限也为2^16。 150 | 151 | ```go 152 | func (q *queue) Push(e interface{}) { 153 | if q == nil { 154 | q = New() 155 | } 156 | q.mutex.Lock() 157 | if q.end < q.cap { 158 | //不需要扩容 159 | q.data[q.end] = e 160 | } else { 161 | //需要扩容 162 | if q.begin > 0 { 163 | //首部有冗余,整体前移 164 | for i := uint64(0); i < q.end-q.begin; i++ { 165 | q.data[i] = q.data[i+q.begin] 166 | } 167 | q.end -= q.begin 168 | q.begin = 0 169 | } else { 170 | //冗余不足,需要扩容 171 | if q.cap <= 65536 { 172 | //容量翻倍 173 | if q.cap == 0 { 174 | q.cap = 1 175 | } 176 | q.cap *= 2 177 | } else { 178 | //容量增加2^16 179 | q.cap += 2 ^ 16 180 | } 181 | //复制扩容前的元素 182 | tmp := make([]interface{}, q.cap, q.cap) 183 | copy(tmp, q.data) 184 | q.data = tmp 185 | } 186 | q.data[q.end] = e 187 | } 188 | q.end++ 189 | q.mutex.Unlock() 190 | } 191 | ``` 192 | 193 | #### Pop 194 | 195 | ​ 以queue队列容器做接收者,弹出容器首部元素,同时begin++即可,若容器为空,则不进行弹出,当弹出元素后,可能进行缩容,由于首部不会进行添加,所以不需要太多的冗余,即将首部冗余上限设为2^10,固定缩容和折半缩容都参考此值执行,具体缩容策略可参考上文介绍。 196 | 197 | ```go 198 | func (q *queue) Pop() (e interface{}) { 199 | if q == nil { 200 | q = New() 201 | return nil 202 | } 203 | if q.Empty() { 204 | q.Clear() 205 | return nil 206 | } 207 | q.mutex.Lock() 208 | e = q.data[q.begin] 209 | q.begin++ 210 | if q.begin >= 1024 || q.begin*2>q.end { 211 | //首部冗余超过2^10或首部冗余超过实际使用 212 | q.cap -= q.begin 213 | q.end -= q.begin 214 | tmp := make([]interface{}, q.cap, q.cap) 215 | copy(tmp, q.data[q.begin:]) 216 | q.data = tmp 217 | q.begin=0 218 | } 219 | q.mutex.Unlock() 220 | return e 221 | } 222 | ``` 223 | 224 | #### Front 225 | 226 | ​ 以queue为接受器,返回vector所承载的元素中位于**首部**的元素,如果queue为nil或者元素数组为nil或为空,则返回nil。考虑到仅仅只是读取元素,故不对该过程进行加锁操作。 227 | 228 | ```go 229 | func (q *queue) Front() (e interface{}) { 230 | if q == nil { 231 | q=New() 232 | return nil 233 | } 234 | if q.Empty() { 235 | q.Clear() 236 | return nil 237 | } 238 | return q.data[q.begin] 239 | } 240 | ``` 241 | 242 | #### Back 243 | 244 | ​ 以queue为接受器,返回queue所承载的元素中位于**尾部**的元素,如果queue为nil或者元素数组为nil或为空,则返回nil。考虑到仅仅只是读取元素,故不对该过程进行加锁操作。 245 | 246 | ```go 247 | func (q *queue) Back() (e interface{}) { 248 | if q == nil { 249 | q=New() 250 | return nil 251 | } 252 | if q.Empty() { 253 | q.Clear() 254 | return nil 255 | } 256 | return q.data[q.end-1] 257 | } 258 | ``` 259 | 260 | ### 使用示例 261 | 262 | ```go 263 | package main 264 | 265 | import ( 266 | "fmt" 267 | "github.com/hlccd/goSTL/data_structure/queue" 268 | "sync" 269 | ) 270 | 271 | func main() { 272 | q := queue.New() 273 | wg := sync.WaitGroup{} 274 | //随机插入队列中 275 | for i := 0; i < 8; i++ { 276 | wg.Add(1) 277 | go func(num int) { 278 | fmt.Println(num) 279 | q.Push(num) 280 | wg.Done() 281 | }(i) 282 | } 283 | wg.Wait() 284 | fmt.Println("输出首部:", q.Front()) 285 | fmt.Println("输出尾部:", q.Back()) 286 | fmt.Println("弹出并输出前4个:") 287 | for i := uint64(0); i < q.Size()-1; i++ { 288 | fmt.Println(q.Pop()) 289 | } 290 | //在尾部再添加4个,从10开始以做区分 291 | for i := 10; i < 14; i++ { 292 | q.Push(i) 293 | } 294 | fmt.Println("从头输出全部:") 295 | for ;!q.Empty();{ 296 | fmt.Println(q.Pop()) 297 | } 298 | } 299 | 300 | ``` 301 | 302 | 注:由于过程中的增删过程是并发执行的,所以其结果和下方示例并不完全相同 303 | 304 | > 0 305 | > 7 306 | > 1 307 | > 2 308 | > 3 309 | > 4 310 | > 5 311 | > 6 312 | > 输出首部: 0 313 | > 输出尾部: 6 314 | > 弹出并输出前4个: 315 | > 0 316 | > 7 317 | > 1 318 | > 2 319 | > 从头输出全部: 320 | > 3 321 | > 4 322 | > 5 323 | > 6 324 | > 10 325 | > 11 326 | > 12 327 | > 13 328 | -------------------------------------------------------------------------------- /data_structure/avlTree/avlTree.go: -------------------------------------------------------------------------------- 1 | package avlTree 2 | 3 | //@Title avlTree 4 | //@Description 5 | // 平衡二叉树-Balanced Binary Tree 6 | // 以二叉树的形式实现 7 | // 平衡二叉树实例保存根节点和比较器以及保存的数量 8 | // 可以在创建时设置节点是否可重复 9 | // 若节点可重复则增加节点中的数值,否则对节点存储元素进行覆盖 10 | // 平衡二叉树在添加和删除时都将对节点进行平衡,以保证一个节点的左右子节点高度差不超过1 11 | // 使用互斥锁实现并发控制 12 | 13 | import ( 14 | "github.com/hlccd/goSTL/utils/comparator" 15 | "github.com/hlccd/goSTL/utils/iterator" 16 | "sync" 17 | ) 18 | 19 | //avlTree平衡二叉树结构体 20 | //该实例存储平衡二叉树的根节点 21 | //同时保存该二叉树已经存储了多少个元素 22 | //二叉树中排序使用的比较器在创建时传入,若不传入则在插入首个节点时从默认比较器中寻找 23 | //创建时传入是否允许该二叉树出现重复值,如果不允许则进行覆盖,允许则对节点数目增加即可 24 | type AvlTree struct { 25 | root *node //根节点指针 26 | size int //存储元素数量 27 | cmp comparator.Comparator //比较器 28 | isMulti bool //是否允许重复 29 | mutex sync.Mutex //并发控制锁 30 | } 31 | 32 | //avlTree平衡二叉树容器接口 33 | //存放了avlTree平衡二叉树可使用的函数 34 | //对应函数介绍见下方 35 | type avlTreer interface { 36 | Iterator() (i *Iterator.Iterator) //返回包含该二叉树的所有元素,重复则返回多个 37 | Size() (num int) //返回该二叉树中保存的元素个数 38 | Clear() //清空该二叉树 39 | Empty() (b bool) //判断该二叉树是否为空 40 | Insert(e interface{}) (b bool) //向二叉树中插入元素e 41 | Erase(e interface{}) (b bool) //从二叉树中删除元素e 42 | Count(e interface{}) (num int) //从二叉树中寻找元素e并返回其个数 43 | } 44 | 45 | //@title New 46 | //@description 47 | // 新建一个avlTree平衡二叉树容器并返回 48 | // 初始根节点为nil 49 | // 传入该二叉树是否为可重复属性,如果为true则保存重复值,否则对原有相等元素进行覆盖 50 | // 若有传入的比较器,则将传入的第一个比较器设为该二叉树的比较器 51 | //@receiver nil 52 | //@param isMulti bool 该二叉树是否保存重复值? 53 | //@param Cmp ...comparator.Comparator avlTree比较器集 54 | //@return avl *avlTree 新建的avlTree指针 55 | func New(isMulti bool, cmps ...comparator.Comparator) (avl *AvlTree) { 56 | //判断是否有传入比较器,若有则设为该二叉树默认比较器 57 | var cmp comparator.Comparator 58 | if len(cmps) == 0 { 59 | cmp = nil 60 | } else { 61 | cmp = cmps[0] 62 | } 63 | return &AvlTree{ 64 | root: nil, 65 | size: 0, 66 | cmp: cmp, 67 | isMulti: isMulti, 68 | } 69 | } 70 | 71 | //@title Iterator 72 | //@description 73 | // 以avlTree平衡二叉树做接收者 74 | // 将该二叉树中所有保存的元素将从根节点开始以中缀序列的形式放入迭代器中 75 | // 若允许重复存储则对于重复元素进行多次放入 76 | //@receiver avl *avlTree 接受者avlTree的指针 77 | //@param nil 78 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 79 | func (avl *AvlTree) Iterator() (i *Iterator.Iterator) { 80 | if avl == nil { 81 | return nil 82 | } 83 | avl.mutex.Lock() 84 | es := avl.root.inOrder() 85 | i = Iterator.New(&es) 86 | avl.mutex.Unlock() 87 | return i 88 | } 89 | 90 | //@title Size 91 | //@description 92 | // 以avlTree平衡二叉树做接收者 93 | // 返回该容器当前含有元素的数量 94 | // 如果容器为nil返回0 95 | //@receiver avl *avlTree 接受者avlTree的指针 96 | //@param nil 97 | //@return num int 容器中实际使用元素所占空间大小 98 | func (avl *AvlTree) Size() (num int) { 99 | if avl == nil { 100 | return 0 101 | } 102 | return avl.size 103 | } 104 | 105 | //@title Clear 106 | //@description 107 | // 以avlTree平衡二叉树做接收者 108 | // 将该容器中所承载的元素清空 109 | // 将该容器的size置0 110 | //@receiver avl *avlTree 接受者avlTree的指针 111 | //@param nil 112 | //@return nil 113 | func (avl *AvlTree) Clear() { 114 | if avl == nil { 115 | return 116 | } 117 | avl.mutex.Lock() 118 | avl.root = nil 119 | avl.size = 0 120 | avl.mutex.Unlock() 121 | } 122 | 123 | //@title Empty 124 | //@description 125 | // 以avlTree平衡二叉树做接收者 126 | // 判断该二叉搜索树是否含有元素 127 | // 如果含有元素则不为空,返回false 128 | // 如果不含有元素则说明为空,返回true 129 | // 如果容器不存在,返回true 130 | //@receiver avl *avlTree 接受者avlTree的指针 131 | //@param nil 132 | //@return b bool 该容器是空的吗? 133 | func (avl *AvlTree) Empty() (b bool) { 134 | if avl == nil { 135 | return true 136 | } 137 | if avl.size > 0 { 138 | return false 139 | } 140 | return true 141 | } 142 | 143 | //@title Insert 144 | //@description 145 | // 以avlTree平衡二叉树做接收者 146 | // 向二叉树插入元素e,若不允许重复则对相等元素进行覆盖 147 | // 如果二叉树为空则之间用根节点承载元素e,否则以根节点开始进行查找 148 | // 当节点左右子树高度差超过1时将进行旋转以保持平衡 149 | //@receiver avl *avlTree 接受者avlTree的指针 150 | //@param e interface{} 待插入元素 151 | //@return b bool 添加成功? 152 | func (avl *AvlTree) Insert(e interface{}) (b bool) { 153 | if avl == nil { 154 | return false 155 | } 156 | avl.mutex.Lock() 157 | if avl.Empty() { 158 | if avl.cmp == nil { 159 | avl.cmp = comparator.GetCmp(e) 160 | } 161 | if avl.cmp == nil { 162 | return 163 | } 164 | //二叉树为空,用根节点承载元素e 165 | avl.root = newNode(e) 166 | avl.size = 1 167 | avl.mutex.Unlock() 168 | return true 169 | } 170 | //从根节点进行插入,并返回节点,同时返回是否插入成功 171 | avl.root, b = avl.root.insert(e, avl.isMulti, avl.cmp) 172 | if b { 173 | //插入成功,数量+1 174 | avl.size++ 175 | } 176 | avl.mutex.Unlock() 177 | return b 178 | } 179 | 180 | //@title Erase 181 | //@description 182 | // 以avlTree平衡二叉树做接收者 183 | // 从平衡二叉树中删除元素e 184 | // 若允许重复记录则对承载元素e的节点中数量记录减一即可 185 | // 若不允许重复记录则删除该节点同时将前缀节点或后继节点更换过来以保证二叉树的不发送断裂 186 | // 如果该二叉树仅持有一个元素且根节点等价于待删除元素,则将二叉树根节点置为nil 187 | //@receiver avl *avlTree 接受者avlTree的指针 188 | //@param e interface{} 待删除元素 189 | //@return b bool 删除成功? 190 | func (avl *AvlTree) Erase(e interface{}) (b bool) { 191 | if avl == nil { 192 | return false 193 | } 194 | if avl.Empty() { 195 | return false 196 | } 197 | avl.mutex.Lock() 198 | if avl.size == 1 && avl.cmp(avl.root.value, e) == 0 { 199 | //二叉树仅持有一个元素且根节点等价于待删除元素,将二叉树根节点置为nil 200 | avl.root = nil 201 | avl.size = 0 202 | avl.mutex.Unlock() 203 | return true 204 | } 205 | //从根节点进行插入,并返回节点,同时返回是否删除成功 206 | avl.root, b = avl.root.erase(e, avl.cmp) 207 | if b { 208 | avl.size-- 209 | } 210 | avl.mutex.Unlock() 211 | return b 212 | } 213 | 214 | //@title Count 215 | //@description 216 | // 以avlTree平衡二叉树做接收者 217 | // 从搜素二叉树中查找元素e的个数 218 | // 如果找到则返回该二叉树中和元素e相同元素的个数 219 | // 如果不允许重复则最多返回1 220 | // 如果未找到则返回0 221 | //@receiver avl *avlTree 接受者avlTree的指针 222 | //@param e interface{} 待查找元素 223 | //@return num int 待查找元素在二叉树中存储的个数 224 | func (avl *AvlTree) Count(e interface{}) (num int) { 225 | if avl == nil { 226 | //二叉树为空,返回0 227 | return 0 228 | } 229 | if avl.Empty() { 230 | return 0 231 | } 232 | avl.mutex.Lock() 233 | num = avl.root.count(e, avl.isMulti, avl.cmp) 234 | avl.mutex.Unlock() 235 | return num 236 | } 237 | 238 | //@title Find 239 | //@description 240 | // 以avlTree平衡二叉树做接收者 241 | // 从搜素二叉树中查找以元素e为索引信息的全部信息 242 | // 如果找到则返回该二叉树中和索引元素e相同的元素的全部信息 243 | // 如果未找到则返回nil 244 | //@receiver avl *avlTree 接受者avlTree的指针 245 | //@param e interface{} 待查找索引元素 246 | //@return ans interface{} 待查找索引元素所指向的元素 247 | func (avl *AvlTree) Find(e interface{}) (ans interface{}) { 248 | if avl == nil { 249 | //二叉树为空,返回0 250 | return 0 251 | } 252 | if avl.Empty() { 253 | return 0 254 | } 255 | avl.mutex.Lock() 256 | ans = avl.root.find(e, avl.isMulti, avl.cmp) 257 | avl.mutex.Unlock() 258 | return ans 259 | } 260 | -------------------------------------------------------------------------------- /data_structure/bitmap/bitmap.go: -------------------------------------------------------------------------------- 1 | package bitmap 2 | 3 | //@Title bitmap 4 | //@Description 5 | // bitmap位图容器包 6 | // 内部使用uint64切片进行存储 7 | // 由于数字在计算机内部存储时采用多个bit组成一个字符 8 | // 而一bit只有1和0两个情况,所以也可以使用一个bit表示任意一位存在 9 | // 该数据结构主要可以进行过滤去重、标注是否存在、快速排序的功能 10 | 11 | //bitmap位图结构体 12 | //包含其用于存储的uint64元素切片 13 | //选用uint64是为了更多的利用bit位 14 | type Bitmap struct { 15 | bits []uint64 16 | } 17 | 18 | //bitmap位图容器接口 19 | //存放了bitmap容器可使用的函数 20 | //对应函数介绍见下方 21 | type bitmaper interface { 22 | Insert(num uint) //在num位插入元素 23 | Delete(num uint) //删除第num位 24 | Check(num uint) (b bool) //检查第num位是否有元素 25 | All() (nums []uint) //返回所有存储的元素的下标 26 | Clear() //清空 27 | } 28 | 29 | //@title New 30 | //@description 31 | // 新建一个bitmap位图容器并返回 32 | // 初始bitmap的切片数组为空 33 | //@receiver nil 34 | //@param nil 35 | //@return bm *Bitmap 新建的bitmap指针 36 | func New() (bm *Bitmap) { 37 | return &Bitmap{ 38 | bits: make([]uint64, 0, 0), 39 | } 40 | } 41 | 42 | //@title Insert 43 | //@description 44 | // 以bitmap位图容器做接收者 45 | // 向位图中第num位插入一个元素(下标从0开始) 46 | // 当num大于当前所能存储的位范围时,需要进行扩增 47 | // 若要插入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 48 | // 否则则直接增加到可以容纳第num位的位置,以此可以提高冗余量,避免多次增加 49 | //@receiver bm *Bitmap 接受者bitmap的指针 50 | //@param num int 待插入的位的下标 51 | //@return nil 52 | func (bm *Bitmap) Insert(num uint) { 53 | //bm不存在时直接结束 54 | if bm == nil { 55 | return 56 | } 57 | //开始插入 58 | if num/64+1 > uint(len(bm.bits)) { 59 | //当前冗余量小于num位,需要扩增 60 | var tmp []uint64 61 | //通过冗余扩增减少扩增次数 62 | if num/64+1 < uint(len(bm.bits)+1024) { 63 | //入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 64 | tmp = make([]uint64, len(bm.bits)+1024) 65 | } else { 66 | //直接增加到可以容纳第num位的位置 67 | tmp = make([]uint64, num/64+1) 68 | } 69 | //将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的 70 | copy(tmp, bm.bits) 71 | bm.bits = tmp 72 | } 73 | //将第num位设为1即实现插入 74 | bm.bits[num/64] ^= 1 << (num % 64) 75 | } 76 | 77 | //@title Delete 78 | //@description 79 | // 以bitmap位图容器做接收者 80 | // 向位图中第num位删除一个元素(下标从0开始) 81 | // 当num大于当前所能存储的位范围时,直接结束即可 82 | // 删除完成后对切片最后存储的uint64进行判断是否大于1,若大于1则不做缩容 83 | // 若等于0则可以进行缩容 84 | // 对于缩容而言,从后往前遍历判断最后有多少个连续的0,即可以删除的多少组 85 | // 若可删除的组大于总组数的一半则进行删除,否则则当作冗余量即可 86 | // 若可删除的组数超过1024个时,则先删除1024个 87 | //@receiver bm *Bitmap 接受者bitmap的指针 88 | //@param num int 待删除的位的下标 89 | //@return nil 90 | func (bm *Bitmap) Delete(num uint) { 91 | //bm不存在时直接结束 92 | if bm == nil { 93 | return 94 | } 95 | //num超出范围,直接结束 96 | if num/64+1 > uint(len(bm.bits)) { 97 | return 98 | } 99 | //将第num位设为0 100 | bm.bits[num/64] &^= 1 << (num % 64) 101 | if bm.bits[len(bm.bits)-1] == 0 { 102 | //最后一组为0,可能进行缩容 103 | //从后往前遍历判断可缩容内容是否小于总组数 104 | i := len(bm.bits) - 1 105 | for ; i >= 0; i-- { 106 | if bm.bits[i] == 0 && i != len(bm.bits)-256 { 107 | continue 108 | } else { 109 | //不为0或到1024个时即可返回 110 | break 111 | } 112 | } 113 | if i <= len(bm.bits)/2 || i == len(bm.bits)-256 { 114 | //小于总组数一半或超过1023个,进行缩容 115 | bm.bits = bm.bits[:i+1] 116 | } 117 | } else { 118 | return 119 | } 120 | } 121 | 122 | //@title Check 123 | //@description 124 | // 以bitmap位图容器做接收者 125 | // 检验第num位在位图中是否存在 126 | // 当num大于当前所能存储的位范围时,直接返回false 127 | // 否则判断第num为是否为1,为1返回true,否则返回false 128 | //@receiver bm *Bitmap 接受者bitmap的指针 129 | //@param num int 待检测位的下标 130 | //@return b bool 第num位存在于位图中吗? 131 | func (bm *Bitmap) Check(num uint) (b bool) { 132 | //bm不存在时直接返回false并结束 133 | if bm == nil { 134 | return false 135 | } 136 | //num超出范围,直接返回false并结束 137 | if num/64+1 > uint(len(bm.bits)) { 138 | return false 139 | } 140 | //判断第num是否为1,为1返回true,否则为false 141 | if bm.bits[num/64]&(1<<(num%64)) > 0 { 142 | return true 143 | } 144 | return false 145 | } 146 | 147 | //@title All 148 | //@description 149 | // 以bitmap位图容器做接收者 150 | // 返回所有在位图中存在的元素的下标 151 | // 返回的下标是单调递增序列 152 | //@receiver bm *Bitmap 接受者bitmap的指针 153 | //@param nil 154 | //@return nums []uint 所有在位图中存在的元素的下标集合 155 | func (bm *Bitmap) All() (nums []uint) { 156 | //对要返回的集合进行初始化,以避免返回nil 157 | nums = make([]uint, 0, 0) 158 | //bm不存在时直接返回并结束 159 | if bm == nil { 160 | return nums 161 | } 162 | //分组遍历判断某下标的元素是否存在于位图中,即其值是否为1 163 | for j := 0; j < len(bm.bits); j++ { 164 | for i := 0; i < 64; i++ { 165 | if bm.bits[j]&(1< 0 { 166 | //该元素存在,添加入结果集合内 167 | nums = append(nums, uint(j*64+i)) 168 | } 169 | } 170 | } 171 | return nums 172 | } 173 | 174 | //@title Clear 175 | //@description 176 | // 以bitmap位图容器做接收者 177 | // 清空位图 178 | //@receiver bm *Bitmap 接受者bitmap的指针 179 | //@param nil 180 | //@return nil 181 | func (bm *Bitmap) Clear() { 182 | if bm == nil { 183 | return 184 | } 185 | bm.bits = make([]uint64, 0, 0) 186 | } 187 | -------------------------------------------------------------------------------- /data_structure/bloomFilter/bloomFilter.go: -------------------------------------------------------------------------------- 1 | package bloomFilter 2 | 3 | //@Title bloomFilter 4 | //@Description 5 | // bloomFilter布隆过滤器容器包 6 | // 内部使用uint64切片进行存储 7 | // 将任意类型的值进行hash计算后放入布隆过滤器中 8 | // 可用于查找某一值是否已经插入过,但查找存在误差,只能确定其不存在,不能保证其必然存在 9 | // 不能用于删除某一特定值,但可清空整个布隆过滤器 10 | 11 | import "fmt" 12 | 13 | //bloomFilter布隆过滤器结构体 14 | //包含其用于存储的uint64元素切片 15 | //选用uint64是为了更多的利用bit位 16 | type bloomFilter struct { 17 | bits []uint64 18 | hash Hash 19 | } 20 | 21 | //bloomFilter布隆过滤器接口 22 | //存放了bloomFilter布隆过滤器可使用的函数 23 | //对应函数介绍见下方 24 | type bloomFilteror interface { 25 | Insert(v interface{}) //向布隆过滤器中插入v 26 | Check(v interface{}) (b bool) //检查该值是否存在于布隆过滤器中,该校验存在误差 27 | Clear() //清空该布隆过滤器 28 | } 29 | 30 | //允许自行传入hash函数 31 | type Hash func(v interface{}) (h uint32) 32 | 33 | //@title hash 34 | //@description 35 | // 传入一个虚拟节点id和实际结点 36 | // 计算出它的hash值 37 | // 逐层访问并利用素数131计算其hash值随后返回 38 | //@receiver nil 39 | //@param v interface{} 待计算的值 40 | //@return h uint32 计算得到的hash值 41 | func hash(v interface{}) (h uint32) { 42 | h = uint32(0) 43 | s := fmt.Sprintf("131-%v-%v", v,v) 44 | bs := []byte(s) 45 | for i := range bs { 46 | h += uint32(bs[i]) * 131 47 | } 48 | return h 49 | } 50 | 51 | //@title New 52 | //@description 53 | // 新建一个bloomFilter布隆过滤器容器并返回 54 | // 初始bloomFilter的切片数组为空 55 | //@receiver nil 56 | //@param h Hash hash函数 57 | //@return bf *bloomFilter 新建的bloomFilter指针 58 | func New(h Hash) (bf *bloomFilter) { 59 | if h == nil { 60 | h = hash 61 | } 62 | return &bloomFilter{ 63 | bits: make([]uint64, 0, 0), 64 | hash: h, 65 | } 66 | } 67 | 68 | //@title Insert 69 | //@description 70 | // 以bloomFilter布隆过滤器容器做接收者 71 | // 先将待插入的value计算得到其哈希值hash 72 | // 再向布隆过滤器中第hash位插入一个元素(下标从0开始) 73 | // 当hash大于当前所能存储的位范围时,需要进行扩增 74 | // 若要插入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 75 | // 否则则直接增加到可以容纳第hash位的位置,以此可以提高冗余量,避免多次增加 76 | //@receiver bf *bloomFilter 接收者bloomFilter指针 77 | //@param v interface{} 待插入的值 78 | //@return nil 79 | func (bf *bloomFilter) Insert(v interface{}) { 80 | //bm不存在时直接结束 81 | if bf == nil { 82 | return 83 | } 84 | //开始插入 85 | h := bf.hash(v) 86 | if h/64+1 > uint32(len(bf.bits)) { 87 | //当前冗余量小于num位,需要扩增 88 | var tmp []uint64 89 | //通过冗余扩增减少扩增次数 90 | if h/64+1 < uint32(len(bf.bits)+1024) { 91 | //入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64 92 | tmp = make([]uint64, len(bf.bits)+1024) 93 | } else { 94 | //直接增加到可以容纳第num位的位置 95 | tmp = make([]uint64, h/64+1) 96 | } 97 | //将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的 98 | copy(tmp, bf.bits) 99 | bf.bits = tmp 100 | } 101 | //将第num位设为1即实现插入 102 | bf.bits[h/64] ^= 1 << (h % 64) 103 | } 104 | 105 | //@title Check 106 | //@description 107 | // 以bloomFilter布隆过滤器容器做接收者 108 | // 将待查找的值做哈希计算得到哈希值h 109 | // 检验第h位在位图中是否存在 110 | // 当h大于当前所能存储的位范围时,直接返回false 111 | // 否则判断第h为是否为1,为1返回true,否则返回false 112 | // 利用布隆过滤器做判断存在误差,即返回true可能也不存在,但返回false则必然不存在 113 | //@receiver bf *bloomFilter 接收者bloomFilter指针 114 | //@param v interface{} 待查找的值 115 | //@return b bool 待查找的值可能存在于布隆过滤器中吗? 116 | func (bf *bloomFilter) Check(v interface{}) (b bool) { 117 | //bf不存在时直接返回false并结束 118 | if bf == nil { 119 | return false 120 | } 121 | h := bf.hash(v) 122 | //h超出范围,直接返回false并结束 123 | if h/64+1 > uint32(len(bf.bits)) { 124 | return false 125 | } 126 | //判断第num是否为1,为1返回true,否则为false 127 | if bf.bits[h/64]&(1<<(h%64)) > 0 { 128 | return true 129 | } 130 | return false 131 | } 132 | 133 | //@title Clear 134 | //@description 135 | // 以bloomFilter布隆过滤器容器做接收者 136 | // 清空整个布隆过滤器 137 | //@receiver bf *bloomFilter 接收者bloomFilter指针 138 | //@param nil 139 | //@return nums []uint 所有在位图中存在的元素的下标集合 140 | func (bf *bloomFilter) Clear() { 141 | if bf == nil { 142 | return 143 | } 144 | bf.bits = make([]uint64, 0, 0) 145 | } 146 | -------------------------------------------------------------------------------- /data_structure/bsTree/bsTree.go: -------------------------------------------------------------------------------- 1 | package bsTree 2 | 3 | //@Title bsTree 4 | //@Description 5 | // 二叉搜索树-Binary Search Tree 6 | // 以二叉树的形式实现 7 | // 二叉树实例保存根节点和比较器以及保存的数量 8 | // 可以在创建时设置节点是否可重复 9 | // 若节点可重复则增加节点中的数值,否则对节点存储元素进行覆盖 10 | // 二叉搜索树不进行平衡 11 | // 增加互斥锁实现并发控制 12 | 13 | import ( 14 | "github.com/hlccd/goSTL/utils/comparator" 15 | "github.com/hlccd/goSTL/utils/iterator" 16 | "sync" 17 | ) 18 | 19 | //bsTree二叉搜索树结构体 20 | //该实例存储二叉树的根节点 21 | //同时保存该二叉树已经存储了多少个元素 22 | //二叉树中排序使用的比较器在创建时传入,若不传入则在插入首个节点时从默认比较器中寻找 23 | //创建时传入是否允许该二叉树出现重复值,如果不允许则进行覆盖,允许则对节点数目增加即可 24 | type BsTree struct { 25 | root *node //根节点指针 26 | size uint64 //存储元素数量 27 | cmp comparator.Comparator //比较器 28 | isMulti bool //是否允许重复 29 | mutex sync.Mutex //并发控制锁 30 | } 31 | 32 | //bsTree二叉搜索树容器接口 33 | //存放了bsTree二叉搜索树可使用的函数 34 | //对应函数介绍见下方 35 | type bsTreeer interface { 36 | Iterator() (i *Iterator.Iterator) //返回包含该二叉树的所有元素,重复则返回多个 37 | Size() (num uint64) //返回该二叉树中保存的元素个数 38 | Clear() //清空该二叉树 39 | Empty() (b bool) //判断该二叉树是否为空 40 | Insert(e interface{}) //向二叉树中插入元素e 41 | Erase(e interface{}) //从二叉树中删除元素e 42 | Count(e interface{}) (num uint64) //从二叉树中寻找元素e并返回其个数 43 | } 44 | 45 | //@title New 46 | //@description 47 | // 新建一个bsTree二叉搜索树容器并返回 48 | // 初始根节点为nil 49 | // 传入该二叉树是否为可重复属性,如果为true则保存重复值,否则对原有相等元素进行覆盖 50 | // 若有传入的比较器,则将传入的第一个比较器设为该二叉树的比较器 51 | //@receiver nil 52 | //@param isMulti bool 该二叉树是否保存重复值? 53 | //@param Cmp ...comparator.Comparator bsTree比较器集 54 | //@return bs *BsTree 新建的bsTree指针 55 | func New(isMulti bool, Cmp ...comparator.Comparator) (bs *BsTree) { 56 | //判断是否有传入比较器,若有则设为该二叉树默认比较器 57 | var cmp comparator.Comparator 58 | if len(Cmp) == 0 { 59 | cmp = nil 60 | } else { 61 | cmp = Cmp[0] 62 | } 63 | return &BsTree{ 64 | root: nil, 65 | size: 0, 66 | cmp: cmp, 67 | isMulti: isMulti, 68 | mutex: sync.Mutex{}, 69 | } 70 | } 71 | 72 | //@title Iterator 73 | //@description 74 | // 以bsTree二叉搜索树做接收者 75 | // 将该二叉树中所有保存的元素将从根节点开始以中缀序列的形式放入迭代器中 76 | // 若允许重复存储则对于重复元素进行多次放入 77 | //@receiver bt *BsTree 接受者bsTree的指针 78 | //@param nil 79 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 80 | func (bs *BsTree) Iterator() (i *Iterator.Iterator) { 81 | if bs == nil { 82 | //创建一个允许插入重复值的二叉搜 83 | bs = New(true) 84 | } 85 | bs.mutex.Lock() 86 | es := bs.root.inOrder() 87 | i = Iterator.New(&es) 88 | bs.mutex.Unlock() 89 | return i 90 | } 91 | 92 | //@title Size 93 | //@description 94 | // 以bsTree二叉搜索树做接收者 95 | // 返回该容器当前含有元素的数量 96 | // 如果容器为nil则创建一个并返回其承载的元素个数 97 | //@receiver bt *BsTree 接受者bsTree的指针 98 | //@param nil 99 | //@return num uint64 容器中实际使用元素所占空间大小 100 | func (bs *BsTree) Size() (num uint64) { 101 | if bs == nil { 102 | //创建一个允许插入重复值的二叉搜 103 | bs = New(true) 104 | } 105 | return bs.size 106 | } 107 | 108 | //@title Clear 109 | //@description 110 | // 以bsTree二叉搜索树做接收者 111 | // 将该容器中所承载的元素清空 112 | // 将该容器的size置0 113 | //@receiver bt *BsTree 接受者bsTree的指针 114 | //@param nil 115 | //@return nil 116 | func (bs *BsTree) Clear() { 117 | if bs == nil { 118 | //创建一个允许插入重复值的二叉搜 119 | bs = New(true) 120 | } 121 | bs.mutex.Lock() 122 | bs.root = nil 123 | bs.size = 0 124 | bs.mutex.Unlock() 125 | } 126 | 127 | //@title Empty 128 | //@description 129 | // 以bsTree二叉搜索树做接收者 130 | // 判断该二叉搜索树是否含有元素 131 | // 如果含有元素则不为空,返回false 132 | // 如果不含有元素则说明为空,返回true 133 | // 如果容器不存在,返回true 134 | //@receiver bt *BsTree 接受者bsTree的指针 135 | //@param nil 136 | //@return b bool 该容器是空的吗? 137 | func (bs *BsTree) Empty() (b bool) { 138 | if bs == nil { 139 | //创建一个允许插入重复值的二叉搜 140 | bs = New(true) 141 | } 142 | return bs.size == 0 143 | } 144 | 145 | //@title Insert 146 | //@description 147 | // 以bsTree二叉搜索树做接收者 148 | // 向二叉树插入元素e,若不允许重复则对相等元素进行覆盖 149 | // 如果二叉树为空则之间用根节点承载元素e,否则以根节点开始进行查找 150 | // 不做平衡 151 | //@receiver bt *BsTree 接受者bsTree的指针 152 | //@param e interface{} 待插入元素 153 | //@return nil 154 | func (bs *BsTree) Insert(e interface{}) { 155 | if bs == nil { 156 | //创建一个允许插入重复值的二叉搜 157 | bs = New(true) 158 | } 159 | bs.mutex.Lock() 160 | if bs.Empty() { 161 | //二叉树为空,用根节点承载元素e 162 | if bs.cmp == nil { 163 | bs.cmp = comparator.GetCmp(e) 164 | } 165 | if bs.cmp == nil { 166 | bs.mutex.Unlock() 167 | return 168 | } 169 | bs.root = newNode(e) 170 | bs.size++ 171 | bs.mutex.Unlock() 172 | return 173 | } 174 | //二叉树不为空,从根节点开始查找添加元素e 175 | if bs.root.insert(e, bs.isMulti, bs.cmp) { 176 | bs.size++ 177 | } 178 | bs.mutex.Unlock() 179 | } 180 | 181 | //@title Erase 182 | //@description 183 | // 以bsTree二叉搜索树做接收者 184 | // 从搜素二叉树中删除元素e 185 | // 若允许重复记录则对承载元素e的节点中数量记录减一即可 186 | // 若不允许重复记录则删除该节点同时将前缀节点或后继节点更换过来以保证二叉树的不发送断裂 187 | // 如果该二叉树仅持有一个元素且根节点等价于待删除元素,则将二叉树根节点置为nil 188 | //@receiver bt *BsTree 接受者bsTree的指针 189 | //@param e interface{} 待删除元素 190 | //@return nil 191 | func (bs *BsTree) Erase(e interface{}) { 192 | if bs == nil { 193 | //创建一个允许插入重复值的二叉搜 194 | bs = New(true) 195 | } 196 | if bs.size == 0 { 197 | return 198 | } 199 | bs.mutex.Lock() 200 | if bs.size == 1 && bs.cmp(bs.root.value, e) == 0 { 201 | //二叉树仅持有一个元素且根节点等价于待删除元素,将二叉树根节点置为nil 202 | bs.root = nil 203 | bs.size = 0 204 | bs.mutex.Unlock() 205 | return 206 | } 207 | //从根节点开始删除元素e 208 | //如果删除成功则将size-1 209 | if bs.root.delete(e, bs.isMulti, bs.cmp) { 210 | bs.size-- 211 | } 212 | bs.mutex.Unlock() 213 | } 214 | 215 | //@title Count 216 | //@description 217 | // 以bsTree二叉搜索树做接收者 218 | // 从搜素二叉树中查找元素e的个数 219 | // 如果找到则返回该二叉树中和元素e相同元素的个数 220 | // 如果不允许重复则最多返回1 221 | // 如果未找到则返回0 222 | //@receiver bt *BsTree 接受者bsTree的指针 223 | //@param e interface{} 待查找元素 224 | //@return num uint64 待查找元素在二叉树中存储的个数 225 | func (bs *BsTree) Count(e interface{}) (num uint64) { 226 | if bs == nil { 227 | //二叉树不存在,返回0 228 | return 0 229 | } 230 | if bs.Empty() { 231 | //二叉树为空,返回0 232 | return 0 233 | } 234 | bs.mutex.Lock() 235 | //从根节点开始查找并返回查找结果 236 | num = bs.root.search(e, bs.isMulti, bs.cmp) 237 | bs.mutex.Unlock() 238 | return num 239 | } 240 | -------------------------------------------------------------------------------- /data_structure/bsTree/node.go: -------------------------------------------------------------------------------- 1 | package bsTree 2 | 3 | //@Title bsTree 4 | //@Description 5 | // 二叉搜索树的节点 6 | // 可通过节点实现二叉搜索树的添加删除 7 | // 也可通过节点返回整个二叉搜索树的所有元素 8 | 9 | import "github.com/hlccd/goSTL/utils/comparator" 10 | 11 | //node树节点结构体 12 | //该节点是二叉搜索树的树节点 13 | //若该二叉搜索树允许重复则对节点num+1即可,否则对value进行覆盖 14 | //二叉搜索树节点不做平衡 15 | type node struct { 16 | value interface{} //节点中存储的元素 17 | num uint64 //该元素数量 18 | left *node //左节点指针 19 | right *node //右节点指针 20 | } 21 | 22 | //@title newNode 23 | //@description 24 | // 新建一个二叉搜索树节点并返回 25 | // 将传入的元素e作为该节点的承载元素 26 | // 该节点的num默认为1,左右子节点设为nil 27 | //@receiver nil 28 | //@param e interface{} 承载元素e 29 | //@return n *node 新建的二叉搜索树节点的指针 30 | func newNode(e interface{}) (n *node) { 31 | return &node{ 32 | value: e, 33 | num: 1, 34 | left: nil, 35 | right: nil, 36 | } 37 | } 38 | 39 | //@title inOrder 40 | //@description 41 | // 以node二叉搜索树节点做接收者 42 | // 以中缀序列返回节点集合 43 | // 若允许重复存储则对于重复元素进行多次放入 44 | //@receiver n *node 接受者node的指针 45 | //@param nil 46 | //@return es []interface{} 以该节点为起点的中缀序列 47 | func (n *node) inOrder() (es []interface{}) { 48 | if n == nil { 49 | return es 50 | } 51 | if n.left != nil { 52 | es = append(es, n.left.inOrder()...) 53 | } 54 | for i := uint64(0); i < n.num; i++ { 55 | es = append(es, n.value) 56 | } 57 | if n.right != nil { 58 | es = append(es, n.right.inOrder()...) 59 | } 60 | return es 61 | } 62 | 63 | //@title insert 64 | //@description 65 | // 以node二叉搜索树节点做接收者 66 | // 从n节点中插入元素e 67 | // 如果n节点中承载元素与e不同则根据大小从左右子树插入该元素 68 | // 如果n节点与该元素相等,且允许重复值,则将num+1否则对value进行覆盖 69 | // 插入成功返回true,插入失败或不允许重复插入返回false 70 | //@receiver n *node 接受者node的指针 71 | //@param e interface{} 待插入元素 72 | //@param isMulti bool 是否允许重复? 73 | //@param cmp comparator.Comparator 判断大小的比较器 74 | //@return b bool 是否插入成功? 75 | func (n *node) insert(e interface{}, isMulti bool, cmp comparator.Comparator) (b bool) { 76 | if n == nil { 77 | return false 78 | } 79 | //n中承载元素小于e,从右子树继续插入 80 | if cmp(n.value, e) < 0 { 81 | if n.right == nil { 82 | //右子树为nil,直接插入右子树即可 83 | n.right = newNode(e) 84 | return true 85 | } else { 86 | return n.right.insert(e, isMulti, cmp) 87 | } 88 | } 89 | //n中承载元素大于e,从左子树继续插入 90 | if cmp(n.value, e) > 0 { 91 | if n.left == nil { 92 | //左子树为nil,直接插入左子树即可 93 | n.left = newNode(e) 94 | return true 95 | } else { 96 | return n.left.insert(e, isMulti, cmp) 97 | } 98 | } 99 | //n中承载元素等于e 100 | if isMulti { 101 | //允许重复 102 | n.num++ 103 | return true 104 | } 105 | //不允许重复,直接进行覆盖 106 | n.value = e 107 | return false 108 | } 109 | 110 | //@title delete 111 | //@description 112 | // 以node二叉搜索树节点做接收者 113 | // 从n节点中删除元素e 114 | // 如果n节点中承载元素与e不同则根据大小从左右子树删除该元素 115 | // 如果n节点与该元素相等,且允许重复值,则将num-1否则直接删除该元素 116 | // 删除时先寻找该元素的前缀节点,若不存在则寻找其后继节点进行替换 117 | // 替换后删除该节点 118 | //@receiver n *node 接受者node的指针 119 | //@param e interface{} 待删除元素 120 | //@param isMulti bool 是否允许重复? 121 | //@param cmp comparator.Comparator 判断大小的比较器 122 | //@return b bool 是否删除成功? 123 | func (n *node) delete(e interface{}, isMulti bool, cmp comparator.Comparator) (b bool) { 124 | if n == nil { 125 | return false 126 | } 127 | //n中承载元素小于e,从右子树继续删除 128 | if cmp(n.value, e) < 0 { 129 | if n.right == nil { 130 | //右子树为nil,删除终止 131 | return false 132 | } 133 | if cmp(e, n.right.value) == 0 && (!isMulti || n.right.num == 1) { 134 | if n.right.left == nil && n.right.right == nil { 135 | //右子树可直接删除 136 | n.right = nil 137 | return true 138 | } 139 | } 140 | //从右子树继续删除 141 | return n.right.delete(e, isMulti, cmp) 142 | } 143 | //n中承载元素大于e,从左子树继续删除 144 | if cmp(n.value, e) > 0 { 145 | if n.left == nil { 146 | //左子树为nil,删除终止 147 | return false 148 | } 149 | if cmp(e, n.left.value) == 0 && (!isMulti || n.left.num == 1) { 150 | if n.left.left == nil && n.left.right == nil { 151 | //左子树可直接删除 152 | n.left = nil 153 | return true 154 | } 155 | } 156 | //从左子树继续删除 157 | return n.left.delete(e, isMulti, cmp) 158 | } 159 | //n中承载元素等于e 160 | if (*n).num > 1 && isMulti { 161 | //允许重复且个数超过1,则减少num即可 162 | (*n).num-- 163 | return true 164 | } 165 | if n.left == nil && n.right == nil { 166 | //该节点无前缀节点和后继节点,删除即可 167 | *(&n) = nil 168 | return true 169 | } 170 | if n.left != nil { 171 | //该节点有前缀节点,找到前缀节点进行交换并删除即可 172 | ln := n.left 173 | if ln.right == nil { 174 | n.value = ln.value 175 | n.num = ln.num 176 | n.left = ln.left 177 | } else { 178 | for ln.right.right != nil { 179 | ln = ln.right 180 | } 181 | n.value = ln.right.value 182 | n.num = ln.right.num 183 | ln.right = ln.right.left 184 | } 185 | } else if (*n).right != nil { 186 | //该节点有后继节点,找到后继节点进行交换并删除即可 187 | tn := n.right 188 | if tn.left == nil { 189 | n.value = tn.value 190 | n.num = tn.num 191 | n.right = tn.right 192 | } else { 193 | for tn.left.left != nil { 194 | tn = tn.left 195 | } 196 | n.value = tn.left.value 197 | n.num = tn.left.num 198 | tn.left = tn.left.right 199 | } 200 | return true 201 | } 202 | return true 203 | } 204 | 205 | //@title search 206 | //@description 207 | // 以node二叉搜索树节点做接收者 208 | // 从n节点中查找元素e并返回存储的个数 209 | // 如果n节点中承载元素与e不同则根据大小从左右子树查找该元素 210 | // 如果n节点与该元素相等,则直接返回其个数 211 | //@receiver n *node 接受者node的指针 212 | //@param e interface{} 待查找元素 213 | //@param isMulti bool 是否允许重复? 214 | //@param cmp comparator.Comparator 判断大小的比较器 215 | //@return num uint64 待查找元素在二叉树中存储的数量 216 | func (n *node) search(e interface{}, isMulti bool, cmp comparator.Comparator) (num uint64) { 217 | if n == nil { 218 | return 0 219 | } 220 | //n中承载元素小于e,从右子树继续查找并返回结果 221 | if cmp(n.value, e) < 0 { 222 | return n.right.search(e, isMulti, cmp) 223 | } 224 | //n中承载元素大于e,从左子树继续查找并返回结果 225 | if cmp(n.value, e) > 0 { 226 | return n.left.search(e, isMulti, cmp) 227 | } 228 | //n中承载元素等于e,直接返回结果 229 | return n.num 230 | } 231 | -------------------------------------------------------------------------------- /data_structure/cbTree/cbTree.go: -------------------------------------------------------------------------------- 1 | package cbTree 2 | 3 | //@Title cbTree 4 | //@Description 5 | // 完全二叉树-Complete Binary Tree 6 | // 以完全二叉树的形式实现的堆 7 | // 通过比较器判断传入元素的大小 8 | // 将最小的元素放在堆顶 9 | // 该结构只保留整个树的根节点,其他节点通过根节点进行查找获得 10 | //@author hlccd 2021-07-14 11 | //@update hlccd 2021-08-01 增加互斥锁实现并发控制 12 | import ( 13 | "github.com/hlccd/goSTL/utils/comparator" 14 | "github.com/hlccd/goSTL/utils/iterator" 15 | "sync" 16 | ) 17 | 18 | //cbTree完全二叉树树结构体 19 | //该实例存储二叉树的根节点 20 | //同时保存该二叉树已经存储了多少个元素 21 | //二叉树中排序使用的比较器在创建时传入,若不传入则在插入首个节点时从默认比较器中寻找 22 | type cbTree struct { 23 | root *node //根节点指针 24 | size int //存储元素数量 25 | cmp comparator.Comparator //比较器 26 | mutex sync.Mutex //并发控制锁 27 | } 28 | 29 | //cbTree二叉搜索树容器接口 30 | //存放了cbTree二叉搜索树可使用的函数 31 | //对应函数介绍见下方 32 | type cbTreer interface { 33 | Iterator() (i *iterator.Iterator) //返回包含该二叉树的所有元素 34 | Size() (num int) //返回该二叉树中保存的元素个数 35 | Clear() //清空该二叉树 36 | Empty() (b bool) //判断该二叉树是否为空 37 | Push(e interface{}) //向二叉树中插入元素e 38 | Pop() //从二叉树中弹出顶部元素 39 | Top() (e interface{}) //返回该二叉树的顶部元素 40 | } 41 | 42 | //@title New 43 | //@description 44 | // 新建一个cbTree完全二叉树容器并返回 45 | // 初始根节点为nil 46 | // 若有传入的比较器,则将传入的第一个比较器设为该二叉树的比较器 47 | //@author hlccd 2021-07-14 48 | //@receiver nil 49 | //@param Cmp ...comparator.Comparator cbTree比较器集 50 | //@return cb *cbTree 新建的cbTree指针 51 | func New(Cmp ...comparator.Comparator) (cb *cbTree) { 52 | //判断是否有传入比较器,若有则设为该二叉树默认比较器 53 | var cmp comparator.Comparator 54 | if len(Cmp) > 0 { 55 | cmp = Cmp[0] 56 | } 57 | return &cbTree{ 58 | root: nil, 59 | size: 0, 60 | cmp: cmp, 61 | mutex: sync.Mutex{}, 62 | } 63 | } 64 | 65 | //@title Iterator 66 | //@description 67 | // 以cbTree完全二叉树做接收者 68 | // 将该二叉树中所有保存的元素将从根节点开始以前缀序列的形式放入迭代器中 69 | //@auth hlccd 2021-07-14 70 | //@receiver cb *cbTree 接受者cbTree的指针 71 | //@param nil 72 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 73 | func (cb *cbTree) Iterator() (i *iterator.Iterator) { 74 | if cb == nil { 75 | return iterator.New(make([]interface{}, 0, 0)) 76 | } 77 | cb.mutex.Lock() 78 | i = iterator.New(cb.root.frontOrder()) 79 | cb.mutex.Unlock() 80 | return i 81 | } 82 | 83 | //@title Size 84 | //@description 85 | // 以cbTree完全二叉树做接收者 86 | // 返回该容器当前含有元素的数量 87 | // 如果容器为nil返回-1 88 | //@auth hlccd 2021-07-14 89 | //@receiver cb *cbTree 接受者cbTree的指针 90 | //@param nil 91 | //@return num int 容器中实际使用元素所占空间大小 92 | func (cb *cbTree) Size() (num int) { 93 | if cb == nil { 94 | return -1 95 | } 96 | return cb.size 97 | } 98 | 99 | //@title Clear 100 | //@description 101 | // 以cbTree完全二叉树做接收者 102 | // 将该容器中所承载的元素清空 103 | // 将该容器的size置0 104 | //@auth hlccd 2021-07-14 105 | //@receiver cb *cbTree 接受者cbTree的指针 106 | //@param nil 107 | //@return nil 108 | func (cb *cbTree) Clear() { 109 | if cb == nil { 110 | return 111 | } 112 | cb.mutex.Lock() 113 | cb.root = nil 114 | cb.size = 0 115 | cb.mutex.Unlock() 116 | } 117 | 118 | //@title Empty 119 | //@description 120 | // 以cbTree完全二叉树做接收者 121 | // 判断该完全二叉树树是否含有元素 122 | // 如果含有元素则不为空,返回false 123 | // 如果不含有元素则说明为空,返回true 124 | // 如果容器不存在,返回true 125 | //@auth hlccd 2021-07-14 126 | //@receiver cb *cbTree 接受者cbTree的指针 127 | //@param nil 128 | //@return b bool 该容器是空的吗? 129 | func (cb *cbTree) Empty() (b bool) { 130 | if cb == nil { 131 | return true 132 | } 133 | if cb.size > 0 { 134 | return false 135 | } 136 | return true 137 | } 138 | 139 | //@title Push 140 | //@description 141 | // 以cbTree完全二叉树做接收者 142 | // 向二叉树插入元素e,将其放入完全二叉树的最后一个位置,随后进行元素上升 143 | // 如果二叉树本身为空,则直接将根节点设为插入节点元素即可 144 | //@auth hlccd 2021-07-14 145 | //@receiver cb *cbTree 接受者cbTree的指针 146 | //@param e interface{} 待插入元素 147 | //@return nil 148 | func (cb *cbTree) Push(e interface{}) { 149 | if cb == nil { 150 | return 151 | } 152 | cb.mutex.Lock() 153 | if cb.Empty() { 154 | if cb.cmp == nil { 155 | cb.cmp = comparator.GetCmp(e) 156 | } 157 | if cb.cmp == nil { 158 | cb.mutex.Unlock() 159 | return 160 | } 161 | cb.root = newNode(nil, e) 162 | cb.size++ 163 | } else { 164 | cb.size++ 165 | cb.root.insert(cb.size, e, cb.cmp) 166 | } 167 | cb.mutex.Unlock() 168 | } 169 | 170 | //@title Pop 171 | //@description 172 | // 以cbTree完全二叉树做接收者 173 | // 从完全二叉树中删除顶部元素e 174 | // 将该顶部元素于最后一个元素进行交换 175 | // 随后删除最后一个元素 176 | // 再将顶部元素进行下沉处理即可 177 | //@auth hlccd 2021-07-14 178 | //@receiver cb *cbTree 接受者cbTree的指针 179 | //@param nil 180 | //@return nil 181 | func (cb *cbTree) Pop() { 182 | if cb == nil { 183 | return 184 | } 185 | if cb.Empty() { 186 | return 187 | } 188 | cb.mutex.Lock() 189 | if cb.size == 1 { 190 | //该二叉树仅剩根节点,直接删除即可 191 | cb.root = nil 192 | } else { 193 | //该二叉树删除根节点后还有其他节点可生为跟节点 194 | cb.root.delete(cb.size, cb.cmp) 195 | } 196 | cb.size-- 197 | cb.mutex.Unlock() 198 | } 199 | 200 | //@title Top 201 | //@description 202 | // 以cbTree完全二叉树做接收者 203 | // 返回该完全二叉树的顶部元素 204 | // 当该完全二叉树不存在或根节点不存在时返回nil 205 | //@auth hlccd 2021-07-14 206 | //@receiver cb *cbTree 接受者cbTree的指针 207 | //@param nil 208 | //@return e interface{} 该完全二叉树的顶部元素 209 | func (cb *cbTree) Top() (e interface{}) { 210 | if cb == nil { 211 | return nil 212 | } 213 | cb.mutex.Lock() 214 | e = cb.root.value 215 | cb.mutex.Unlock() 216 | return e 217 | } 218 | -------------------------------------------------------------------------------- /data_structure/cbTree/node.go: -------------------------------------------------------------------------------- 1 | package cbTree 2 | 3 | //@Title cbTree 4 | //@Description 5 | // 完全二叉树的节点 6 | // 可通过节点实现完全二叉树的节点上升与下沉 7 | // 也可查找待插入的最后一个节点的父节点,即该待插入节点将放入该父节点的左右子节点中 8 | //@author hlccd 2021-07-14 9 | import "github.com/hlccd/goSTL/utils/comparator" 10 | 11 | //node树节点结构体 12 | //该节点是完全二叉树的树节点 13 | //该节点除了保存承载元素外,还将保存父节点、左右子节点的指针 14 | type node struct { 15 | value interface{} //节点中存储的元素 16 | parent *node //父节点指针 17 | left *node //左节点指针 18 | right *node //右节点指针 19 | } 20 | 21 | //@title newNode 22 | //@description 23 | // 新建一个完全二叉树节点并返回 24 | // 将传入的元素e作为该节点的承载元素 25 | // 将传入的parent节点作为其父节点,左右节点设为nil 26 | //@auth hlccd 2021-07-14 27 | //@receiver nil 28 | //@param parent *node 新建节点的父节点指针 29 | //@param e interface{} 承载元素e 30 | //@return n *node 新建的完全二叉树节点的指针 31 | func newNode(parent *node, e interface{}) (n *node) { 32 | return &node{ 33 | value: e, 34 | parent: parent, 35 | left: nil, 36 | right: nil, 37 | } 38 | } 39 | 40 | //@title frontOrder 41 | //@description 42 | // 以node节点做接收者 43 | // 以前缀序列返回节点集合 44 | //@auth hlccd 2021-07-14 45 | //@receiver n *node 接受者node的指针 46 | //@param nil 47 | //@return es []interface{} 以该节点为起点的前缀序列 48 | func (n *node) frontOrder() (es []interface{}) { 49 | if n == nil { 50 | return es 51 | } 52 | es = append(es, n.value) 53 | if n.left != nil { 54 | es = append(es, n.left.frontOrder()...) 55 | } 56 | if n.right != nil { 57 | es = append(es, n.right.frontOrder()...) 58 | } 59 | return es 60 | } 61 | 62 | //@title lastParent 63 | //@description 64 | // 以node节点做接收者 65 | // 根据传入数值通过转化为二进制的方式模拟查找最后一个父节点 66 | // 由于查找父节点的路径等同于转化为二进制后除开首位的中间值,故该方案是可行的 67 | //@auth hlccd 2021-07-14 68 | //@receiver n *node 接受者node的指针 69 | //@param nil 70 | //@return ans *node 查找到的最后一个父节点 71 | func (n *node) lastParent(num int) (ans *node) { 72 | if num > 3 { 73 | //去掉末尾的二进制值 74 | arr := make([]int, 0, 32) 75 | ans = n 76 | for num > 0 { 77 | //转化为二进制 78 | arr = append(arr, num%2) 79 | num /= 2 80 | } 81 | //去掉首位的二进制值 82 | for i := len(arr) - 2; i >= 1; i-- { 83 | if arr[i] == 1 { 84 | ans = ans.right 85 | } else { 86 | ans = ans.left 87 | } 88 | } 89 | return ans 90 | } 91 | return n 92 | } 93 | 94 | //@title insert 95 | //@description 96 | // 以node节点做接收者 97 | // 从该节点插入元素e,并根据传入的num寻找最后一个父节点用于插入最后一位值 98 | // 随后对插入值进行上升处理 99 | //@auth hlccd 2021-07-14 100 | //@receiver n *node 接受者node的指针 101 | //@param num int 插入后的元素数量,用于寻找最后一个父节点 102 | //@param e interface{} 待插入元素 103 | //@param cmp comparator.Comparator 比较器,在节点上升时使用 104 | //@return nil 105 | func (n *node) insert(num int, e interface{}, cmp comparator.Comparator) { 106 | if n == nil { 107 | return 108 | } 109 | //寻找最后一个父节点 110 | n = n.lastParent(num) 111 | //将元素插入最后一个节点 112 | if num%2 == 0 { 113 | n.left = newNode(n, e) 114 | n = n.left 115 | } else { 116 | n.right = newNode(n, e) 117 | n = n.right 118 | } 119 | //对插入的节点进行上升 120 | n.up(cmp) 121 | } 122 | 123 | //@title up 124 | //@description 125 | // 以node节点做接收者 126 | // 对该节点进行上升 127 | // 当该节点存在且父节点存在时,若该节点小于夫节点 128 | // 则在交换两个节点值后继续上升即可 129 | //@auth hlccd 2021-07-14 130 | //@receiver n *node 接受者node的指针 131 | //@param cmp comparator.Comparator 比较器,在节点上升时使用 132 | //@return nil 133 | func (n *node) up(cmp comparator.Comparator) { 134 | if n == nil { 135 | return 136 | } 137 | if n.parent == nil { 138 | return 139 | } 140 | //该节点和父节点都存在 141 | if cmp(n.parent.value, n.value) > 0 { 142 | //该节点值小于父节点值,交换两节点值,继续上升 143 | n.parent.value, n.value = n.value, n.parent.value 144 | n.parent.up(cmp) 145 | } 146 | } 147 | 148 | //@title delete 149 | //@description 150 | // 以node节点做接收者 151 | // 从删除该,并根据传入的num寻找最后一个父节点用于替换删除 152 | // 随后对替换后的值进行下沉处理即可 153 | //@auth hlccd 2021-07-14 154 | //@receiver n *node 接受者node的指针 155 | //@param num int 删除前的元素数量,用于寻找最后一个父节点 156 | //@param cmp comparator.Comparator 比较器,在节点下沉时使用 157 | //@return nil 158 | func (n *node) delete(num int, cmp comparator.Comparator) { 159 | if n == nil { 160 | return 161 | } 162 | //寻找最后一个父节点 163 | ln := n.lastParent(num) 164 | if num%2 == 0 { 165 | n.value = ln.left.value 166 | ln.left = nil 167 | } else { 168 | n.value = ln.right.value 169 | ln.right = nil 170 | } 171 | //对交换后的节点进行下沉 172 | n.down(cmp) 173 | } 174 | 175 | //@title down 176 | //@description 177 | // 以node节点做接收者 178 | // 对该节点进行下沉 179 | // 当该存在右节点且小于自身元素时,与右节点进行交换并继续下沉 180 | // 否则当该存在左节点且小于自身元素时,与左节点进行交换并继续下沉 181 | // 当左右节点都不存在或都大于自身时下沉停止 182 | //@auth hlccd 2021-07-14 183 | //@receiver n *node 接受者node的指针 184 | //@param cmp comparator.Comparator 比较器,在节点下沉时使用 185 | //@return nil 186 | func (n *node) down(cmp comparator.Comparator) { 187 | if n == nil { 188 | return 189 | } 190 | if n.right != nil && cmp(n.left.value, n.right.value) >= 0 { 191 | n.right.value, n.value = n.value, n.right.value 192 | n.right.down(cmp) 193 | return 194 | } 195 | if n.left != nil && cmp(n.value, n.left.value) >= 0 { 196 | n.left.value, n.value = n.value, n.left.value 197 | n.left.down(cmp) 198 | return 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /data_structure/deque/deque.go: -------------------------------------------------------------------------------- 1 | package deque 2 | 3 | //@Title deque 4 | //@Description 5 | // deque双队列容器包 6 | // 区别于queue的动态数组实现方式,deque采取将数组和链表相结合的方案 7 | // 该容器既可以在首部增删元素,也可以在尾部增删元素 8 | // deque在扩容和缩容时,都是固定增加2^10的空间,同时这一部分空间形成链表节点,并串成链表去保存 9 | // 可接纳不同类型的元素 10 | // 通过并发控制锁保证了在高并发过程中的数据一致性 11 | 12 | import ( 13 | "github.com/hlccd/goSTL/utils/iterator" 14 | "sync" 15 | ) 16 | 17 | //deque双向队列结构体 18 | //包含链表的头尾节点指针 19 | //当删除节点时通过头尾节点指针进入链表进行删除 20 | //当一个节点全部被删除后则释放该节点,同时首尾节点做相应调整 21 | //当添加节点时若未占满节点空间时移动下标并做覆盖即可 22 | //当添加节点时空间已使用完毕时,根据添加位置新建一个新节点补充上去 23 | type Deque struct { 24 | first *node //链表首节点指针 25 | last *node //链表尾节点指针 26 | size uint64 //当前存储的元素个数 27 | mutex sync.Mutex //并发控制锁 28 | } 29 | 30 | //deque双向队列容器接口 31 | //存放了deque容器可使用的函数 32 | //对应函数介绍见下方 33 | 34 | type dequer interface { 35 | Iterator() (i *Iterator.Iterator) //返回包含双向队列中所有元素的迭代器 36 | Size() (size uint64) //返回该双向队列中元素的使用空间大小 37 | Clear() //清空该双向队列 38 | Empty() (b bool) //判断该双向队列是否为空 39 | PushFront(e interface{}) //将元素e添加到该双向队列的首部 40 | PushBack(e interface{}) //将元素e添加到该双向队列的尾部 41 | PopFront() (e interface{}) //将该双向队列首元素弹出 42 | PopBack() (e interface{}) //将该双向队列首元素弹出 43 | Front() (e interface{}) //获取该双向队列首部元素 44 | Back() (e interface{}) //获取该双向队列尾部元素 45 | } 46 | 47 | //@title New 48 | //@description 49 | // 新建一个deque双向队列容器并返回 50 | // 初始deque双向队列的链表首尾节点为nil 51 | // 初始size为0 52 | //@receiver nil 53 | //@param nil 54 | //@return d *Deque 新建的deque指针 55 | func New() *Deque { 56 | return &Deque{ 57 | first: nil, 58 | last: nil, 59 | size: 0, 60 | mutex: sync.Mutex{}, 61 | } 62 | } 63 | 64 | //@title Iterator 65 | //@description 66 | // 以deque双向队列容器做接收者 67 | // 将deque双向队列容器中所承载的元素放入迭代器中 68 | // 节点的冗余空间不释放 69 | //@receiver d *Deque 接收者的deque指针 70 | //@param nil 71 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 72 | func (d *Deque) Iterator() (i *Iterator.Iterator) { 73 | if d == nil { 74 | d = New() 75 | } 76 | tmp := make([]interface{}, 0, d.size) 77 | //遍历链表的所有节点,将其中承载的元素全部复制出来 78 | for m := d.first; m != nil; m = m.nextNode() { 79 | tmp = append(tmp, m.value()...) 80 | } 81 | return Iterator.New(&tmp) 82 | } 83 | 84 | //@title Size 85 | //@description 86 | // 以deque双向队列容器做接收者 87 | // 返回该容器当前含有元素的数量 88 | // 该长度并非实际占用空间数量 89 | // 若容器为空则返回0 90 | //@receiver d *Deque 接收者的deque指针 91 | //@param nil 92 | //@return size uint64 容器中实际使用元素所占空间大小 93 | func (d *Deque) Size() (size uint64) { 94 | if d == nil { 95 | d = New() 96 | } 97 | return d.size 98 | } 99 | 100 | //@title Clear 101 | //@description 102 | // 以deque双向队列容器做接收者 103 | // 将该容器中所承载的元素清空 104 | // 将该容器的首尾指针均置nil,将size重置为0 105 | //@receiver d *Deque 接收者的deque指针 106 | //@param nil 107 | //@return nil 108 | func (d *Deque) Clear() { 109 | if d == nil { 110 | d = New() 111 | return 112 | } 113 | d.mutex.Lock() 114 | d.first = nil 115 | d.last = nil 116 | d.size = 0 117 | d.mutex.Unlock() 118 | } 119 | 120 | //@title Empty 121 | //@description 122 | // 以deque双向队列容器做接收者 123 | // 判断该deque双向队列容器是否含有元素 124 | // 如果含有元素则不为空,返回false 125 | // 如果不含有元素则说明为空,返回true 126 | // 如果容器不存在,返回true 127 | // 该判断过程通过size进行判断,为0则为true,否则为false 128 | //@receiver d *Deque 接收者的deque指针 129 | //@param nil 130 | //@return b bool 该容器是空的吗? 131 | func (d *Deque) Empty() (b bool) { 132 | if d == nil { 133 | d = New() 134 | } 135 | return d.Size() == 0 136 | } 137 | 138 | //@title PushFront 139 | //@description 140 | // 以deque双向队列向量容器做接收者 141 | // 在容器首部插入元素 142 | // 通过链表首节点进行添加 143 | //@receiver d *Deque 接收者的deque指针 144 | //@param e interface{} 待插入元素 145 | //@return nil 146 | func (d *Deque) PushFront(e interface{}) { 147 | if d == nil { 148 | d = New() 149 | } 150 | d.mutex.Lock() 151 | d.size++ 152 | //通过首节点进行添加 153 | if d.first == nil { 154 | d.first = createFirst() 155 | d.last = d.first 156 | } 157 | d.first = d.first.pushFront(e) 158 | d.mutex.Unlock() 159 | } 160 | 161 | //@title PushBack 162 | //@description 163 | // 以deque双向队列向量容器做接收者 164 | // 在容器尾部插入元素 165 | // 通过链表尾节点进行添加 166 | //@receiver d *Deque 接收者的deque指针 167 | //@param e interface{} 待插入元素 168 | //@return nil 169 | func (d *Deque) PushBack(e interface{}) { 170 | if d == nil { 171 | d = New() 172 | } 173 | d.mutex.Lock() 174 | d.size++ 175 | //通过尾节点进行添加 176 | if d.last == nil { 177 | d.last = createLast() 178 | d.first = d.last 179 | } 180 | d.last = d.last.pushBack(e) 181 | d.mutex.Unlock() 182 | } 183 | 184 | //@title PopFront 185 | //@description 186 | // 以deque双向队列容器做接收者 187 | // 利用首节点进行弹出元素,可能存在首节点全部释放要进行首节点后移的情况 188 | // 当元素全部删除后,释放全部空间,将首尾节点都设为nil 189 | //@receiver d *Deque 接收者的deque指针 190 | //@param nil 191 | //@return e interface{} 首元素 192 | func (d *Deque) PopFront() (e interface{}) { 193 | if d == nil { 194 | d = New() 195 | } 196 | if d.size == 0 { 197 | return nil 198 | } 199 | d.mutex.Lock() 200 | //利用首节点删除首元素 201 | //返回新的首节点 202 | e = d.first.front() 203 | d.first = d.first.popFront() 204 | d.size-- 205 | if d.size == 0 { 206 | //全部删除完成,释放空间,并将首尾节点设为nil 207 | d.first = nil 208 | d.last = nil 209 | } 210 | d.mutex.Unlock() 211 | return e 212 | } 213 | 214 | //@title PopBack 215 | //@description 216 | // 以deque双向队列容器做接收者 217 | // 利用尾节点进行弹出元素,可能存在尾节点全部释放要进行尾节点前移的情况 218 | // 当元素全部删除后,释放全部空间,将首尾节点都设为nil 219 | //@receiver d *Deque 接收者的deque指针 220 | //@param nil 221 | //@return e interface{} 尾元素 222 | func (d *Deque) PopBack() (e interface{}) { 223 | if d == nil { 224 | d = New() 225 | } 226 | if d.size == 0 { 227 | return nil 228 | } 229 | d.mutex.Lock() 230 | //利用尾节点删除首元素 231 | //返回新的尾节点 232 | d.last = d.last.popBack() 233 | e = d.last.back() 234 | d.size-- 235 | if d.size == 0 { 236 | //全部删除完成,释放空间,并将首尾节点设为nil 237 | d.first = nil 238 | d.last = nil 239 | } 240 | d.mutex.Unlock() 241 | return e 242 | } 243 | 244 | //@title Front 245 | //@description 246 | // 以deque双向队列容器做接收者 247 | // 返回该容器的第一个元素,利用首节点进行寻找 248 | // 若该容器当前为空,则返回nil 249 | //@receiver d *Deque 接收者的deque指针 250 | //@param nil 251 | //@return e interface{} 容器的第一个元素 252 | func (d *Deque) Front() (e interface{}) { 253 | if d == nil { 254 | d = New() 255 | } 256 | return d.first.front() 257 | } 258 | 259 | //@title Back 260 | //@description 261 | // 以deque双向队列容器做接收者 262 | // 返回该容器的最后一个元素,利用尾节点进行寻找 263 | // 若该容器当前为空,则返回nil 264 | //@receiver d *Deque 接收者的deque指针 265 | //@param nil 266 | //@return e interface{} 容器的最后一个元素 267 | func (d *Deque) Back() (e interface{}) { 268 | if d == nil { 269 | d = New() 270 | } 271 | return d.last.back() 272 | } 273 | -------------------------------------------------------------------------------- /data_structure/deque/deque_test.go: -------------------------------------------------------------------------------- 1 | package deque 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | "testing" 7 | ) 8 | 9 | func TestDeque_Front(t *testing.T) { 10 | type fields struct { 11 | first *node 12 | last *node 13 | size uint64 14 | mutex sync.Mutex 15 | } 16 | tests := []struct { 17 | name string 18 | fields fields 19 | wantE interface{} 20 | }{ 21 | // TODO: Add test cases. 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | d := &Deque{ 26 | first: tt.fields.first, 27 | last: tt.fields.last, 28 | size: tt.fields.size, 29 | mutex: tt.fields.mutex, 30 | } 31 | if gotE := d.Front(); !reflect.DeepEqual(gotE, tt.wantE) { 32 | t.Errorf("Front() = %v, want %v", gotE, tt.wantE) 33 | } 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /data_structure/deque/node.go: -------------------------------------------------------------------------------- 1 | package deque 2 | 3 | //@Title deque 4 | //@Description 5 | // deque双队列容器包 6 | // 该部分包含了deque双向队列中链表节点 7 | // 链表的增删都通过节点的增删完成 8 | // 节点空间全部使用或全部废弃后将进行节点增删 9 | // 增删之后会返回对应的首尾节点以辅助deque容器仍持有首尾节点 10 | // 为保证效率问题,设定了一定的冗余量,即每个节点设定2^10的空间以存放元素 11 | 12 | //deque双向队列中链表的node节点结构体 13 | //包含一个2^10空间的固定数组用以承载元素 14 | //使用begin和end两个下标用以表示新增的元素的下标,由于begin可能出现-1所以不选用uint16 15 | //pre和next是该节点的前后两个节点 16 | //用以保证链表整体是相连的 17 | type node struct { 18 | data [1024]interface{} //用于承载元素的股东数组 19 | begin int16 //该结点在前方添加结点的下标 20 | end int16 //该结点在后方添加结点的下标 21 | pre *node //该结点的前一个结点 22 | next *node //该节点的后一个结点 23 | } 24 | 25 | //deque双向队列容器接口 26 | //存放了node结点容器可使用的函数 27 | //对应函数介绍见下方 28 | type noder interface { 29 | nextNode() (m *node) //返回下一个结点 30 | preNode() (m *node) //返回上一个结点 31 | value() (es []interface{}) //返回该结点所承载的所有元素 32 | pushFront(e interface{}) (first *node) //在该结点头部添加一个元素,并返回新首结点 33 | pushBack(e interface{}) (last *node) //在该结点尾部添加一个元素,并返回新尾结点 34 | popFront() (first *node) //弹出首元素并返回首结点 35 | popBack() (last *node) //弹出尾元素并返回尾结点 36 | front() (e interface{}) //返回首元素 37 | back() (e interface{}) //返回尾元素 38 | } 39 | 40 | //@title createFirst 41 | //@description 42 | // 新建一个冗余在前方的首结点并返回其指针 43 | // 初始首结点的begin为1023,end为1024 44 | // 该结点的前后结点均置为nil 45 | //@receiver nil 46 | //@param nil 47 | //@return n *node 新建的node指针 48 | func createFirst() (n *node) { 49 | return &node{ 50 | data: [1024]interface{}{}, 51 | begin: 1023, 52 | end: 1024, 53 | pre: nil, 54 | next: nil, 55 | } 56 | } 57 | 58 | //@title createLast 59 | //@description 60 | // 新建一个冗余在后方的尾结点并返回其指针 61 | // 初始首结点的begin为-1,end为0 62 | // 该结点的前后结点均置为nil 63 | //@receiver nil 64 | //@param nil 65 | //@return n *node 新建的node指针 66 | func createLast() (n *node) { 67 | return &node{ 68 | data: [1024]interface{}{}, 69 | begin: -1, 70 | end: 0, 71 | pre: nil, 72 | next: nil, 73 | } 74 | } 75 | 76 | //@title nextNode 77 | //@description 78 | // 以node结点做接收者 79 | // 返回该结点的后一个结点 80 | // 如果n为nil则返回nil 81 | //@receiver n *node 接收者的node指针 82 | //@param nil 83 | //@return m *node n结点的下一个结点m的指针 84 | func (n *node) nextNode() (m *node) { 85 | if n == nil { 86 | return nil 87 | } 88 | return n.next 89 | } 90 | 91 | //@title preNode 92 | //@description 93 | // 以node结点做接收者 94 | // 返回该结点的前一个结点 95 | // 如果n为nil则返回nil 96 | //@receiver n *node 接收者的node指针 97 | //@param nil 98 | //@return m *node n结点的上一个结点m的指针 99 | func (n *node) preNode() (m *node) { 100 | if n == nil { 101 | return nil 102 | } 103 | return n.pre 104 | } 105 | 106 | //@title value 107 | //@description 108 | // 以node结点做接收者 109 | // 返回该结点所承载的所有元素 110 | // 根据其begin和end来获取其元素 111 | // 当该结点为nil时返回[]而非nil 112 | //@receiver n *node 接收者的node指针 113 | //@param nil 114 | //@return es []interface{} 该结点所承载的所有元素 115 | func (n *node) value() (es []interface{}) { 116 | es = make([]interface{}, 0, 0) 117 | if n == nil { 118 | return es 119 | } 120 | if n.begin > n.end { 121 | return es 122 | } 123 | es = n.data[n.begin+1 : n.end] 124 | return es 125 | } 126 | 127 | //@title pushFront 128 | //@description 129 | // 以node结点做接收者 130 | // 向该节点前方添加元素e 131 | // 当该结点空间已经使用完毕后,新建一个结点并将新结点设为首结点 132 | // 将插入元素放入新结点并返回新结点作为新的首结点 133 | // 否则插入当前结点并返回当前结点,首结点不变 134 | //@receiver n *node 接收者的node指针 135 | //@param e interface{} 待插入元素 136 | //@return first *node 首节点指针 137 | func (n *node) pushFront(e interface{}) (first *node) { 138 | if n == nil { 139 | return n 140 | } 141 | if n.begin >= 0 { 142 | //该结点仍有空间可用于承载元素 143 | n.data[n.begin] = e 144 | n.begin-- 145 | return n 146 | } 147 | //该结点无空间承载,创建新的首结点用于存放 148 | m := createFirst() 149 | m.data[m.begin] = e 150 | m.next = n 151 | n.pre = m 152 | m.begin-- 153 | return m 154 | } 155 | 156 | //@title pushBack 157 | //@description 158 | // 以node结点做接收者 159 | // 向该节点后方添加元素e 160 | // 当该结点空间已经使用完毕后,新建一个结点并将新结点设为尾结点 161 | // 将插入元素放入新结点并返回新结点作为新的尾结点 162 | // 否则插入当前结点并返回当前结点,尾结点不变 163 | //@receiver n *node 接收者的node指针 164 | //@param e interface{} 待插入元素 165 | //@return last *node 尾节点指针 166 | func (n *node) pushBack(e interface{}) (last *node) { 167 | if n == nil { 168 | return n 169 | } 170 | if n.end < int16(len(n.data)) { 171 | //该结点仍有空间可用于承载元素 172 | n.data[n.end] = e 173 | n.end++ 174 | return n 175 | } 176 | //该结点无空间承载,创建新的尾结点用于存放 177 | m := createLast() 178 | m.data[m.end] = e 179 | m.pre = n 180 | n.next = m 181 | m.end++ 182 | return m 183 | } 184 | 185 | //@title popFront 186 | //@description 187 | // 以node结点做接收者 188 | // 利用首节点进行弹出元素,可能存在首节点全部释放要进行首节点后移的情况 189 | // 当发生首结点后移后将会返回新首结点,否则返回当前结点 190 | //@receiver n *node 接收者的node指针 191 | //@param nil 192 | //@return first *node 首节点指针 193 | func (n *node) popFront() (first *node) { 194 | if n == nil { 195 | return nil 196 | } 197 | if n.begin < int16(len(n.data))-2 { 198 | //该结点仍有承载元素 199 | n.begin++ 200 | n.data[n.begin] = nil 201 | return n 202 | } 203 | if n.next != nil { 204 | //清除该结点下一节点的前结点指针 205 | n.next.pre = nil 206 | } 207 | return n.next 208 | } 209 | 210 | //@title popBack 211 | //@description 212 | // 以node结点做接收者 213 | // 利用尾节点进行弹出元素,可能存在尾节点全部释放要进行尾节点前移的情况 214 | // 当发生尾结点前移后将会返回新尾结点,否则返回当前结点 215 | //@receiver n *node 接收者的node指针 216 | //@param nil 217 | //@return last *node 尾节点指针 218 | func (n *node) popBack() (last *node) { 219 | if n == nil { 220 | return nil 221 | } 222 | if n.end > 1 { 223 | //该结点仍有承载元素 224 | n.end-- 225 | n.data[n.end] = nil 226 | return n 227 | } 228 | if n.pre != nil { 229 | //清除该结点上一节点的后结点指针 230 | n.pre.next = nil 231 | } 232 | return n.pre 233 | } 234 | 235 | //@title front 236 | //@description 237 | // 以node结点做接收者 238 | // 返回该结点的第一个元素,利用首节点和begin进行查找 239 | // 若该结点为nil,则返回nil 240 | //@receiver n *node 接收者的node指针 241 | //@param nil 242 | //@return e interface{} 该结点承载的的第一个元素 243 | func (n *node) front() (e interface{}) { 244 | if n == nil { 245 | return nil 246 | } 247 | return n.data[n.begin+1] 248 | } 249 | 250 | //@title back 251 | //@description 252 | // 以node结点做接收者 253 | // 返回该结点的最后一个元素,利用尾节点和end进行查找 254 | // 若该结点为nil,则返回nil 255 | //@receiver n *node 接收者的node指针 256 | //@param nil 257 | //@return e interface{} 该结点承载的的最后一个元素 258 | func (n *node) back() (e interface{}) { 259 | if n == nil { 260 | return nil 261 | } 262 | return n.data[n.end-1] 263 | } 264 | -------------------------------------------------------------------------------- /data_structure/heap/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | //@Title heap 4 | //@Description 5 | // 采用完全二叉树-Complete Binary Tree实现堆 6 | // 通过比较器判断传入元素的大小 7 | // 将最小的元素放在堆顶 8 | // 该结构只保留整个树的根节点,其他节点通过根节点进行查找获得 9 | // 增加互斥锁实现并发控制 10 | import ( 11 | "github.com/hlccd/goSTL/utils/comparator" 12 | "github.com/hlccd/goSTL/utils/iterator" 13 | "sync" 14 | ) 15 | 16 | //cbTree完全二叉树树结构体 17 | //该实例存储二叉树的根节点 18 | //同时保存该二叉树已经存储了多少个元素 19 | //二叉树中排序使用的比较器在创建时传入,若不传入则在插入首个节点时从默认比较器中寻找 20 | type cbTree struct { 21 | root *node //根节点指针 22 | size uint64 //存储元素数量 23 | cmp comparator.Comparator //比较器 24 | mutex sync.Mutex //并发控制锁 25 | } 26 | 27 | //cbTree二叉搜索树容器接口 28 | //存放了cbTree二叉搜索树可使用的函数 29 | //对应函数介绍见下方 30 | type cbTreer interface { 31 | Iterator() (i *Iterator.Iterator) //返回包含该二叉树的所有元素 32 | Size() (num uint64) //返回该二叉树中保存的元素个数 33 | Clear() //清空该二叉树 34 | Empty() (b bool) //判断该二叉树是否为空 35 | Push(e interface{}) //向二叉树中插入元素e 36 | Pop() //从二叉树中弹出顶部元素 37 | Top() (e interface{}) //返回该二叉树的顶部元素 38 | } 39 | 40 | //@title New 41 | //@description 42 | // 新建一个cbTree完全二叉树容器并返回 43 | // 初始根节点为nil 44 | // 若有传入的比较器,则将传入的第一个比较器设为该二叉树的比较器 45 | //@author hlccd 2021-07-14 46 | //@receiver nil 47 | //@param Cmp ...comparator.Comparator cbTree比较器集 48 | //@return cb *cbTree 新建的cbTree指针 49 | func New(Cmp ...comparator.Comparator) (cb *cbTree) { 50 | //判断是否有传入比较器,若有则设为该二叉树默认比较器 51 | var cmp comparator.Comparator 52 | if len(Cmp) > 0 { 53 | cmp = Cmp[0] 54 | } 55 | return &cbTree{ 56 | root: nil, 57 | size: 0, 58 | cmp: cmp, 59 | mutex: sync.Mutex{}, 60 | } 61 | } 62 | 63 | //@title Iterator 64 | //@description 65 | // 以cbTree完全二叉树做接收者 66 | // 将该二叉树中所有保存的元素将从根节点开始以前缀序列的形式放入迭代器中 67 | //@receiver cb *cbTree 接受者cbTree的指针 68 | //@param nil 69 | //@return i *Iterator.Iterator 新建的Iterator迭代器指针 70 | func (cb *cbTree) Iterator() (i *Iterator.Iterator) { 71 | if cb == nil { 72 | cb = New() 73 | } 74 | cb.mutex.Lock() 75 | es := cb.root.frontOrder() 76 | i = Iterator.New(&es) 77 | cb.mutex.Unlock() 78 | return i 79 | } 80 | 81 | //@title Size 82 | //@description 83 | // 以cbTree完全二叉树做接收者 84 | // 返回该容器当前含有元素的数量 85 | // 如果容器为nil返回0 86 | //@receiver cb *cbTree 接受者cbTree的指针 87 | //@param nil 88 | //@return num uint64 容器中实际使用元素所占空间大小 89 | func (cb *cbTree) Size() (num uint64) { 90 | if cb == nil { 91 | cb = New() 92 | } 93 | return cb.size 94 | } 95 | 96 | //@title Clear 97 | //@description 98 | // 以cbTree完全二叉树做接收者 99 | // 将该容器中所承载的元素清空 100 | // 将该容器的size置0 101 | //@receiver cb *cbTree 接受者cbTree的指针 102 | //@param nil 103 | //@return nil 104 | func (cb *cbTree) Clear() { 105 | if cb == nil { 106 | cb = New() 107 | } 108 | cb.mutex.Lock() 109 | cb.root = nil 110 | cb.size = 0 111 | cb.mutex.Unlock() 112 | } 113 | 114 | //@title Empty 115 | //@description 116 | // 以cbTree完全二叉树做接收者 117 | // 判断该完全二叉树树是否含有元素 118 | // 如果含有元素则不为空,返回false 119 | // 如果不含有元素则说明为空,返回true 120 | // 如果容器不存在,返回true 121 | //@receiver cb *cbTree 接受者cbTree的指针 122 | //@param nil 123 | //@return b bool 该容器是空的吗? 124 | func (cb *cbTree) Empty() (b bool) { 125 | if cb == nil { 126 | cb = New() 127 | } 128 | return cb.size == 0 129 | } 130 | 131 | //@title Push 132 | //@description 133 | // 以cbTree完全二叉树做接收者 134 | // 向二叉树插入元素e,将其放入完全二叉树的最后一个位置,随后进行元素上升 135 | // 如果二叉树本身为空,则直接将根节点设为插入节点元素即可 136 | //@receiver cb *cbTree 接受者cbTree的指针 137 | //@param e interface{} 待插入元素 138 | //@return nil 139 | func (cb *cbTree) Push(e interface{}) { 140 | if cb == nil { 141 | cb=New() 142 | } 143 | cb.mutex.Lock() 144 | if cb.Empty() { 145 | if cb.cmp == nil { 146 | cb.cmp = comparator.GetCmp(e) 147 | } 148 | if cb.cmp == nil { 149 | cb.mutex.Unlock() 150 | return 151 | } 152 | cb.root = newNode(nil, e) 153 | cb.size++ 154 | } else { 155 | cb.size++ 156 | cb.root.insert(cb.size, e, cb.cmp) 157 | } 158 | cb.mutex.Unlock() 159 | } 160 | 161 | //@title Pop 162 | //@description 163 | // 以cbTree完全二叉树做接收者 164 | // 从完全二叉树中删除顶部元素e 165 | // 将该顶部元素于最后一个元素进行交换 166 | // 随后删除最后一个元素 167 | // 再将顶部元素进行下沉处理即可 168 | //@receiver cb *cbTree 接受者cbTree的指针 169 | //@param nil 170 | //@return nil 171 | func (cb *cbTree) Pop() { 172 | if cb == nil { 173 | cb=New() 174 | } 175 | if cb.Empty() { 176 | return 177 | } 178 | cb.mutex.Lock() 179 | if cb.size == 1 { 180 | //该二叉树仅剩根节点,直接删除即可 181 | cb.root = nil 182 | } else { 183 | //该二叉树删除根节点后还有其他节点可生为跟节点 184 | cb.root.delete(cb.size, cb.cmp) 185 | } 186 | cb.size-- 187 | cb.mutex.Unlock() 188 | } 189 | 190 | //@title Top 191 | //@description 192 | // 以cbTree完全二叉树做接收者 193 | // 返回该完全二叉树的顶部元素 194 | // 当该完全二叉树不存在或根节点不存在时返回nil 195 | //@receiver cb *cbTree 接受者cbTree的指针 196 | //@param nil 197 | //@return e interface{} 该完全二叉树的顶部元素 198 | func (cb *cbTree) Top() (e interface{}) { 199 | if cb == nil { 200 | cb=New() 201 | } 202 | cb.mutex.Lock() 203 | e = cb.root.value 204 | cb.mutex.Unlock() 205 | return e 206 | } 207 | -------------------------------------------------------------------------------- /data_structure/heap/node.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | //@Title cbTree 4 | //@Description 5 | // 完全二叉树的节点 6 | // 可通过节点实现完全二叉树的节点上升与下沉 7 | // 也可查找待插入的最后一个节点的父节点,即该待插入节点将放入该父节点的左右子节点中 8 | 9 | import "github.com/hlccd/goSTL/utils/comparator" 10 | 11 | //node树节点结构体 12 | //该节点是完全二叉树的树节点 13 | //该节点除了保存承载元素外,还将保存父节点、左右子节点的指针 14 | type node struct { 15 | value interface{} //节点中存储的元素 16 | parent *node //父节点指针 17 | left *node //左节点指针 18 | right *node //右节点指针 19 | } 20 | 21 | //@title newNode 22 | //@description 23 | // 新建一个完全二叉树节点并返回 24 | // 将传入的元素e作为该节点的承载元素 25 | // 将传入的parent节点作为其父节点,左右节点设为nil 26 | //@receiver nil 27 | //@param parent *node 新建节点的父节点指针 28 | //@param e interface{} 承载元素e 29 | //@return n *node 新建的完全二叉树节点的指针 30 | func newNode(parent *node, e interface{}) (n *node) { 31 | return &node{ 32 | value: e, 33 | parent: parent, 34 | left: nil, 35 | right: nil, 36 | } 37 | } 38 | 39 | //@title frontOrder 40 | //@description 41 | // 以node节点做接收者 42 | // 以前缀序列返回节点集合 43 | //@receiver n *node 接受者node的指针 44 | //@param nil 45 | //@return es []interface{} 以该节点为起点的前缀序列 46 | func (n *node) frontOrder() (es []interface{}) { 47 | if n == nil { 48 | return es 49 | } 50 | es = append(es, n.value) 51 | if n.left != nil { 52 | es = append(es, n.left.frontOrder()...) 53 | } 54 | if n.right != nil { 55 | es = append(es, n.right.frontOrder()...) 56 | } 57 | return es 58 | } 59 | 60 | //@title lastParent 61 | //@description 62 | // 以node节点做接收者 63 | // 根据传入数值通过转化为二进制的方式模拟查找最后一个父节点 64 | // 由于查找父节点的路径等同于转化为二进制后除开首位的中间值,故该方案是可行的 65 | //@receiver n *node 接受者node的指针 66 | //@param num uint64 对应位置转化为二进制的值,用于查找 67 | //@return ans *node 查找到的最后一个父节点 68 | func (n *node) lastParent(num uint64) (ans *node) { 69 | if num > 3 { 70 | //去掉末尾的二进制值 71 | arr := make([]byte, 0, 64) 72 | ans = n 73 | for num > 0 { 74 | //转化为二进制 75 | arr = append(arr, byte(num%2)) 76 | num /= 2 77 | } 78 | //去掉首位的二进制值 79 | for i := len(arr) - 2; i >= 1; i-- { 80 | if arr[i] == 1 { 81 | ans = ans.right 82 | } else { 83 | ans = ans.left 84 | } 85 | } 86 | return ans 87 | } 88 | return n 89 | } 90 | 91 | //@title insert 92 | //@description 93 | // 以node节点做接收者 94 | // 从该节点插入元素e,并根据传入的num寻找最后一个父节点用于插入最后一位值 95 | // 随后对插入值进行上升处理 96 | //@receiver n *node 接受者node的指针 97 | //@param num uint64 插入后的元素数量,用于寻找最后一个父节点 98 | //@param e interface{} 待插入元素 99 | //@param cmp comparator.Comparator 比较器,在节点上升时使用 100 | //@return nil 101 | func (n *node) insert(num uint64, e interface{}, cmp comparator.Comparator) { 102 | if n == nil { 103 | return 104 | } 105 | //寻找最后一个父节点 106 | n = n.lastParent(num) 107 | //将元素插入最后一个节点 108 | if num%2 == 0 { 109 | n.left = newNode(n, e) 110 | n = n.left 111 | } else { 112 | n.right = newNode(n, e) 113 | n = n.right 114 | } 115 | //对插入的节点进行上升 116 | n.up(cmp) 117 | } 118 | 119 | //@title up 120 | //@description 121 | // 以node节点做接收者 122 | // 对该节点进行上升 123 | // 当该节点存在且父节点存在时,若该节点小于夫节点 124 | // 则在交换两个节点值后继续上升即可 125 | //@receiver n *node 接受者node的指针 126 | //@param cmp comparator.Comparator 比较器,在节点上升时使用 127 | //@return nil 128 | func (n *node) up(cmp comparator.Comparator) { 129 | if n == nil { 130 | return 131 | } 132 | if n.parent == nil { 133 | return 134 | } 135 | //该节点和父节点都存在 136 | if cmp(n.parent.value, n.value) > 0 { 137 | //该节点值小于父节点值,交换两节点值,继续上升 138 | n.parent.value, n.value = n.value, n.parent.value 139 | n.parent.up(cmp) 140 | } 141 | } 142 | 143 | //@title delete 144 | //@description 145 | // 以node节点做接收者 146 | // 从删除该,并根据传入的num寻找最后一个父节点用于替换删除 147 | // 随后对替换后的值进行下沉处理即可 148 | //@receiver n *node 接受者node的指针 149 | //@param num uint64 删除前的元素数量,用于寻找最后一个父节点 150 | //@param cmp comparator.Comparator 比较器,在节点下沉时使用 151 | //@return nil 152 | func (n *node) delete(num uint64, cmp comparator.Comparator) { 153 | if n == nil { 154 | return 155 | } 156 | //寻找最后一个父节点 157 | ln := n.lastParent(num) 158 | if num%2 == 0 { 159 | n.value = ln.left.value 160 | ln.left = nil 161 | } else { 162 | n.value = ln.right.value 163 | ln.right = nil 164 | } 165 | //对交换后的节点进行下沉 166 | n.down(cmp) 167 | } 168 | 169 | //@title down 170 | //@description 171 | // 以node节点做接收者 172 | // 对该节点进行下沉 173 | // 当该存在右节点且小于自身元素时,与右节点进行交换并继续下沉 174 | // 否则当该存在左节点且小于自身元素时,与左节点进行交换并继续下沉 175 | // 当左右节点都不存在或都大于自身时下沉停止 176 | //@receiver n *node 接受者node的指针 177 | //@param cmp comparator.Comparator 比较器,在节点下沉时使用 178 | //@return nil 179 | func (n *node) down(cmp comparator.Comparator) { 180 | if n == nil { 181 | return 182 | } 183 | if n.right != nil && cmp(n.left.value, n.right.value) >= 0 { 184 | n.right.value, n.value = n.value, n.right.value 185 | n.right.down(cmp) 186 | return 187 | } 188 | if n.left != nil && cmp(n.value, n.left.value) >= 0 { 189 | n.left.value, n.value = n.value, n.left.value 190 | n.left.down(cmp) 191 | return 192 | } 193 | } -------------------------------------------------------------------------------- /data_structure/list/node.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | //@Title list 4 | //@Description 5 | // list链表容器包 6 | // 该部分包含了链表的节点 7 | // 链表的增删都通过节点的增删完成 8 | // 结点间可插入其前后节点,并同时将两结点建立连接 9 | // 增删之后会返回对应的首尾节点以辅助list容器仍持有首尾节点 10 | // 为保证效率问题,设定了一定的冗余量,即每个节点设定2^10的空间以存放元素 11 | 12 | //链表的node节点结构体 13 | //pre和next是该节点的前后两个节点的指针 14 | //用以保证链表整体是相连的 15 | type node struct { 16 | data interface{} //结点所承载的元素 17 | pre *node //前结点指针 18 | next *node //后结点指针 19 | } 20 | 21 | //node结点容器接口 22 | //存放了node容器可使用的函数 23 | //对应函数介绍见下方 24 | 25 | type noder interface { 26 | preNode() (m *node) //返回前结点指针 27 | nextNode() (m *node) //返回后结点指针 28 | insertPre(pre *node) //在该结点前插入结点并建立连接 29 | insertNext(next *node) //在该结点后插入结点并建立连接 30 | erase() //删除该结点,并使该结点前后两结点建立连接 31 | value() (e interface{}) //返回该结点所承载的元素 32 | setValue(e interface{}) //修改该结点承载元素为e 33 | } 34 | 35 | //@title newNode 36 | //@description 37 | // 新建一个结点并返回其指针 38 | // 初始首结点的前后结点指针都为nil 39 | //@receiver nil 40 | //@param nil 41 | //@return n *node 新建的node指针 42 | func newNode(e interface{}) (n *node) { 43 | return &node{ 44 | data: e, 45 | pre: nil, 46 | next: nil, 47 | } 48 | } 49 | 50 | //@title preNode 51 | //@description 52 | // 以node结点做接收者 53 | // 返回该结点的前结点 54 | //@receiver n *node 接收者的node指针 55 | //@param nil 56 | //@return pre *node 该结点的前结点指针 57 | func (n *node) preNode() (pre *node) { 58 | if n == nil { 59 | return 60 | } 61 | return n.pre 62 | } 63 | 64 | //@title nextNode 65 | //@description 66 | // 以node结点做接收者 67 | // 返回该结点的后结点 68 | //@receiver n *node 接收者的node指针 69 | //@param nil 70 | //@return next *node 该结点的后结点指针 71 | func (n *node) nextNode() (next *node) { 72 | if n == nil { 73 | return 74 | } 75 | return n.next 76 | } 77 | 78 | //@title insertPre 79 | //@description 80 | // 以node结点做接收者 81 | // 对该结点插入前结点 82 | // 并建立前结点和该结点之间的连接 83 | //@receiver n *node 接收者的node指针 84 | //@param pre *node 该结点的前结点指针 85 | //@return nil 86 | func (n *node) insertPre(pre *node) { 87 | if n == nil || pre == nil { 88 | return 89 | } 90 | pre.next = n 91 | pre.pre = n.pre 92 | if n.pre != nil { 93 | n.pre.next = pre 94 | } 95 | n.pre = pre 96 | } 97 | 98 | //@title insertNext 99 | //@description 100 | // 以node结点做接收者 101 | // 对该结点插入后结点 102 | // 并建立后结点和该结点之间的连接 103 | //@receiver n *node 接收者的node指针 104 | //@param next *node 该结点的后结点指针 105 | //@return nil 106 | func (n *node) insertNext(next *node) { 107 | if n == nil || next == nil { 108 | return 109 | } 110 | next.pre = n 111 | next.next = n.next 112 | if n.next != nil { 113 | n.next.pre = next 114 | } 115 | n.next = next 116 | } 117 | 118 | //@title erase 119 | //@description 120 | // 以node结点做接收者 121 | // 销毁该结点 122 | // 同时建立该节点前后节点之间的连接 123 | //@receiver n *node 接收者的node指针 124 | //@param nil 125 | //@return nil 126 | func (n *node) erase() { 127 | if n == nil { 128 | return 129 | } 130 | if n.pre == nil && n.next == nil { 131 | return 132 | } else if n.pre == nil { 133 | n.next.pre = nil 134 | } else if n.next == nil { 135 | n.pre.next = nil 136 | } else { 137 | n.pre.next = n.next 138 | n.next.pre = n.pre 139 | } 140 | n = nil 141 | } 142 | 143 | //@title value 144 | //@description 145 | // 以node结点做接收者 146 | // 返回该结点所要承载的元素 147 | //@receiver n *node 接收者的node指针 148 | //@param nil 149 | //@return e interface{} 该节点所承载的元素e 150 | func (n *node) value() (e interface{}) { 151 | if n == nil { 152 | return nil 153 | } 154 | return n.data 155 | } 156 | 157 | //@title setValue 158 | //@description 159 | // 以node结点做接收者 160 | // 对该结点设置其承载的元素 161 | //@receiver n *node 接收者的node指针 162 | //@param e interface{} 该节点所要承载的元素e 163 | //@return nil 164 | func (n *node) setValue(e interface{}) { 165 | if n == nil { 166 | return 167 | } 168 | n.data = e 169 | } 170 | -------------------------------------------------------------------------------- /data_structure/lru/lru.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | //@Title lru 4 | //@Description 5 | // LRU-Least Recently Used,最近最少使用链结构 6 | // 相对于仅考虑时间因素的FIFO和仅考虑访问频率的LFU,LRU算法可以认为是相对平衡的一种淘汰算法 7 | // LRU认为,如果数据最近被访问过,那么将来被访问的概率也会更高 8 | // LRU 算法的实现非常简单,维护一个队列 9 | // 如果某条记录被访问了,则移动到队尾,那么队首则是最近最少访问的数据,淘汰该条记录即可。 10 | // 可接纳不同类型的元素 11 | // 使用并发控制锁保证线程安全 12 | // 使用map加快索引速率 13 | // 不做定时淘汰 14 | import ( 15 | "container/list" 16 | "sync" 17 | ) 18 | 19 | //LRU链结构体 20 | //包含了该LRU结构中能承载的byte数上限和当前已承载的数量 21 | //以链表的形式存储承载元素 22 | //使用map建立key索引和链表结点之间的联系,链表结点中存放其value 23 | //onRemove函数是用于在删除时的执行,可用于将数据持久化 24 | //使用并发控制所保证线程安全 25 | type LRU struct { 26 | maxBytes int64 //所能承载的最大byte数量 27 | nowBytes int64 //当前承载的byte数 28 | ll *list.List //用于存储的链表 29 | cache map[string]*list.Element //链表元素与key的映射表 30 | onRemove func(key string, value Value) //删除元素时的执行函数 31 | mutex sync.Mutex //并发控制锁 32 | } 33 | 34 | //索引结构体 35 | //保存了一个待存储值的索引和值 36 | //value值为一个interface{},需要实现它的长度函数即Len() 37 | type indexes struct { 38 | key string //索引 39 | value Value //存储值 40 | } 41 | 42 | //存储值的函数 43 | type Value interface { 44 | Len() int //用于计算该存储值所占用的长度 45 | } 46 | 47 | //lru链容器接口 48 | //存放了lru容器可使用的函数 49 | //对应函数介绍见下方 50 | type lruer interface { 51 | Size() (num int64) //返回lru中当前存放的byte数 52 | Cap() (num int64) //返回lru能存放的byte树的最大值 53 | Clear() //清空lru,将其中存储的所有元素都释放 54 | Empty() (b bool) //判断该lru中是否存储了元素 55 | Insert(key string, value Value) //向lru中插入以key为索引的value 56 | Erase(key string) //从lru中删除以key为索引的值 57 | Get(key string) (value Value, ok bool) //从lru中获取以key为索引的value和是否获取成功? 58 | } 59 | 60 | //@title New 61 | //@description 62 | // 新建一个lru链容器并返回 63 | // 初始的lru不存储元素 64 | // 需要传入其最大存储的bytes和删除后的执行函数 65 | //@receiver nil 66 | //@param maxBytes int64 该LRU能存储的最大byte数 67 | //@param onRemove func(string, Value) 删除元素后的执行函数,一般建议做持久化 68 | //@return l *LRU 新建的LRU指针 69 | func New(maxBytes int64, onRemove func(string, Value)) (l *LRU) { 70 | return &LRU{ 71 | maxBytes: maxBytes, 72 | nowBytes: 0, 73 | ll: list.New(), 74 | cache: make(map[string]*list.Element), 75 | onRemove: onRemove, 76 | mutex: sync.Mutex{}, 77 | } 78 | } 79 | 80 | //@title Size 81 | //@description 82 | // 以LRU链容器做接收者 83 | // 返回该LRU链当前所存储的byte数 84 | //@receiver l *LRU 接受者LRU的指针 85 | //@param nil 86 | //@return num uint64 该LRU链当前所存储的byte数 87 | func (l *LRU) Size() (num int64) { 88 | if l == nil { 89 | return 0 90 | } 91 | return l.nowBytes 92 | } 93 | 94 | //@title Cap 95 | //@description 96 | // 以LRU链容器做接收者 97 | // 返回该LRU链能存储的最大byte数 98 | //@receiver l *LRU 接受者LRU的指针 99 | //@param nil 100 | //@return num uint64 该LRU链所能存储的最大byte数 101 | func (l *LRU) Cap() (num int64) { 102 | if l == nil { 103 | return 0 104 | } 105 | return l.maxBytes 106 | } 107 | 108 | //@title Clear 109 | //@description 110 | // 以LRU链容器做接收者 111 | // 将LRU链中的所有承载的元素清除 112 | // 同时将map清空,将当前存储的byte数清零 113 | //@receiver l *LRU 接受者LRU的指针 114 | //@param nil 115 | //@return nil 116 | func (l *LRU) Clear() { 117 | if l == nil { 118 | return 119 | } 120 | l.mutex.Lock() 121 | l.ll = list.New() 122 | l.cache = make(map[string]*list.Element) 123 | l.nowBytes = 0 124 | l.mutex.Unlock() 125 | } 126 | 127 | //@title Empty 128 | //@description 129 | // 以LRU链容器做接收者 130 | // 判断该LRU链中是否存储了元素 131 | // 没存储则返回true,LRU不存在也返回true 132 | // 否则返回false 133 | //@receiver l *LRU 接受者LRU的指针 134 | //@param nil 135 | //@return b bool 该容器是空的吗? 136 | func (l *LRU) Empty() (b bool) { 137 | if l == nil { 138 | return true 139 | } 140 | return l.nowBytes <= 0 141 | } 142 | 143 | //@title Insert 144 | //@description 145 | // 以LRU链容器做接收者 146 | // 向该LRU中插入以key为索引的value 147 | // 若已经存在则将其放到队尾 148 | // 若空间充足且不存在则直接插入队尾 149 | // 若空间不足则淘汰队首元素再将其插入队尾 150 | // 插入完成后将当前已存的byte数增加 151 | //@receiver l *LRU 接受者LRU的指针 152 | //@param key string 待插入结点的索引key 153 | //@param value Value 待插入元素的值value,本质也是个interface{} 154 | //@return nil 155 | func (l *LRU) Insert(key string, value Value) { 156 | l.mutex.Lock() 157 | //利用map从已存的元素中寻找 158 | if ele, ok := l.cache[key]; ok { 159 | //该key已存在,直接替换即可 160 | l.ll.MoveToFront(ele) 161 | kv := ele.Value.(*indexes) 162 | //此处是一个替换,即将cache中的value替换为新的value,同时根据实际存储量修改其当前存储的实际大小 163 | l.nowBytes += int64(value.Len()) - int64(kv.value.Len()) 164 | kv.value = value 165 | } else { 166 | //该key不存在,需要进行插入 167 | ele := l.ll.PushFront(&indexes{key, value}) 168 | l.cache[key] = ele 169 | //此处是一个增加操作,即原本不存在,所以直接插入即可,同时在当前数值范围内增加对应的占用空间 170 | l.nowBytes += int64(len(key)) + int64(value.Len()) 171 | } 172 | //添加完成后根据删除掉尾部一部分数据以保证实际使用空间小于设定的空间上限 173 | for l.maxBytes != 0 && l.maxBytes < l.nowBytes { 174 | //删除队尾元素 175 | //删除后执行创建时传入的删除执行函数 176 | ele := l.ll.Back() 177 | if ele != nil { 178 | l.ll.Remove(ele) 179 | kv := ele.Value.(*indexes) 180 | //删除最末尾的同时将其占用空间减去 181 | delete(l.cache, kv.key) 182 | l.nowBytes -= int64(len(kv.key)) + int64(kv.value.Len()) 183 | if l.onRemove != nil { 184 | //删除后的回调函数,可用于持久化该部分数据 185 | l.onRemove(kv.key, kv.value) 186 | } 187 | } 188 | } 189 | l.mutex.Unlock() 190 | } 191 | 192 | //@title Erase 193 | //@description 194 | // 以LRU链容器做接收者 195 | // 从LRU链中删除以key为索引的value 196 | // 如果不存在则直接结束 197 | // 删除完成后将其占用的byte数减去 198 | // 删除后执行函数回调函数,一般用于持久化 199 | //@receiver l *LRU 接受者LRU的指针 200 | //@param key string 待删除的索引key 201 | //@return nil 202 | //以key为索引删除元素 203 | func (l *LRU) Erase(key string) { 204 | l.mutex.Lock() 205 | if ele, ok := l.cache[key]; ok { 206 | l.ll.Remove(ele) 207 | kv := ele.Value.(*indexes) 208 | //删除的同时将其占用空间减去 209 | delete(l.cache, kv.key) 210 | l.nowBytes -= int64(len(kv.key)) + int64(kv.value.Len()) 211 | if l.onRemove != nil { 212 | //删除后的回调函数,可用于持久化该部分数据 213 | l.onRemove(kv.key, kv.value) 214 | } 215 | } 216 | l.mutex.Unlock() 217 | } 218 | 219 | //@title Get 220 | //@description 221 | // 以LRU链容器做接收者 222 | // 从LRU链中寻找以key为索引的value 223 | // 找到对应的value后将其移到首部,随后返回其value 224 | // 如果没找到以key为索引的value,直接结束即可 225 | //@receiver l *LRU 接受者LRU的指针 226 | //@param key string 待查找的索引key 227 | //@return value Value 以key为索引的value,本质是个interface{} 228 | //@return ok bool 查找成功? 229 | func (l *LRU) Get(key string) (value Value, ok bool) { 230 | l.mutex.Lock() 231 | if ele, ok := l.cache[key]; ok { 232 | //找到了value,将其移到链表首部 233 | l.ll.MoveToFront(ele) 234 | kv := ele.Value.(*indexes) 235 | l.mutex.Unlock() 236 | return kv.value, true 237 | } 238 | l.mutex.Unlock() 239 | return nil, false 240 | } 241 | -------------------------------------------------------------------------------- /data_structure/priority_queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package priority_queue 2 | 3 | //@Title priority_queue 4 | //@Description 5 | // priority_queue优先队列集合容器包 6 | // 以动态数组的形式实现 7 | // 该容器可以增减元素使最值元素处于顶端 8 | // 若使用默认比较器,顶端元素是最小元素 9 | // 该集合只能对于相等元素可以存储多个 10 | // 可接纳不同类型的元素,但为了便于比较,建议使用同一个类型 11 | // 使用互斥锁实现并发控制,以保证在高并发情况下的数据一致性 12 | import ( 13 | "github.com/hlccd/goSTL/utils/comparator" 14 | "sync" 15 | ) 16 | 17 | //priority_queue优先队列集合结构体 18 | //包含动态数组和比较器,同时包含其实际使用长度和实际占用空间容量 19 | //该数据结构可以存储多个相同的元素,并不会产生冲突 20 | //增删节点后会使用比较器保持该动态数组的相对有序性 21 | type Priority_queue struct { 22 | data []interface{} //动态数组 23 | len uint64 //实际使用长度 24 | cap uint64 //实际占用的空间的容量 25 | cmp comparator.Comparator //该优先队列的比较器 26 | mutex sync.Mutex //并发控制锁 27 | } 28 | 29 | //priority_queue优先队列容器接口 30 | //存放了priority_queue容器可使用的函数 31 | //对应函数介绍见下方 32 | type priority_queueer interface { 33 | Size() (num uint64) //返回该容器存储的元素数量 34 | Clear() //清空该容器 35 | Empty() (b bool) //判断该容器是否为空 36 | Push(e interface{}) //将元素e插入该容器 37 | Pop() //弹出顶部元素 38 | Top() (e interface{}) //返回顶部元素 39 | } 40 | 41 | //@title New 42 | //@description 43 | // 新建一个priority_queue优先队列容器并返回 44 | // 初始priority_queue的切片数组为空 45 | // 如果有传入比较器,则将传入的第一个比较器设为可重复集合默认比较器 46 | // 如果不传入比较器,在后续的增删过程中将会去寻找默认比较器 47 | //@receiver nil 48 | //@param Cmp ...comparator.Comparator priority_queue的比较器 49 | //@return pq *Priority_queue 新建的priority_queue指针 50 | func New(cmps ...comparator.Comparator) (pq *Priority_queue) { 51 | var cmp comparator.Comparator 52 | if len(cmps) == 0 { 53 | cmp = nil 54 | } else { 55 | cmp = cmps[0] 56 | } 57 | //比较器为nil时后续的增删将会去寻找默认比较器 58 | return &Priority_queue{ 59 | data: make([]interface{}, 1, 1), 60 | len: 0, 61 | cap: 1, 62 | cmp: cmp, 63 | mutex: sync.Mutex{}, 64 | } 65 | } 66 | 67 | //@title Size 68 | //@description 69 | // 以priority_queue容器做接收者 70 | // 返回该容器当前含有元素的数量 71 | //@receiver pq *Priority_queue 接受者priority_queue的指针 72 | //@param nil 73 | //@return num uint64 容器中存储元素的个数 74 | func (pq *Priority_queue) Size() (num uint64) { 75 | if pq == nil { 76 | pq = New() 77 | } 78 | return pq.len 79 | } 80 | 81 | //@title Clear 82 | //@description 83 | // 以priority_queue容器做接收者 84 | // 将该容器中所承载的元素清空 85 | //@receiver pq *Priority_queue 接受者priority_queue的指针 86 | //@param nil 87 | //@return nil 88 | func (pq *Priority_queue) Clear() { 89 | if pq == nil { 90 | pq = New() 91 | } 92 | pq.mutex.Lock() 93 | //清空已分配的空间 94 | pq.data = make([]interface{}, 1, 1) 95 | pq.len = 0 96 | pq.cap = 1 97 | pq.mutex.Unlock() 98 | } 99 | 100 | //@title Empty 101 | //@description 102 | // 以priority_queue容器做接收者 103 | // 判断该priority_queue容器是否含有元素 104 | // 如果含有元素则不为空,返回false 105 | // 如果不含有元素则说明为空,返回true 106 | // 如果容器不存在,返回true 107 | // 该判断过程通过含有元素个数进行判断 108 | //@receiver pq *Priority_queue 接受者priority_queue的指针 109 | //@param nil 110 | //@return b bool 该容器是空的吗? 111 | func (pq *Priority_queue) Empty() bool { 112 | if pq == nil { 113 | pq = New() 114 | } 115 | return pq.len == 0 116 | } 117 | 118 | //@title Push 119 | //@description 120 | // 以priority_queue容器做接收者 121 | // 在该优先队列中插入元素e,利用比较器和交换使得优先队列保持相对有序状态 122 | // 插入时,首先将该元素放入末尾,然后通过比较其逻辑上的父结点选择是否上移 123 | // 扩容策略同vector,先进行翻倍扩容,在进行固定扩容,界限为2^16 124 | //@receiver pq *Priority_queue 接受者priority_queue的指针 125 | //@param e interface{} 待插入元素 126 | //@return nil 127 | func (pq *Priority_queue) Push(e interface{}) { 128 | if pq == nil { 129 | pq = New() 130 | } 131 | pq.mutex.Lock() 132 | //判断是否存在比较器,不存在则寻找默认比较器,若仍不存在则直接结束 133 | if pq.cmp == nil { 134 | pq.cmp = comparator.GetCmp(e) 135 | } 136 | if pq.cmp == nil { 137 | pq.mutex.Unlock() 138 | return 139 | } 140 | //先判断是否需要扩容,同时使用和vector相同的扩容策略 141 | //即先翻倍扩容再固定扩容,随后在末尾插入元素e 142 | if pq.len < pq.cap { 143 | //还有冗余,直接添加 144 | pq.data[pq.len] = e 145 | } else { 146 | //冗余不足,需要扩容 147 | if pq.cap <= 65536 { 148 | //容量翻倍 149 | if pq.cap == 0 { 150 | pq.cap = 1 151 | } 152 | pq.cap *= 2 153 | } else { 154 | //容量增加2^16 155 | pq.cap += 65536 156 | } 157 | //复制扩容前的元素 158 | tmp := make([]interface{}, pq.cap, pq.cap) 159 | copy(tmp, pq.data) 160 | pq.data = tmp 161 | pq.data[pq.len] = e 162 | } 163 | pq.len++ 164 | //到此时,元素以插入到末尾处,同时插入位的元素的下标为pq.len-1,随后将对该位置的元素进行上升 165 | //即通过比较它逻辑上的父结点进行上升 166 | pq.up(pq.len - 1) 167 | pq.mutex.Unlock() 168 | } 169 | 170 | //@title up 171 | //@description 172 | // 以priority_queue容器做接收者 173 | // 用于递归判断任意子结点和其父结点之间的关系,满足上升条件则递归上升 174 | // 从而保证父节点必然都大于或都小于子节点 175 | //@receiver pq *Priority_queue 接受者priority_queue的指针 176 | //@param p uint64 待上升节点的位置 177 | //@return nil 178 | func (pq *Priority_queue) up(p uint64) { 179 | if p == 0 { 180 | //以及上升到顶部,直接结束即可 181 | return 182 | } 183 | if pq.cmp(pq.data[(p-1)/2], pq.data[p]) > 0 { 184 | //判断该结点和其父结点的关系 185 | //满足给定的比较函数的关系则先交换该结点和父结点的数值,随后继续上升即可 186 | pq.data[p], pq.data[(p-1)/2] = pq.data[(p-1)/2], pq.data[p] 187 | pq.up((p - 1) / 2) 188 | } 189 | } 190 | 191 | //@title Pop 192 | //@description 193 | // 以priority_queue容器做接收者 194 | // 在该优先队列中删除顶部元素,利用比较器和交换使得优先队列保持相对有序状态 195 | // 删除时首先将首结点移到最后一位进行交换,随后删除最后一位即可,然后对首节点进行下降即可 196 | // 缩容时同vector一样,先进行固定缩容在进行折半缩容,界限为2^16 197 | //@receiver pq *Priority_queue 接受者priority_queue的指针 198 | //@param nil 199 | //@return nil 200 | func (pq *Priority_queue) Pop() { 201 | if pq == nil { 202 | pq = New() 203 | } 204 | if pq.Empty() { 205 | return 206 | } 207 | pq.mutex.Lock() 208 | //将最后一位移到首位,随后删除最后一位,即删除了首位,同时判断是否需要缩容 209 | pq.data[0] = pq.data[pq.len-1] 210 | pq.data[pq.len-1]=nil 211 | pq.len-- 212 | //缩容判断,缩容策略同vector,即先固定缩容在折半缩容 213 | if pq.cap-pq.len >= 65536 { 214 | //容量和实际使用差值超过2^16时,容量直接减去2^16 215 | pq.cap -= 65536 216 | tmp := make([]interface{}, pq.cap, pq.cap) 217 | copy(tmp, pq.data) 218 | pq.data = tmp 219 | } else if pq.len*2 < pq.cap { 220 | //实际使用长度是容量的一半时,进行折半缩容 221 | pq.cap /= 2 222 | tmp := make([]interface{}, pq.cap, pq.cap) 223 | copy(tmp, pq.data) 224 | pq.data = tmp 225 | } 226 | //判断是否为空,为空则直接结束 227 | if pq.Empty() { 228 | pq.mutex.Unlock() 229 | return 230 | } 231 | //对首位进行下降操作,即对比其逻辑上的左右结点判断是否应该下降,再递归该过程即可 232 | pq.down(0) 233 | pq.mutex.Unlock() 234 | } 235 | 236 | //@title down 237 | //@description 238 | // 以priority_queue容器做接收者 239 | // 判断待下沉节点与其左右子节点的大小关系以确定是否进行递归上升 240 | // 从而保证父节点必然都大于或都小于子节点 241 | //@receiver pq *Priority_queue 接受者priority_queue的指针 242 | //@param p uint64 待下沉节点的位置 243 | //@return nil 244 | func (pq *Priority_queue) down(p uint64) { 245 | q := p 246 | //先判断其左结点是否在范围内,然后在判断左结点是否满足下降条件 247 | if 2*p+1 <= pq.len-1 && pq.cmp(pq.data[p], pq.data[2*p+1]) > 0 { 248 | q = 2*p + 1 249 | } 250 | //在判断右结点是否在范围内,同时若判断右节点是否满足下降条件 251 | if 2*p+2 <= pq.len-1 && pq.cmp(pq.data[q], pq.data[2*p+2]) > 0 { 252 | q = 2*p + 2 253 | } 254 | //根据上面两次判断,从最小一侧进行下降 255 | if p != q { 256 | //进行交互,递归下降 257 | pq.data[p], pq.data[q] = pq.data[q], pq.data[p] 258 | pq.down(q) 259 | } 260 | } 261 | 262 | //@title Top 263 | //@description 264 | // 以priority_queue容器做接收者 265 | // 返回该优先队列容器的顶部元素 266 | // 如果容器不存在或容器为空,返回nil 267 | //@receiver pq *Priority_queue 接受者priority_queue的指针 268 | //@param nil 269 | //@return e interface{} 优先队列顶元素 270 | func (pq *Priority_queue) Top() (e interface{}) { 271 | if pq == nil { 272 | pq = New() 273 | } 274 | if pq.Empty() { 275 | return nil 276 | } 277 | pq.mutex.Lock() 278 | e = pq.data[0] 279 | pq.mutex.Unlock() 280 | return e 281 | } 282 | -------------------------------------------------------------------------------- /data_structure/queue/queue.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | //@Title queue 4 | //@Description 5 | // queue队列容器包 6 | // 以动态数组的形式实现 7 | // 该容器可以在尾部实现线性增加元素,在首部实现线性减少元素 8 | // 队列的扩容和缩容同vector一样,即数组小采用翻倍扩缩容/折半缩容,数组大时采用固定扩/缩容 9 | // 该容器满足FIFO的先进先出模式 10 | // 可接纳不同类型的元素 11 | // 通过并发控制锁保证了在高并发过程中的数据一致性 12 | 13 | import ( 14 | "github.com/hlccd/goSTL/utils/iterator" 15 | "sync" 16 | ) 17 | 18 | //queue队列结构体 19 | //包含泛型切片和该切片的首尾位的下标 20 | //当删除节点时仅仅需要后移首位一位即可 21 | //当剩余长度较小时采用缩容策略进行缩容以释放空间 22 | //当添加节点时若未占满全部已分配空间则尾指针后移一位同时进行覆盖存放 23 | //当添加节点时尾指针大于已分配空间长度,则先去掉首部多出来的空间,如果还不足则进行扩容 24 | //首节点指针始终不能超过尾节点指针 25 | type Queue struct { 26 | data []interface{} //泛型切片 27 | begin uint64 //首节点下标 28 | end uint64 //尾节点下标 29 | cap uint64 //容量 30 | mutex sync.Mutex //并发控制锁 31 | } 32 | 33 | //queue队列容器接口 34 | //存放了queue容器可使用的函数 35 | //对应函数介绍见下方 36 | 37 | type queuer interface { 38 | Iterator() (i *Iterator.Iterator) //返回包含队列中所有元素的迭代器 39 | Size() (size uint64) //返回该队列中元素的使用空间大小 40 | Clear() //清空该队列 41 | Empty() (b bool) //判断该队列是否为空 42 | Push(e interface{}) //将元素e添加到该队列末尾 43 | Pop() (e interface{}) //将该队列首元素弹出并返回 44 | Front() (e interface{}) //获取该队列首元素 45 | Back() (e interface{}) //获取该队列尾元素 46 | } 47 | 48 | //@title New 49 | //@description 50 | // 新建一个queue队列容器并返回 51 | // 初始queue的切片数组为空 52 | // 初始queue的首尾指针均置零 53 | //@receiver nil 54 | //@param nil 55 | //@return q *Queue 新建的queue指针 56 | func New() (q *Queue) { 57 | return &Queue{ 58 | data: make([]interface{}, 1, 1), 59 | begin: 0, 60 | end: 0, 61 | cap: 1, 62 | mutex: sync.Mutex{}, 63 | } 64 | } 65 | 66 | //@title Iterator 67 | //@description 68 | // 以queue队列容器做接收者 69 | // 将queue队列容器中不使用空间释放掉 70 | //@return q *Queue 接收者的queue指针 71 | //@param nil 72 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 73 | func (q *Queue) Iterator() (i *Iterator.Iterator) { 74 | if q == nil { 75 | q = New() 76 | } 77 | q.mutex.Lock() 78 | tmp := make([]interface{}, q.end-q.begin, q.end-q.begin) 79 | copy(tmp, q.data[q.begin:q.end]) 80 | i = Iterator.New(&tmp) 81 | q.mutex.Unlock() 82 | return i 83 | } 84 | 85 | //@title Size 86 | //@description 87 | // 以queue队列容器做接收者 88 | // 返回该容器当前含有元素的数量 89 | // 该长度并非实际占用空间数量 90 | // 若容器为空则返回0 91 | //@receiver q *Queue 接受者queue的指针 92 | //@param nil 93 | //@return size uint64 容器中实际使用元素所占空间大小 94 | func (q *Queue) Size() (size uint64) { 95 | if q == nil { 96 | q = New() 97 | } 98 | return q.end - q.begin 99 | } 100 | 101 | //@title Clear 102 | //@description 103 | // 以queue队列容器做接收者 104 | // 将该容器中所承载的元素清空 105 | // 将该容器的首尾指针均置0,容量设为1 106 | //@receiver q *Queue 接受者queue的指针 107 | //@param nil 108 | //@return nil 109 | func (q *Queue) Clear() { 110 | if q == nil { 111 | q = New() 112 | } 113 | q.mutex.Lock() 114 | q.data = make([]interface{}, 1, 1) 115 | q.begin = 0 116 | q.end = 0 117 | q.cap = 1 118 | q.mutex.Unlock() 119 | } 120 | 121 | //@title Empty 122 | //@description 123 | // 以queue队列容器做接收者 124 | // 判断该queue队列容器是否含有元素 125 | // 如果含有元素则不为空,返回false 126 | // 如果不含有元素则说明为空,返回true 127 | // 如果容器不存在,返回true 128 | // 该判断过程通过首尾指针数值进行判断 129 | // 当尾指针数值等于首指针时说明不含有元素 130 | // 当尾指针数值大于首指针时说明含有元素 131 | //@receiver q *Queue 接受者queue的指针 132 | //@param nil 133 | //@return b bool 该容器是空的吗? 134 | func (q *Queue) Empty() (b bool) { 135 | if q == nil { 136 | q = New() 137 | } 138 | return q.Size() <= 0 139 | } 140 | 141 | //@title Push 142 | //@description 143 | // 以queue队列向量容器做接收者 144 | // 在容器尾部插入元素 145 | // 若尾指针小于切片实际使用长度,则对当前指针位置进行覆盖,同时尾下标后移一位 146 | // 若尾指针等于切片实际使用长度,则对实际使用量和实际占用量进行判断 147 | // 当首部还有冗余时则删将实际使用整体前移到首部,否则对尾部进行扩容即可 148 | //@receiver q *Queue 接受者queue的指针 149 | //@param e interface{} 待插入元素 150 | //@return nil 151 | func (q *Queue) Push(e interface{}) { 152 | if q == nil { 153 | q = New() 154 | } 155 | q.mutex.Lock() 156 | if q.end < q.cap { 157 | //不需要扩容 158 | q.data[q.end] = e 159 | } else { 160 | //需要扩容 161 | if q.begin > 0 { 162 | //首部有冗余,整体前移 163 | for i := uint64(0); i < q.end-q.begin; i++ { 164 | q.data[i] = q.data[i+q.begin] 165 | } 166 | q.end -= q.begin 167 | q.begin = 0 168 | } else { 169 | //冗余不足,需要扩容 170 | if q.cap <= 65536 { 171 | //容量翻倍 172 | if q.cap == 0 { 173 | q.cap = 1 174 | } 175 | q.cap *= 2 176 | } else { 177 | //容量增加2^16 178 | q.cap += 2 ^ 16 179 | } 180 | //复制扩容前的元素 181 | tmp := make([]interface{}, q.cap, q.cap) 182 | copy(tmp, q.data) 183 | q.data = tmp 184 | } 185 | q.data[q.end] = e 186 | } 187 | q.end++ 188 | q.mutex.Unlock() 189 | } 190 | 191 | //@title Pop 192 | //@description 193 | // 以queue队列容器做接收者 194 | // 弹出容器第一个元素,同时首下标后移一位 195 | // 若容器为空,则不进行弹出 196 | // 弹出结束后,进行缩容判断,考虑到queue的冗余会存在于前后两个方向 197 | // 所以需要对前后两方分别做判断, 但由于首部主要是减少,并不会增加,所以不需要太多冗余量,而尾部只做添加,所以需要更多的冗余 198 | // 所以可以对首部预留2^10的冗余,当超过时直接对首部冗余清除即可,释放首部空间时尾部空间仍然保留不变 199 | // 当首部冗余不足2^10时,但冗余超过实际使用空间,也会对首部进行缩容,尾部不变 200 | // 同时返回队首元素 201 | //@receiver q *Queue 接受者queue的指针 202 | //@param nil 203 | //@return e interface{} 队首元素 204 | func (q *Queue) Pop() (e interface{}) { 205 | if q == nil { 206 | q = New() 207 | return nil 208 | } 209 | if q.Empty() { 210 | q.Clear() 211 | return nil 212 | } 213 | q.mutex.Lock() 214 | e = q.data[q.begin] 215 | q.begin++ 216 | if q.begin >= 1024 || q.begin*2 > q.end { 217 | //首部冗余超过2^10或首部冗余超过实际使用 218 | q.cap -= q.begin 219 | q.end -= q.begin 220 | tmp := make([]interface{}, q.cap, q.cap) 221 | copy(tmp, q.data[q.begin:]) 222 | q.data = tmp 223 | q.begin = 0 224 | } 225 | q.mutex.Unlock() 226 | return e 227 | } 228 | 229 | //@title Front 230 | //@description 231 | // 以queue队列容器做接收者 232 | // 返回该容器的第一个元素 233 | // 若该容器当前为空,则返回nil 234 | //@receiver q *Queue 接受者queue的指针 235 | //@param nil 236 | //@return e interface{} 容器的第一个元素 237 | func (q *Queue) Front() (e interface{}) { 238 | if q == nil { 239 | q = New() 240 | return nil 241 | } 242 | if q.Empty() { 243 | q.Clear() 244 | return nil 245 | } 246 | return q.data[q.begin] 247 | } 248 | 249 | //@title Back 250 | //@description 251 | // 以queue队列容器做接收者 252 | // 返回该容器的最后一个元素 253 | // 若该容器当前为空,则返回nil 254 | //@receiver q *Queue 接受者queue的指针 255 | //@param nil 256 | //@return e interface{} 容器的最后一个元素 257 | func (q *Queue) Back() (e interface{}) { 258 | if q == nil { 259 | q = New() 260 | return nil 261 | } 262 | if q.Empty() { 263 | q.Clear() 264 | return nil 265 | } 266 | return q.data[q.end-1] 267 | } 268 | -------------------------------------------------------------------------------- /data_structure/radix/node.go: -------------------------------------------------------------------------------- 1 | package radix 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | //@Title radix 8 | //@Description 9 | // 前缀基数树的节点 10 | // 可通过节点的分叉对string进行查找 11 | // 增添string时候需要增删结点,同时将结点内置的map中增删对应的string即可 12 | // 当string到终点时存储元素 13 | 14 | //node树节点结构体 15 | //该节点是radix的树节点 16 | //结点存储到此时的string的前缀数量 17 | //son存储其下属分叉的子结点指针 18 | //该节点同时存储其元素 19 | type node struct { 20 | pattern string //到终点时不为"",其他都为"" 21 | part string //以当前结点的string内容 22 | num int //以当前结点为前缀的数量 23 | sons map[string]*node //该结点下属结点的指针 24 | fuzzy bool //模糊匹配?该结点首字符为':'或'*'为模糊匹配 25 | } 26 | 27 | //@title newNode 28 | //@description 29 | // 新建一个前缀基数树节点并返回 30 | // 将传入的元素e作为该节点的承载元素 31 | //@receiver nil 32 | //@param name string 该节点的名字,即其对应的string 33 | //@return n *node 新建的单词查找树节点的指针 34 | func newNode(part string) (n *node) { 35 | fuzzy := false 36 | if len(part) > 0 { 37 | fuzzy = part[0] == ':' || part[0] == '*' 38 | } 39 | return &node{ 40 | pattern: "", 41 | part: part, 42 | num: 0, 43 | sons: make(map[string]*node), 44 | fuzzy: fuzzy, 45 | } 46 | } 47 | 48 | //@title analysis 49 | //@description 50 | // 将string按'/'进行分段解析 51 | // 为""部分直接舍弃,返回解析结果 52 | // 同时按规则重组用以解析是string并返回 53 | //@receiver nil 54 | //@param s string 待解析的string 55 | //@return ss []string 按'/'进行分层解析后的结果 56 | //@return newS string 按符合规则解析结果重组后的s 57 | func analysis(s string) (ss []string, newS string) { 58 | vs := strings.Split(s, "/") 59 | ss = make([]string, 0) 60 | newS = "/" 61 | for _, item := range vs { 62 | if item != "" { 63 | ss = append(ss, item) 64 | newS = newS + "/" + item 65 | if item[0] == '*' { 66 | break 67 | } 68 | } 69 | } 70 | return ss, newS 71 | } 72 | 73 | //@title inOrder 74 | //@description 75 | // 以node前缀基数树节点做接收者 76 | // 遍历其分叉以找到其存储的所有string 77 | //@receiver n *node 接受者node的指针 78 | //@param s string 到该结点时的前缀string 79 | //@return es []interface{} 以该前缀s为前缀的所有string的集合 80 | func (n *node) inOrder(s string) (es []interface{}) { 81 | if n == nil { 82 | return es 83 | } 84 | if n.pattern != "" { 85 | es = append(es, s+n.part) 86 | } 87 | for _, son := range n.sons { 88 | es = append(es, son.inOrder(s+n.part+"/")...) 89 | } 90 | return es 91 | } 92 | 93 | //@title insert 94 | //@description 95 | // 以node前缀基数树节点做接收者 96 | // 从n节点中继续插入以s为索引的元素e,且当前抵达的string位置为p 97 | // 当到达s终点时进行插入,如果此时node承载了string则插入失败,否则成功 98 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可 99 | // 当插入失败且对应子结点为新建节点时则需要删除该子结点 100 | //@receiver n *node 接受者node的指针 101 | //@param pattern string 待插入的string整体 102 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 103 | //@param p int 索引当前抵达的位置 104 | //@return b bool 是否插入成功? 105 | func (n *node) insert(pattern string, ss []string, p int) (b bool) { 106 | if p == len(ss) { 107 | if n.pattern != "" { 108 | //该节点承载了string 109 | return false 110 | } 111 | //成功插入 112 | n.pattern = pattern 113 | n.num++ 114 | return true 115 | } 116 | //找到该层的string 117 | s := ss[p] 118 | //从其子结点的map中找到对应的方向 119 | son, ok := n.sons[s] 120 | if !ok { 121 | //不存在,新建并放入map中 122 | son = newNode(s) 123 | n.sons[s] = son 124 | } 125 | //从子结点对应方向继续插入 126 | b = son.insert(pattern, ss, p+1) 127 | if b { 128 | n.num++ 129 | } else { 130 | if !ok { 131 | //插入失败且该子节点为新建结点则需要删除该子结点 132 | delete(n.sons, s) 133 | } 134 | } 135 | return b 136 | } 137 | 138 | //@title erase 139 | //@description 140 | // 以node前缀基数树节点做接收者 141 | // 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p 142 | // 当到达s终点时进行删除,如果此时node未承载元素则删除失败,否则成功 143 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接失败 144 | //@receiver n *node 接受者node的指针 145 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 146 | //@param p int 索引当前抵达的位置 147 | //@return b bool 是否删除成功? 148 | func (n *node) erase(ss []string, p int) (b bool) { 149 | if p == len(ss) { 150 | if n.pattern != "" { 151 | //该结点承载是string是,删除成功 152 | n.pattern = "" 153 | n.num-- 154 | return true 155 | } 156 | return false 157 | } 158 | //从map中找到对应下子结点位置并递归进行删除 159 | s := ss[p] 160 | son, ok := n.sons[s] 161 | if !ok || son == nil { 162 | //未找到或son不存在,删除失败 163 | return false 164 | } 165 | b = son.erase(ss, p+1) 166 | if b { 167 | n.num-- 168 | if son.num <= 0 { 169 | //删除后子结点的num<=0即该节点无后续存储元素,可以销毁 170 | delete(n.sons, s) 171 | } 172 | } 173 | return b 174 | } 175 | 176 | //@title delete 177 | //@description 178 | // 以node前缀基数树节点做接收者 179 | // 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p 180 | // 当到达s终点时进行删除,删除所有后续元素,并返回其后续元素的数量 181 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接返回0 182 | //@receiver n *node 接受者node的指针 183 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 184 | //@param p int 索引当前抵达的位置 185 | //@return num int 被删除元素的数量 186 | func (n *node) delete(ss []string, p int) (num int) { 187 | if p == len(ss) { 188 | return n.num 189 | } 190 | //从map中找到对应下子结点位置并递归进行删除 191 | s := ss[p] 192 | son, ok := n.sons[s] 193 | if !ok || son == nil { 194 | return 0 195 | } 196 | num = son.delete(ss, p+1) 197 | if num > 0 { 198 | son.num -= num 199 | if son.num <= 0 { 200 | //删除后子结点的num<=0即该节点无后续存储元素,可以销毁 201 | delete(n.sons, s) 202 | } 203 | } 204 | return num 205 | } 206 | 207 | //@title count 208 | //@description 209 | // 以node前缀基数树节点做接收者 210 | // 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p 211 | // 当到达s终点时返回其值即可 212 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回0 213 | //@receiver n *node 接受者node的指针 214 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 215 | //@param p int 索引当前抵达的位置 216 | //@return num int 以该s为前缀的string的数量 217 | func (n *node) count(ss []string, p int) (num int) { 218 | if p == len(ss) { 219 | return n.num 220 | } 221 | //从map中找到对应下子结点位置并递归进行查找 222 | s := ss[p] 223 | son, ok := n.sons[s] 224 | if !ok || son == nil { 225 | return 0 226 | } 227 | return son.count(ss, p+1) 228 | } 229 | 230 | //@title mate 231 | //@description 232 | // 以node前缀基数树节点做接收者 233 | // 先从radix树的根节点开始找到第一个可以满足该模糊匹配方案的string结点 234 | // 随后将s和结点的pattern进行模糊映射,将模糊查找的值和匹配值进行映射并返回即可 235 | // 若该结点未找到则直接返回nil和false即可 236 | //@receiver n *node 接受者node的指针 237 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 238 | //@param p int 索引当前抵达的位置 239 | //@return m map[string]string s从结点中利用模糊匹配到的所有key和value的映射 240 | //@return ok bool 匹配成功? 241 | func (n *node) mate(s string, p int) (m map[string]string, ok bool) { 242 | //解析url 243 | searchParts, _ := analysis(s) 244 | //从该请求类型中寻找对应的路由结点 245 | q := n.find(searchParts, 0) 246 | if q != nil { 247 | //解析该结点的pattern 248 | parts, _ := analysis(q.pattern) 249 | //动态参数映射表 250 | params := make(map[string]string) 251 | for index, part := range parts { 252 | if part[0] == ':' { 253 | //动态匹配,将参数名和参数内容的映射放入映射表内 254 | params[part[1:]] = searchParts[index] 255 | } 256 | if part[0] == '*' && len(part) > 1 { 257 | //通配符,将后续所有内容全部添加到映射表内同时结束遍历 258 | params[part[1:]] = strings.Join(searchParts[index:], "/") 259 | break 260 | } 261 | } 262 | return params, true 263 | } 264 | return nil, false 265 | } 266 | 267 | //@title find 268 | //@description 269 | // 以node前缀基数树节点做接收者 270 | // 从radix树的根节点开始找到第一个可以满足该模糊匹配方案的string结点 271 | // 若该结点未找到则直接返回nil 272 | //@receiver n *node 接受者node的指针 273 | //@param ss []string 待删除元素的索引s的按'/'进行分层的索引集合 274 | //@param p int 索引当前抵达的位置 275 | //@return m map[string]string s从结点中利用模糊匹配到的所有key和value的映射 276 | //@return ok bool 匹配成功? 277 | func (n *node) find(parts []string, height int) (q *node) { 278 | //根据长度和局部string的首字符进行判断 279 | if len(parts) == height || strings.HasPrefix(n.part, "*") { 280 | if n.pattern == "" { 281 | //匹配失败,该结点处无匹配的信息 282 | return nil 283 | } 284 | //匹配成功,返回该结点 285 | return n 286 | } 287 | //从该结点的所有子结点中查找可用于递归查找的结点 288 | //当局部string信息和当前层string相同时可用于递归查找 289 | //当该子结点是动态匹配时也可以用于递归查找 290 | part := parts[height] 291 | //从所有子结点中找到可用于递归查找的结点 292 | children := make([]*node, 0, 0) 293 | for _, child := range n.sons { 294 | if child.part == part || child.fuzzy { 295 | //局部string相同或动态匹配 296 | children = append(children, child) 297 | } 298 | } 299 | for _, child := range children { 300 | //递归查询,并根据结果进行判断 301 | result := child.find(parts, height+1) 302 | if result != nil { 303 | //存在一个满足时就可以返回 304 | return result 305 | } 306 | } 307 | return nil 308 | } 309 | -------------------------------------------------------------------------------- /data_structure/radix/radix.go: -------------------------------------------------------------------------------- 1 | package radix 2 | 3 | //@Title radix 4 | //@Description 5 | // 前缀基数树-radix 6 | // 以多叉树的形式实现,根据'/'进行string分割,将分割后的string数组进行段存储 7 | // 不存储其他元素,仅对string进行分段存储和模糊匹配 8 | // 使用互斥锁实现并发控制 9 | 10 | import ( 11 | "github.com/hlccd/goSTL/utils/iterator" 12 | "sync" 13 | ) 14 | 15 | //radix前缀基数树结构体 16 | //该实例存储前缀基数树的根节点 17 | //同时保存该树已经存储了多少个元素 18 | type radix struct { 19 | root *node //前缀基数树的根节点指针 20 | size int //当前已存放的元素数量 21 | mutex sync.Mutex //并发控制锁 22 | } 23 | 24 | //radix前缀基数树容器接口 25 | //存放了radix前缀基数树可使用的函数 26 | //对应函数介绍见下方 27 | type radixer interface { 28 | Iterator() (i *Iterator.Iterator) //返回包含该radix的所有string 29 | Size() (num int) //返回该radix中保存的元素个数 30 | Clear() //清空该radix 31 | Empty() (b bool) //判断该radix是否为空 32 | Insert(s string) (b bool) //向radix中插入string 33 | Erase(s string) (b bool) //从radix中删除string 34 | Delete(s string) (num int) //从radix中删除以s为前缀的所有string 35 | Count(s string) (num int) //从radix中寻找以s为前缀的string单词数 36 | Mate(s string) (m map[string]string, ok bool) //利用radix树中的string对s进行模糊匹配,':'可模糊匹配该层,'*'可模糊匹配后面所有 37 | } 38 | 39 | //@title New 40 | //@description 41 | // 新建一个radix前缀基数树容器并返回 42 | // 初始根节点为nil 43 | //@receiver nil 44 | //@param nil 45 | //@return r *radix 新建的radix指针 46 | func New() (r *radix) { 47 | return &radix{ 48 | root: newNode(""), 49 | size: 0, 50 | mutex: sync.Mutex{}, 51 | } 52 | } 53 | 54 | //@title Iterator 55 | //@description 56 | // 以radix前缀基数树做接收者 57 | // 将该radix中所有存放的string放入迭代器中并返回 58 | //@receiver r *radix 接受者radix的指针 59 | //@param nil 60 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 61 | func (r *radix) Iterator() (i *Iterator.Iterator) { 62 | if r == nil { 63 | return nil 64 | } 65 | r.mutex.Lock() 66 | es := r.root.inOrder("") 67 | i = Iterator.New(&es) 68 | r.mutex.Unlock() 69 | return i 70 | } 71 | 72 | //@title Size 73 | //@description 74 | // 以radix前缀基数树做接收者 75 | // 返回该容器当前含有元素的数量 76 | // 如果容器为nil返回0 77 | //@receiver r *radix 接受者radix的指针 78 | //@param nil 79 | //@return num int 容器中实际使用元素所占空间大小 80 | func (r *radix) Size() (num int) { 81 | if r == nil { 82 | return 0 83 | } 84 | if r.root == nil { 85 | return 0 86 | } 87 | return r.size 88 | } 89 | 90 | //@title Clear 91 | //@description 92 | // 以radix前缀基数树做接收者 93 | // 将该容器中所承载的元素清空 94 | // 将该容器的size置0 95 | //@receiver r *radix 接受者radix的指针 96 | //@param nil 97 | //@return nil 98 | func (r *radix) Clear() { 99 | if r == nil { 100 | return 101 | } 102 | r.mutex.Lock() 103 | r.root = newNode("") 104 | r.size = 0 105 | r.mutex.Unlock() 106 | } 107 | 108 | //@title Empty 109 | //@description 110 | // 以radix前缀基数树做接收者 111 | // 判断该radix是否含有元素 112 | // 如果含有元素则不为空,返回false 113 | // 如果不含有元素则说明为空,返回true 114 | // 如果容器不存在,返回true 115 | //@receiver r *radix 接受者radix的指针 116 | //@param nil 117 | //@return b bool 该容器是空的吗? 118 | func (r *radix) Empty() (b bool) { 119 | if r == nil { 120 | return true 121 | } 122 | return r.size == 0 123 | } 124 | 125 | //@title Insert 126 | //@description 127 | // 以radix前缀基数树做接收者 128 | // 向radix插入string 129 | // 将对string进行解析,按'/'进行分层,':'为首则为模糊匹配该层,'*'为首则为模糊匹配后面所有 130 | // 已经存在则无法重复插入 131 | //@receiver r *radix 接受者radix的指针 132 | //@param s string 待插入string 133 | //@return b bool 添加成功? 134 | func (r *radix) Insert(s string) (b bool) { 135 | if r == nil { 136 | return false 137 | } 138 | //解析s并按规则重构s 139 | ss, s := analysis(s) 140 | r.mutex.Lock() 141 | if r.root == nil { 142 | //避免根节点为nil 143 | r.root = newNode("") 144 | } 145 | //从根节点开始插入 146 | b = r.root.insert(s, ss, 0) 147 | if b { 148 | //插入成功,size+1 149 | r.size++ 150 | } 151 | r.mutex.Unlock() 152 | return b 153 | } 154 | 155 | //@title Erase 156 | //@description 157 | // 以radix前缀基数树做接收者 158 | // 从radix树中删除元素string 159 | //@receiver r *radix 接受者radix的指针 160 | //@param s string 待删除的string 161 | //@return b bool 删除成功? 162 | func (r *radix) Erase(s string) (b bool) { 163 | if r.Empty() { 164 | return false 165 | } 166 | if len(s) == 0 { 167 | return false 168 | } 169 | if r.root == nil { 170 | //根节点为nil即无法删除 171 | return false 172 | } 173 | //解析s并按规则重构s 174 | ss, _ := analysis(s) 175 | r.mutex.Lock() 176 | //从根节点开始删除 177 | b = r.root.erase(ss, 0) 178 | if b { 179 | //删除成功,size-1 180 | r.size-- 181 | if r.size == 0 { 182 | //所有string都被删除,根节点置为nil 183 | r.root = nil 184 | } 185 | } 186 | r.mutex.Unlock() 187 | return b 188 | } 189 | 190 | //@title Delete 191 | //@description 192 | // 以radix前缀基数树做接收者 193 | // 从radix树中删除以s为前缀的所有string 194 | //@receiver r *radix 接受者radix的指针 195 | //@param s string 待删除string的前缀 196 | //@return num int 被删除的元素的数量 197 | func (r *radix) Delete(s string) (num int) { 198 | if r.Empty() { 199 | return 0 200 | } 201 | if len(s) == 0 { 202 | return 0 203 | } 204 | if r.root == nil { 205 | return 0 206 | } 207 | //解析s并按规则重构s 208 | ss, _ := analysis(s) 209 | r.mutex.Lock() 210 | //从根节点开始删除 211 | num = r.root.delete(ss, 0) 212 | if num > 0 { 213 | //删除成功 214 | r.size -= num 215 | if r.size <= 0 { 216 | //所有string都被删除,根节点置为nil 217 | r.root = nil 218 | } 219 | } 220 | r.mutex.Unlock() 221 | return num 222 | } 223 | 224 | //@title Count 225 | //@description 226 | // 以radix前缀基数树做接收者 227 | // 从radix中查找以s为前缀的所有string的个数 228 | // 如果存在以s为前缀的则返回大于0的值即其数量 229 | // 如果未找到则返回0 230 | //@receiver r *radix 接受者radix的指针 231 | //@param s string 待查找的前缀s 232 | //@return num int 待查找前缀在radix树中存在的数量 233 | func (r *radix) Count(s string) (num int) { 234 | if r.Empty() { 235 | return 0 236 | } 237 | if r.root == nil { 238 | return 0 239 | } 240 | if len(s) == 0 { 241 | return 0 242 | } 243 | //解析s并按规则重构s 244 | ss, _ := analysis(s) 245 | r.mutex.Lock() 246 | num = r.root.count(ss, 0) 247 | r.mutex.Unlock() 248 | return num 249 | } 250 | 251 | //@title Mate 252 | //@description 253 | // 以radix前缀基数树做接收者 254 | // 从radix中查找以s为信息的第一个可以模糊匹配到的key和value的映射表 255 | // key是radix树中的段名,value是s中的段名 256 | // 如果未找到则返回nil和false 257 | // 否则返回一个映射表和true 258 | //@receiver r *radix 接受者radix的指针 259 | //@param s string 待查找的信息s 260 | //@return m map[string]string s从前缀基数树中利用模糊匹配到的所有key和value的映射 261 | //@return ok bool 匹配成功? 262 | func (r *radix) Mate(s string) (m map[string]string, ok bool) { 263 | if r.Empty() { 264 | return nil, false 265 | } 266 | if len(s) == 0 { 267 | return nil, false 268 | } 269 | if r.root == nil { 270 | return nil, false 271 | } 272 | //将s按'/'进行分割,并去掉第一个即去掉"",随后一次按照分层结果进行查找 273 | m, ok = r.root.mate(s, 0) 274 | return m, ok 275 | } 276 | -------------------------------------------------------------------------------- /data_structure/ring/node.go: -------------------------------------------------------------------------------- 1 | package ring 2 | 3 | //@Title ring 4 | //@Description 5 | // ring环容器包 6 | // 该部分包含了环的节点 7 | // 环的增删都通过节点的增删完成 8 | // 结点间可插入其前后节点,并同时将两结点建立连接 9 | 10 | //环的node节点结构体 11 | //pre和next是该节点的前后两个节点的指针 12 | //用以保证环整体是相连的 13 | type node struct { 14 | data interface{} //结点所承载的元素 15 | pre *node //前结点指针 16 | next *node //后结点指针 17 | } 18 | 19 | //node结点容器接口 20 | //存放了node容器可使用的函数 21 | //对应函数介绍见下方 22 | 23 | type noder interface { 24 | preNode() (m *node) //返回前结点指针 25 | nextNode() (m *node) //返回后结点指针 26 | insertPre(pre *node) //在该结点前插入结点并建立连接 27 | insertNext(next *node) //在该结点后插入结点并建立连接 28 | erase() //删除该结点,并使该结点前后两结点建立连接 29 | value() (e interface{}) //返回该结点所承载的元素 30 | setValue(e interface{}) //修改该结点承载元素为e 31 | } 32 | 33 | //@title newNode 34 | //@description 35 | // 新建一个自环结点并返回其指针 36 | // 初始首结点的前后结点指针都为自身 37 | //@receiver nil 38 | //@param nil 39 | //@return n *node 新建的node指针 40 | func newNode(e interface{}) (n *node) { 41 | n = &node{ 42 | data: e, 43 | pre: nil, 44 | next: nil, 45 | } 46 | n.pre = n 47 | n.next = n 48 | return n 49 | } 50 | 51 | //@title preNode 52 | //@description 53 | // 以node结点做接收者 54 | // 返回该结点的前结点 55 | //@receiver n *node 接收者的node指针 56 | //@param nil 57 | //@return pre *node 该结点的前结点指针 58 | func (n *node) preNode() (pre *node) { 59 | if n == nil { 60 | return 61 | } 62 | return n.pre 63 | } 64 | 65 | //@title nextNode 66 | //@description 67 | // 以node结点做接收者 68 | // 返回该结点的后结点 69 | //@receiver n *node 接收者的node指针 70 | //@param nil 71 | //@return next *node 该结点的后结点指针 72 | func (n *node) nextNode() (next *node) { 73 | if n == nil { 74 | return 75 | } 76 | return n.next 77 | } 78 | 79 | //@title insertPre 80 | //@description 81 | // 以node结点做接收者 82 | // 对该结点插入前结点 83 | // 并建立前结点和该结点之间的连接 84 | //@receiver n *node 接收者的node指针 85 | //@param pre *node 该结点的前结点指针 86 | //@return nil 87 | func (n *node) insertPre(pre *node) { 88 | if n == nil || pre == nil { 89 | return 90 | } 91 | pre.next = n 92 | pre.pre = n.pre 93 | if n.pre != nil { 94 | n.pre.next = pre 95 | } 96 | n.pre = pre 97 | } 98 | 99 | //@title insertNext 100 | //@description 101 | // 以node结点做接收者 102 | // 对该结点插入后结点 103 | // 并建立后结点和该结点之间的连接 104 | //@receiver n *node 接收者的node指针 105 | //@param next *node 该结点的后结点指针 106 | //@return nil 107 | func (n *node) insertNext(next *node) { 108 | if n == nil || next == nil { 109 | return 110 | } 111 | next.pre = n 112 | next.next = n.next 113 | if n.next != nil { 114 | n.next.pre = next 115 | } 116 | n.next = next 117 | } 118 | 119 | //@title erase 120 | //@description 121 | // 以node结点做接收者 122 | // 销毁该结点 123 | // 同时建立该节点前后节点之间的连接 124 | //@receiver n *node 接收者的node指针 125 | //@param nil 126 | //@return nil 127 | func (n *node) erase() { 128 | if n == nil { 129 | return 130 | } 131 | if n.pre == nil && n.next == nil { 132 | return 133 | } else if n.pre == nil { 134 | n.next.pre = nil 135 | } else if n.next == nil { 136 | n.pre.next = nil 137 | } else { 138 | n.pre.next = n.next 139 | n.next.pre = n.pre 140 | } 141 | n = nil 142 | } 143 | 144 | //@title value 145 | //@description 146 | // 以node结点做接收者 147 | // 返回该结点所要承载的元素 148 | //@receiver n *node 接收者的node指针 149 | //@param nil 150 | //@return e interface{} 该节点所承载的元素e 151 | func (n *node) value() (e interface{}) { 152 | if n == nil { 153 | return nil 154 | } 155 | return n.data 156 | } 157 | 158 | //@title setValue 159 | //@description 160 | // 以node结点做接收者 161 | // 对该结点设置其承载的元素 162 | //@receiver n *node 接收者的node指针 163 | //@param e interface{} 该节点所要承载的元素e 164 | //@return nil 165 | func (n *node) setValue(e interface{}) { 166 | if n == nil { 167 | return 168 | } 169 | n.data = e 170 | } 171 | -------------------------------------------------------------------------------- /data_structure/ring/ring.go: -------------------------------------------------------------------------------- 1 | package ring 2 | 3 | //@Title ring 4 | //@Description 5 | // ring环容器包 6 | // 环将所有结点通过指针的方式串联起来,从而使得其整体保持一个线性状态 7 | // 不同于链表首尾不相连的情况,环将首尾结点连接起来,从而摒弃孤立的首尾结点 8 | // 可以利用其中的任何一个结点遍历整个环,也可以在任何位置进行插入 9 | // 增删结点需要同步修改其相邻的元素的前后指针以保证其整体是联通的 10 | // 可接纳不同类型的元素 11 | // 通过并发控制锁保证了在高并发过程中的数据一致性 12 | 13 | import ( 14 | "github.com/hlccd/goSTL/utils/iterator" 15 | "sync" 16 | ) 17 | 18 | //ring环结构体 19 | //包含环的头尾节点指针 20 | //当增删结点时只需要移动到对应位置进行操作即可 21 | //当一个节点进行增删时需要同步修改其临接结点的前后指针 22 | //结构体中记录该环中当前所持有的结点的指针即可 23 | //同时记录该环中存在多少元素即size 24 | //使用并发控制锁以保证数据一致性 25 | type Ring struct { 26 | now *node //环当前持有的结点指针 27 | size uint64 //当前存储的元素个数 28 | mutex sync.Mutex //并发控制锁 29 | } 30 | 31 | //ring环容器接口 32 | //存放了ring容器可使用的函数 33 | //对应函数介绍见下方 34 | 35 | type ringer interface { 36 | Iterator() (i *Iterator.Iterator) //创建一个包含环中所有元素的迭代器并返回其指针 37 | Size() (size uint64) //返回环所承载的元素个数 38 | Clear() //清空该环 39 | Empty() (b bool) //判断该环是否位空 40 | Insert(e interface{}) //向环当前位置后方插入元素e 41 | Erase() //删除当前结点并持有下一结点 42 | Value() (e interface{}) //返回当前持有结点的元素 43 | Set(e interface{}) //在当前结点设置其承载的元素为e 44 | Next() //持有下一节点 45 | Pre() //持有上一结点 46 | } 47 | 48 | //@title New 49 | //@description 50 | // 新建一个ring环容器并返回 51 | // 初始持有的结点不存在,即为nil 52 | // 初始size为0 53 | //@receiver nil 54 | //@param nil 55 | //@return r *Ring 新建的ring指针 56 | func New() (r *Ring) { 57 | return &Ring{ 58 | now: nil, 59 | size: 0, 60 | mutex: sync.Mutex{}, 61 | } 62 | } 63 | 64 | //@title Iterator 65 | //@description 66 | // 以ring环容器做接收者 67 | // 将ring环容器中所承载的元素放入迭代器中 68 | // 从该结点开始向后遍历获取全部承载的元素 69 | //@receiver r *Ring 接收者的ring指针 70 | //@param nil 71 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 72 | func (r *Ring) Iterator() (i *Iterator.Iterator) { 73 | if r == nil { 74 | r = New() 75 | } 76 | r.mutex.Lock() 77 | //将所有元素复制出来放入迭代器中 78 | tmp := make([]interface{}, r.size, r.size) 79 | //从当前结点开始向后遍历 80 | for n, idx := r.now, uint64(0); n != nil && idx < r.size; n, idx = n.nextNode(), idx+1 { 81 | tmp[idx] = n.value() 82 | } 83 | i = Iterator.New(&tmp) 84 | r.mutex.Unlock() 85 | return i 86 | } 87 | 88 | //@title Size 89 | //@description 90 | // 以ring环容器做接收者 91 | // 返回该容器当前含有元素的数量 92 | //@receiver r *Ring 接收者的ring指针 93 | //@param nil 94 | //@return num int 容器中所承载的元素数量 95 | func (r *Ring) Size() (size uint64) { 96 | if r == nil { 97 | r = New() 98 | } 99 | return r.size 100 | } 101 | 102 | //@title Clear 103 | //@description 104 | // 以ring环容器做接收者 105 | // 将该容器中所承载的元素清空 106 | // 将该容器的当前持有的结点置为nil,长度初始为0 107 | //@receiver r *Ring 接收者的ring指针 108 | //@param nil 109 | //@return nil 110 | func (r *Ring) Clear() { 111 | if r == nil { 112 | r = New() 113 | } 114 | r.mutex.Lock() 115 | //销毁环 116 | r.now = nil 117 | r.size = 0 118 | r.mutex.Unlock() 119 | } 120 | 121 | //@title Empty 122 | //@description 123 | // 以ring环容器做接收者 124 | // 判断该ring环容器是否含有元素 125 | // 该判断过程通过size进行判断,size为0则为true,否则为false 126 | //@receiver r *Ring 接收者的ring指针 127 | //@param nil 128 | //@return b bool 该容器是空的吗? 129 | func (r *Ring) Empty() (b bool) { 130 | if r == nil { 131 | r = New() 132 | } 133 | return r.size == 0 134 | } 135 | 136 | //@title Insert 137 | //@description 138 | // 以ring环容器做接收者 139 | // 通过环中当前持有的结点进行添加 140 | // 如果环为建立,则新建一个自环结点设为环 141 | // 存在持有的结点,则在其后方添加即可 142 | //@receiver r *Ring 接收者的ring指针 143 | //@param e interface{} 待插入元素 144 | //@return nil 145 | func (r *Ring) Insert(e interface{}) { 146 | if r == nil { 147 | r = New() 148 | } 149 | r.mutex.Lock() 150 | //新建自环结点 151 | n := newNode(e) 152 | if r.size == 0 { 153 | //原本无环,设为新环 154 | r.now = n 155 | } else { 156 | //持有结点,在后方插入 157 | r.now.insertNext(n) 158 | } 159 | r.size++ 160 | r.mutex.Unlock() 161 | } 162 | 163 | //@title Erase 164 | //@description 165 | // 以ring环容器做接收者 166 | // 先判断是否仅持有一个结点 167 | // 若仅有一个结点,则直接销毁环 168 | // 否则将当前持有结点设为下一节点,并前插原持有结点的前结点即可 169 | //@receiver r *Ring 接收者的ring指针 170 | //@param nil 171 | //@return nil 172 | func (r *Ring) Erase() { 173 | if r == nil { 174 | r = New() 175 | } 176 | if r.size == 0 { 177 | return 178 | } 179 | r.mutex.Lock() 180 | //删除开始 181 | if r.size == 1 { 182 | //环内仅有一个结点,销毁环即可 183 | r.now = nil 184 | } else { 185 | //环内还有其他结点,将持有结点后移一位 186 | //后移后将当前结点前插原持有结点的前结点 187 | r.now = r.now.nextNode() 188 | r.now.insertPre(r.now.preNode().preNode()) 189 | } 190 | r.size-- 191 | r.mutex.Unlock() 192 | } 193 | 194 | //@title Value 195 | //@description 196 | // 以ring环容器做接收者 197 | // 获取环中当前持有节点所承载的元素 198 | // 若环中持有的结点不存在,直接返回nil 199 | //@receiver r *Ring 接收者的ring指针 200 | //@param nil 201 | //@return e interface{} 获取的元素 202 | func (r *Ring) Value() (e interface{}) { 203 | if r == nil { 204 | r = New() 205 | } 206 | if r.now == nil { 207 | //无持有结点,直接返回nil 208 | return nil 209 | } 210 | return r.now.value() 211 | } 212 | 213 | //@title Set 214 | //@description 215 | // 以ring环容器做接收者 216 | // 修改当前持有结点所承载的元素 217 | // 若未持有结点,直接结束即可 218 | //@receiver r *Ring 接收者的ring指针 219 | //@param e interface{} 修改后当元素 220 | //@return nil 221 | func (r *Ring) Set(e interface{}) { 222 | if r == nil { 223 | r = New() 224 | } 225 | if r.now == nil { 226 | return 227 | } 228 | r.mutex.Lock() 229 | r.now.setValue(e) 230 | r.mutex.Unlock() 231 | } 232 | 233 | //@title Next 234 | //@description 235 | // 以ring环容器做接收者 236 | // 将当前持有的结点后移一位 237 | // 若当前无持有结点,则直接结束 238 | //@receiver r *Ring 接收者的ring指针 239 | //@param nil 240 | //@return nil 241 | func (r *Ring) Next() { 242 | if r == nil { 243 | r = New() 244 | } 245 | if r.now == nil { 246 | return 247 | } 248 | r.mutex.Lock() 249 | r.now = r.now.nextNode() 250 | r.mutex.Unlock() 251 | } 252 | 253 | //@title Pre 254 | //@description 255 | // 以ring环容器做接收者 256 | // 将当前持有的结点前移一位 257 | // 若当前无持有结点,则直接结束 258 | //@receiver r *Ring 接收者的ring指针 259 | //@param nil 260 | //@return nil 261 | func (r *Ring) Pre() { 262 | if r == nil { 263 | r = New() 264 | } 265 | if r.size == 0 { 266 | return 267 | } 268 | r.mutex.Lock() 269 | r.now = r.now.preNode() 270 | r.mutex.Unlock() 271 | } 272 | -------------------------------------------------------------------------------- /data_structure/stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | //@Title stack 4 | //@Description 5 | // stack栈容器包 6 | // 以动态数组的形式实现,扩容方式同vector 7 | // 该容器可以在顶部实现线性增减元素 8 | // 通过interface实现泛型,可接纳不同类型的元素 9 | // 互斥锁实现并发控制 10 | import ( 11 | "github.com/hlccd/goSTL/utils/iterator" 12 | "sync" 13 | ) 14 | 15 | //stack栈结构体 16 | //包含动态数组和该数组的顶部指针 17 | //顶部指针指向实际顶部元素的下一位置 18 | //当删除节点时仅仅需要下移顶部指针一位即可 19 | //当新增结点时优先利用冗余空间 20 | //当冗余空间不足时先倍增空间至2^16,超过后每次增加2^16的空间 21 | //删除结点后如果冗余超过2^16,则释放掉 22 | //删除后若冗余量超过使用量,也释放掉冗余空间 23 | type Stack struct { 24 | data []interface{} //用于存储元素的动态数组 25 | top uint64 //顶部指针 26 | cap uint64 //动态数组的实际空间 27 | mutex sync.Mutex //并发控制锁 28 | } 29 | 30 | //stack栈容器接口 31 | //存放了stack容器可使用的函数 32 | //对应函数介绍见下方 33 | type stacker interface { 34 | Iterator() (i *Iterator.Iterator) //返回一个包含栈中所有元素的迭代器 35 | Size() (num uint64) //返回该栈中元素的使用空间大小 36 | Clear() //清空该栈容器 37 | Empty() (b bool) //判断该栈容器是否为空 38 | Push(e interface{}) //将元素e添加到栈顶 39 | Pop() //弹出栈顶元素 40 | Top() (e interface{}) //返回栈顶元素 41 | } 42 | 43 | //@title New 44 | //@description 45 | // 新建一个stack栈容器并返回 46 | // 初始stack的动态数组容量为1 47 | // 初始stack的顶部指针置0,容量置1 48 | //@receiver nil 49 | //@param nil 50 | //@return s *Stack 新建的stack指针 51 | func New() (s *Stack) { 52 | return &Stack{ 53 | data: make([]interface{}, 1, 1), 54 | top: 0, 55 | cap: 1, 56 | mutex: sync.Mutex{}, 57 | } 58 | } 59 | 60 | //@title Iterator 61 | //@description 62 | // 以stack栈容器做接收者 63 | // 将stack栈容器中不使用空间释放掉 64 | // 返回一个包含容器中所有使用元素的迭代器 65 | //@receiver s *Stack 接受者stack的指针 66 | //@param nil 67 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 68 | func (s *Stack) Iterator() (i *Iterator.Iterator) { 69 | if s == nil { 70 | s = New() 71 | } 72 | s.mutex.Lock() 73 | if s.data == nil { 74 | //data不存在,新建一个 75 | s.data = make([]interface{}, 1, 1) 76 | s.top = 0 77 | s.cap = 1 78 | } else if s.top < s.cap { 79 | //释放未使用的空间 80 | tmp := make([]interface{}, s.top, s.top) 81 | copy(tmp, s.data) 82 | s.data = tmp 83 | } 84 | //创建迭代器 85 | i = Iterator.New(&s.data) 86 | s.mutex.Unlock() 87 | return i 88 | } 89 | 90 | //@title Size 91 | //@description 92 | // 以stack栈容器做接收者 93 | // 返回该容器当前含有元素的数量 94 | //@receiver s *Stack 接受者stack的指针 95 | //@param nil 96 | //@return num int 容器中实际使用元素所占空间大小 97 | func (s *Stack) Size() (num uint64) { 98 | if s == nil { 99 | s = New() 100 | } 101 | return s.top 102 | } 103 | 104 | //@title Clear 105 | //@description 106 | // 以stack栈容器做接收者 107 | // 将该容器中所承载的元素清空 108 | // 将该容器的尾指针置0 109 | //@receiver s *Stack 接受者stack的指针 110 | //@param nil 111 | //@return nil 112 | func (s *Stack) Clear() { 113 | if s == nil { 114 | s = New() 115 | } 116 | s.mutex.Lock() 117 | s.data = make([]interface{}, 0, 0) 118 | s.top = 0 119 | s.cap = 1 120 | s.mutex.Unlock() 121 | } 122 | 123 | //@title Empty 124 | //@description 125 | // 以stack栈容器做接收者 126 | // 判断该stack栈容器是否含有元素 127 | // 如果含有元素则不为空,返回false 128 | // 如果不含有元素则说明为空,返回true 129 | // 如果容器不存在,返回true 130 | // 该判断过程通过顶部指针数值进行判断 131 | // 当顶部指针数值为0时说明不含有元素 132 | // 当顶部指针数值大于0时说明含有元素 133 | //@receiver s *Stack 接受者stack的指针 134 | //@param nil 135 | //@return b bool 该容器是空的吗? 136 | func (s *Stack) Empty() (b bool) { 137 | if s == nil { 138 | return true 139 | } 140 | return s.Size() == 0 141 | } 142 | 143 | //@title Push 144 | //@description 145 | // 以stack栈容器做接收者 146 | // 在容器顶部插入元素 147 | // 若存储冗余空间,则在顶部指针位插入元素,随后上移顶部指针 148 | // 否则进行扩容,扩容后获得冗余空间重复上一步即可。 149 | //@receiver s *Stack 接受者stack的指针 150 | //@param e interface{} 待插入顶部的元素 151 | //@return nil 152 | func (s *Stack) Push(e interface{}) { 153 | if s == nil { 154 | s = New() 155 | } 156 | s.mutex.Lock() 157 | if s.top < s.cap { 158 | //还有冗余,直接添加 159 | s.data[s.top] = e 160 | } else { 161 | //冗余不足,需要扩容 162 | if s.cap <= 65536 { 163 | //容量翻倍 164 | if s.cap == 0 { 165 | s.cap = 1 166 | } 167 | s.cap *= 2 168 | } else { 169 | //容量增加2^16 170 | s.cap += 65536 171 | } 172 | //复制扩容前的元素 173 | tmp := make([]interface{}, s.cap, s.cap) 174 | copy(tmp, s.data) 175 | s.data = tmp 176 | s.data[s.top] = e 177 | } 178 | s.top++ 179 | s.mutex.Unlock() 180 | } 181 | 182 | //@title Pop 183 | //@description 184 | // 以stack栈容器做接收者 185 | // 弹出容器顶部元素,同时顶部指针下移一位 186 | // 当顶部指针小于容器切片实际使用空间的一半时,重新分配空间释放未使用部分 187 | // 若容器为空,则不进行弹出 188 | //@receiver s *Stack 接受者stack的指针 189 | //@param nil 190 | //@return nil 191 | func (s *Stack) Pop() { 192 | if s == nil { 193 | s = New() 194 | return 195 | } 196 | if s.Empty() { 197 | return 198 | } 199 | s.mutex.Lock() 200 | s.top-- 201 | if s.cap-s.top >= 65536 { 202 | //容量和实际使用差值超过2^16时,容量直接减去2^16 203 | s.cap -= 65536 204 | tmp := make([]interface{}, s.cap, s.cap) 205 | copy(tmp, s.data) 206 | s.data = tmp 207 | } else if s.top*2 < s.cap { 208 | //实际使用长度是容量的一半时,进行折半缩容 209 | s.cap /= 2 210 | tmp := make([]interface{}, s.cap, s.cap) 211 | copy(tmp, s.data) 212 | s.data = tmp 213 | } 214 | s.mutex.Unlock() 215 | } 216 | 217 | //@title Top 218 | //@description 219 | // 以stack栈容器做接收者 220 | // 返回该容器的顶部元素 221 | // 若该容器当前为空,则返回nil 222 | //@receiver s *Stack 接受者stack的指针 223 | //@param nil 224 | //@return e interface{} 容器的顶部元素 225 | func (s *Stack) Top() (e interface{}) { 226 | if s == nil { 227 | return nil 228 | } 229 | if s.Empty() { 230 | return nil 231 | } 232 | s.mutex.Lock() 233 | e = s.data[s.top-1] 234 | s.mutex.Unlock() 235 | return e 236 | } 237 | -------------------------------------------------------------------------------- /data_structure/treap/node.go: -------------------------------------------------------------------------------- 1 | package treap 2 | //@Title Treap 3 | //@Description 4 | // 树堆的节点 5 | // 节点在创建是赋予一个随机的优先级,随后进行堆平衡,使得整个树堆依概率实现平衡 6 | // 可通过节点实现树堆的添加删除 7 | // 也可通过节点返回整个二叉搜索树的所有元素 8 | import ( 9 | "github.com/hlccd/goSTL/utils/comparator" 10 | "math/rand" 11 | ) 12 | 13 | //node树节点结构体 14 | //该节点是树堆的树节点 15 | //若该树堆允许重复则对节点num+1即可,否则对value进行覆盖 16 | //树堆节点将针对堆的性质通过左右旋转的方式做平衡 17 | type node struct { 18 | value interface{} //节点中存储的元素 19 | priority uint32 //该节点的优先级,随机生成 20 | num int //该节点中存储的数量 21 | left *node //左节点指针 22 | right *node //右节点指针 23 | } 24 | 25 | //@title newNode 26 | //@description 27 | // 新建一个树堆节点并返回 28 | // 将传入的元素e作为该节点的承载元素 29 | // 该节点的num默认为1,左右子节点设为nil 30 | // 该节点优先级随机生成,范围在0~2^16内 31 | //@receiver nil 32 | //@param e interface{} 承载元素e 33 | //@param rand *rand.Rand 随机数生成器 34 | //@return n *node 新建的树堆树节点的指针 35 | func newNode(e interface{}, rand *rand.Rand) (n *node) { 36 | return &node{ 37 | value: e, 38 | priority: uint32(rand.Intn(4294967295)), 39 | num: 1, 40 | left: nil, 41 | right: nil, 42 | } 43 | } 44 | 45 | //@title inOrder 46 | //@description 47 | // 以node树堆节点做接收者 48 | // 以中缀序列返回节点集合 49 | // 若允许重复存储则对于重复元素进行多次放入 50 | //@receiver n *node 接受者node的指针 51 | //@param nil 52 | //@return es []interface{} 以该节点为起点的中缀序列 53 | func (n *node) inOrder() (es []interface{}) { 54 | if n == nil { 55 | return es 56 | } 57 | if n.left != nil { 58 | es = append(es, n.left.inOrder()...) 59 | } 60 | for i := 0; i < n.num; i++ { 61 | es = append(es, n.value) 62 | } 63 | if n.right != nil { 64 | es = append(es, n.right.inOrder()...) 65 | } 66 | return es 67 | } 68 | 69 | 70 | //@title rightRotate 71 | //@description 72 | // 以node树堆节点做接收者 73 | // 新建一个节点作为n节点的右节点,同时将n节点的数值放入新建节点中作为右转后的n节点 74 | // 右转后的n节点的左节点是原n节点左节点的右节点,右转后的右节点保持不变 75 | // 原n节点改为原n节点的左节点,同时右节点指向新建的节点即右转后的n节点 76 | // 该右转方式可以保证n节点的双亲节点不用更换节点指向 77 | //@receiver n *node 接受者node的指针 78 | //@param nil 79 | //@return nil 80 | func (n *node) rightRotate() { 81 | if n == nil { 82 | return 83 | } 84 | if n.left == nil { 85 | return 86 | } 87 | //新建节点作为更换后的n节点 88 | tmp := &node{ 89 | value: n.value, 90 | priority: n.priority, 91 | num: n.num, 92 | left: n.left.right, 93 | right: n.right, 94 | } 95 | //原n节点左节点上移到n节点位置 96 | n.right = tmp 97 | n.value = n.left.value 98 | n.priority = n.left.priority 99 | n.num = n.left.num 100 | n.left = n.left.left 101 | } 102 | 103 | //@title leftRotate 104 | //@description 105 | // 以node树堆节点做接收者 106 | // 新建一个节点作为n节点的左节点,同时将n节点的数值放入新建节点中作为左转后的n节点 107 | // 左转后的n节点的右节点是原n节点右节点的左节点,左转后的左节点保持不变 108 | // 原n节点改为原n节点的右节点,同时左节点指向新建的节点即左转后的n节点 109 | // 该左转方式可以保证n节点的双亲节点不用更换节点指向 110 | //@receiver n *node 接受者node的指针 111 | //@param nil 112 | //@return nil 113 | func (n *node) leftRotate() { 114 | if n == nil { 115 | return 116 | } 117 | if n.right == nil { 118 | return 119 | } 120 | //新建节点作为更换后的n节点 121 | tmp := &node{ 122 | value: n.value, 123 | priority: n.priority, 124 | num: n.num, 125 | left: n.left, 126 | right: n.right.left, 127 | } 128 | //原n节点右节点上移到n节点位置 129 | n.left = tmp 130 | n.value = n.right.value 131 | n.priority = n.right.priority 132 | n.num = n.right.num 133 | n.right = n.right.right 134 | } 135 | 136 | //@title insert 137 | //@description 138 | // 以node二叉搜索树节点做接收者 139 | // 从n节点中插入元素e 140 | // 如果n节点中承载元素与e不同则根据大小从左右子树插入该元素 141 | // 如果n节点与该元素相等,且允许重复值,则将num+1否则对value进行覆盖 142 | // 插入成功返回true,插入失败或不允许重复插入返回false 143 | //@receiver n *node 接受者node的指针 144 | //@param e interface{} 待插入元素 145 | //@param isMulti bool 是否允许重复? 146 | //@param cmp comparator.Comparator 判断大小的比较器 147 | //@return b bool 是否插入成功? 148 | func (n *node) insert(e *node, isMulti bool, cmp comparator.Comparator) (b bool) { 149 | if cmp(n.value, e.value) > 0 { 150 | if n.left == nil { 151 | //将左节点直接设为e 152 | n.left = e 153 | b = true 154 | } else { 155 | //对左节点进行递归插入 156 | b = n.left.insert(e, isMulti, cmp) 157 | } 158 | if n.priority > e.priority { 159 | //对n节点进行右转 160 | n.rightRotate() 161 | } 162 | return b 163 | } else if cmp(n.value, e.value) < 0 { 164 | if n.right == nil { 165 | //将右节点直接设为e 166 | n.right = e 167 | b = true 168 | } else { 169 | //对右节点进行递归插入 170 | b = n.right.insert(e, isMulti, cmp) 171 | } 172 | if n.priority > e.priority { 173 | //对n节点进行左转 174 | n.leftRotate() 175 | } 176 | return b 177 | } 178 | if isMulti { 179 | //允许重复 180 | n.num++ 181 | return true 182 | } 183 | //不允许重复,对值进行覆盖 184 | n.value = e.value 185 | return false 186 | } 187 | 188 | //@title delete 189 | //@description 190 | // 以node二叉搜索树节点做接收者 191 | // 从n节点中删除元素e 192 | // 如果n节点中承载元素与e不同则根据大小从左右子树删除该元素 193 | // 如果n节点与该元素相等,且允许重复值,则将num-1否则直接删除该元素 194 | // 删除时先寻找该元素的前缀节点,若不存在则寻找其后继节点进行替换 195 | // 替换后删除该节点 196 | //@receiver n *node 接受者node的指针 197 | //@param e interface{} 待删除元素 198 | //@param isMulti bool 是否允许重复? 199 | //@param cmp comparator.Comparator 判断大小的比较器 200 | //@return b bool 是否删除成功? 201 | func (n *node) delete(e interface{}, isMulti bool, cmp comparator.Comparator) (b bool) { 202 | if n == nil { 203 | return false 204 | } 205 | //n中承载元素小于e,从右子树继续删除 206 | if cmp(n.value, e) < 0 { 207 | if n.right == nil { 208 | //右子树为nil,删除终止 209 | return false 210 | } 211 | if cmp(e, n.right.value) == 0 && (!isMulti || n.right.num == 1) { 212 | //待删除节点无子节点,直接删除即可 213 | if n.right.left == nil && n.right.right == nil { 214 | //右子树可直接删除 215 | n.right = nil 216 | return true 217 | } 218 | } 219 | //从右子树继续删除 220 | return n.right.delete(e, isMulti, cmp) 221 | } 222 | //n中承载元素大于e,从左子树继续删除 223 | if cmp(n.value, e) > 0 { 224 | if n.left == nil { 225 | //左子树为nil,删除终止 226 | return false 227 | } 228 | if cmp(e, n.left.value) == 0 && (!isMulti || n.left.num == 1) { 229 | //待删除节点无子节点,直接删除即可 230 | if n.left.left == nil && n.left.right == nil { 231 | //左子树可直接删除 232 | n.left = nil 233 | return true 234 | } 235 | } 236 | //从左子树继续删除 237 | return n.left.delete(e, isMulti, cmp) 238 | } 239 | if isMulti && n.num > 1 { 240 | //允许重复且数量超过1 241 | n.num-- 242 | return true 243 | } 244 | //删除该节点 245 | tmp := n 246 | //左右子节点都存在则选择优先级较小一个进行旋转 247 | for tmp.left != nil && tmp.right != nil { 248 | if tmp.left.priority < tmp.right.priority { 249 | tmp.rightRotate() 250 | if tmp.right.left == nil && tmp.right.right == nil { 251 | tmp.right = nil 252 | return false 253 | } 254 | tmp = tmp.right 255 | } else { 256 | tmp.leftRotate() 257 | if tmp.left.left == nil && tmp.left.right == nil { 258 | tmp.left = nil 259 | return false 260 | } 261 | tmp = tmp.left 262 | } 263 | } 264 | if tmp.left == nil && tmp.right != nil { 265 | //到左子树为nil时直接换为右子树即可 266 | tmp.value = tmp.right.value 267 | tmp.num = tmp.right.num 268 | tmp.priority = tmp.right.priority 269 | tmp.left = tmp.right.left 270 | tmp.right = tmp.right.right 271 | } else if tmp.right == nil && tmp.left != nil { 272 | //到右子树为nil时直接换为左子树即可 273 | tmp.value = tmp.left.value 274 | tmp.num = tmp.left.num 275 | tmp.priority = tmp.left.priority 276 | tmp.right = tmp.left.right 277 | tmp.left = tmp.left.left 278 | } 279 | //当左右子树都为nil时直接结束 280 | return true 281 | } 282 | 283 | //@title search 284 | //@description 285 | // 以node二叉搜索树节点做接收者 286 | // 从n节点中查找元素e并返回存储的个数 287 | // 如果n节点中承载元素与e不同则根据大小从左右子树查找该元素 288 | // 如果n节点与该元素相等,则直接返回其个数 289 | //@receiver n *node 接受者node的指针 290 | //@param e interface{} 待查找元素 291 | //@param isMulti bool 是否允许重复? 292 | //@param cmp comparator.Comparator 判断大小的比较器 293 | //@return num int 待查找元素在二叉树中存储的数量 294 | func (n *node) search(e interface{}, cmp comparator.Comparator) (num int) { 295 | if n == nil { 296 | return 0 297 | } 298 | if cmp(n.value, e) > 0 { 299 | return n.left.search(e, cmp) 300 | } else if cmp(n.value, e) < 0 { 301 | return n.right.search(e, cmp) 302 | } 303 | return n.num 304 | } -------------------------------------------------------------------------------- /data_structure/treap/treap.go: -------------------------------------------------------------------------------- 1 | package treap 2 | 3 | //@Title treap 4 | //@Description 5 | // Treap树堆容器包 6 | // 树堆本身是一个二叉树,同时赋予随机的节点优先级 7 | // 通过旋转使树堆中节点既满足存储元素的组成符合二叉搜索树的性质,同时也使得优先级满足堆的的性质 8 | // 同时由于每个节点的优先级随机生成,使得整个二叉树得以实现随机平衡 9 | // 该树堆依概率实现平衡 10 | // 可接纳不同类型的元素,但建议在同一个树堆中使用相同类型的元素 11 | // 配合比较器实现元素之间的大小比较 12 | 13 | import ( 14 | "github.com/hlccd/goSTL/utils/comparator" 15 | "github.com/hlccd/goSTL/utils/iterator" 16 | "math/rand" 17 | "sync" 18 | "time" 19 | ) 20 | 21 | //treap树堆结构体 22 | //该实例存储树堆的根节点 23 | //同时保存该树堆中已经存储了多少个元素 24 | //二叉树中排序使用的比较器在创建时传入,若不传入则在插入首个节点时从默认比较器中寻找 25 | //该树堆实例中存储随机数生成器,用于后续新建节点时生成随机数 26 | //创建时传入是否允许该树堆出现重复值,如果不允许则进行覆盖,允许则对节点数目增加即可 27 | type treap struct { 28 | root *node //根节点指针 29 | size int //存储元素数量 30 | cmp comparator.Comparator //比较器 31 | rand *rand.Rand //随机数生成器 32 | isMulti bool //是否允许重复 33 | mutex sync.Mutex //并发控制锁 34 | } 35 | 36 | //treap树堆容器接口 37 | //存放了treap树堆可使用的函数 38 | //对应函数介绍见下方 39 | type treaper interface { 40 | Iterator() (i *Iterator.Iterator) //返回包含该树堆的所有元素,重复则返回多个 41 | Size() (num int) //返回该树堆中保存的元素个数 42 | Clear() //清空该树堆 43 | Empty() (b bool) //判断该树堆是否为空 44 | Insert(e interface{}) //向树堆中插入元素e 45 | Erase(e interface{}) //从树堆中删除元素e 46 | Count(e interface{}) (num int) //从树堆中寻找元素e并返回其个数 47 | } 48 | 49 | //@title New 50 | //@description 51 | // 新建一个treap树堆容器并返回 52 | // 初始根节点为nil 53 | // 传入该树堆是否为可重复属性,如果为true则保存重复值,否则对原有相等元素进行覆盖 54 | // 若有传入的比较器,则将传入的第一个比较器设为该树堆的比较器 55 | //@receiver nil 56 | //@param isMulti bool 该树堆是否保存重复值? 57 | //@param Cmp ...comparator.Comparator treap比较器集 58 | //@return t *treap 新建的treap指针 59 | func New(isMulti bool, Cmp ...comparator.Comparator) (t *treap) { 60 | //设置默认比较器 61 | var cmp comparator.Comparator 62 | if len(Cmp) > 0 { 63 | cmp = Cmp[0] 64 | } 65 | //创建随机数生成器 66 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 67 | return &treap{ 68 | root: nil, 69 | size: 0, 70 | cmp: cmp, 71 | rand: r, 72 | isMulti: isMulti, 73 | mutex: sync.Mutex{}, 74 | } 75 | } 76 | 77 | //@title Iterator 78 | //@description 79 | // 以treap树堆做接收者 80 | // 将该树堆中所有保存的元素将从根节点开始以中缀序列的形式放入迭代器中 81 | // 若允许重复存储则对于重复元素进行多次放入 82 | //@receiver t *treap 接受者treap的指针 83 | //@param nil 84 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 85 | func (t *treap) Iterator() (i *Iterator.Iterator) { 86 | if t == nil { 87 | return nil 88 | } 89 | t.mutex.Lock() 90 | es := t.root.inOrder() 91 | i = Iterator.New(&es) 92 | t.mutex.Unlock() 93 | return i 94 | } 95 | 96 | //@title Size 97 | //@description 98 | // 以treap树堆做接收者 99 | // 返回该容器当前含有元素的数量 100 | // 如果容器为nil返回0 101 | //@receiver t *treap 接受者treap的指针 102 | //@param nil 103 | //@return num int 容器中实际使用元素所占空间大小 104 | func (t *treap) Size() (num int) { 105 | if t == nil { 106 | return 0 107 | } 108 | return t.size 109 | } 110 | //@title Clear 111 | //@description 112 | // 以treap树堆做接收者 113 | // 将该容器中所承载的元素清空 114 | // 将该容器的size置0 115 | //@receiver t *treap 接受者treap的指针 116 | //@param nil 117 | //@return nil 118 | func (t *treap) Clear() { 119 | if t == nil { 120 | return 121 | } 122 | t.mutex.Lock() 123 | t.root = nil 124 | t.size = 0 125 | t.mutex.Unlock() 126 | } 127 | //@title Empty 128 | //@description 129 | // 以treap树堆做接收者 130 | // 判断该二叉搜索树是否含有元素 131 | // 如果含有元素则不为空,返回false 132 | // 如果不含有元素则说明为空,返回true 133 | // 如果容器不存在,返回true 134 | //@receiver t *treap 接受者treap的指针 135 | //@param nil 136 | //@return b bool 该容器是空的吗? 137 | func (t *treap) Empty() (b bool) { 138 | if t == nil { 139 | return true 140 | } 141 | if t.size > 0 { 142 | return false 143 | } 144 | return true 145 | } 146 | 147 | //@title Insert 148 | //@description 149 | // 以treap树堆做接收者 150 | // 向二叉树插入元素e,若不允许重复则对相等元素进行覆盖 151 | // 如果二叉树为空则之间用根节点承载元素e,否则以根节点开始进行查找 152 | // 对于该树堆来说,通过赋予随机的优先级根据堆的性质来实现平衡 153 | //@receiver t *treap 接受者treap的指针 154 | //@param e interface{} 待插入元素 155 | //@return nil 156 | func (t *treap) Insert(e interface{}) { 157 | //判断容器是否存在 158 | if t == nil { 159 | return 160 | } 161 | t.mutex.Lock() 162 | if t.Empty() { 163 | //判断比较器是否存在 164 | if t.cmp == nil { 165 | t.cmp = comparator.GetCmp(e) 166 | } 167 | if t.cmp == nil { 168 | t.mutex.Unlock() 169 | return 170 | } 171 | //插入到根节点 172 | t.root = newNode(e, t.rand) 173 | t.size = 1 174 | t.mutex.Unlock() 175 | return 176 | } 177 | //从根节点向下插入 178 | if t.root.insert(newNode(e, t.rand), t.isMulti, t.cmp) { 179 | t.size++ 180 | } 181 | t.mutex.Unlock() 182 | } 183 | 184 | 185 | //@title Erase 186 | //@description 187 | // 以treap树堆做接收者 188 | // 从树堆中删除元素e 189 | // 若允许重复记录则对承载元素e的节点中数量记录减一即可 190 | // 若不允许重复记录则删除该节点同时将前缀节点或后继节点更换过来以保证树堆的不发送断裂 191 | // 交换后根据优先级进行左右旋转以保证符合堆的性质 192 | // 如果该树堆仅持有一个元素且根节点等价于待删除元素,则将根节点置为nil 193 | //@receiver t *treap 接受者treap的指针 194 | //@param e interface{} 待删除元素 195 | //@return nil 196 | func (t *treap) Erase(e interface{}) { 197 | if t == nil { 198 | return 199 | } 200 | if t.Empty() { 201 | return 202 | } 203 | t.mutex.Lock() 204 | if t.size == 1 && t.cmp(t.root.value, e) == 0 { 205 | //该树堆仅持有一个元素且根节点等价于待删除元素,则将根节点置为nil 206 | t.root = nil 207 | t.size = 0 208 | t.mutex.Unlock() 209 | return 210 | } 211 | //从根节点开始删除元素 212 | if t.root.delete(e, t.isMulti, t.cmp) { 213 | //删除成功 214 | t.size-- 215 | } 216 | t.mutex.Unlock() 217 | } 218 | 219 | //@title Count 220 | //@description 221 | // 以treap树堆做接收者 222 | // 从树堆中查找元素e的个数 223 | // 如果找到则返回该树堆中和元素e相同元素的个数 224 | // 如果不允许重复则最多返回1 225 | // 如果未找到则返回0 226 | //@receiver t *treap 接受者treap的指针 227 | //@param e interface{} 待查找元素 228 | //@return num int 待查找元素在树堆中存储的个数 229 | func (t *treap) Count(e interface{}) (num int) { 230 | if t == nil { 231 | //树堆不存在,直接返回0 232 | return 0 233 | } 234 | if t.Empty() { 235 | return 236 | } 237 | t.mutex.Lock() 238 | num = t.root.search(e, t.cmp) 239 | t.mutex.Unlock() 240 | //树堆存在,从根节点开始查找该元素 241 | return num 242 | } -------------------------------------------------------------------------------- /data_structure/trie/node.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | //@Title trie 4 | //@Description 5 | // 单词查找树的节点 6 | // 可通过节点的分叉对string进行查找 7 | // 增添string时候只需要增删结点即可 8 | // 当string到终点时存储元素 9 | 10 | //node树节点结构体 11 | //该节点是trie的树节点 12 | //结点存储到此时的string的前缀数量 13 | //以son为分叉存储下属的string 14 | //该节点同时存储其元素 15 | type node struct { 16 | num int //以当前结点为前缀的string的数量 17 | son [64]*node //分叉 18 | value interface{} //当前结点承载的元素 19 | } 20 | 21 | //@title newNode 22 | //@description 23 | // 新建一个单词查找树节点并返回 24 | // 将传入的元素e作为该节点的承载元素 25 | //@receiver nil 26 | //@param e interface{} 承载元素e 27 | //@return n *node 新建的单词查找树节点的指针 28 | func newNode(e interface{}) (n *node) { 29 | return &node{ 30 | num: 0, 31 | value: e, 32 | } 33 | } 34 | 35 | //@title inOrder 36 | //@description 37 | // 以node单词查找树节点做接收者 38 | // 遍历其分叉以找到其存储的所有string 39 | //@receiver n *node 接受者node的指针 40 | //@param s string 到该结点时的前缀string 41 | //@return es []interface{} 以该前缀s为前缀的所有string的集合 42 | func (n *node) inOrder(s string) (es []interface{}) { 43 | if n == nil { 44 | return es 45 | } 46 | if n.value != nil { 47 | es = append(es, s) 48 | } 49 | for i, p := 0, 0; i < 62 && p < n.num; i++ { 50 | if n.son[i] != nil { 51 | if i < 26 { 52 | es = append(es, n.son[i].inOrder(s+string(i+'a'))...) 53 | } else if i < 52 { 54 | es = append(es, n.son[i].inOrder(s+string(i-26+'A'))...) 55 | } else { 56 | es = append(es, n.son[i].inOrder(s+string(i-52+'0'))...) 57 | } 58 | p++ 59 | } 60 | } 61 | return es 62 | } 63 | 64 | //@title getIdx 65 | //@description 66 | // 传入一个byte并根据其值返回其映射到分叉的值 67 | // 当不属于'a'~'z','A'~'Z','0'~'9','+','/'时返回-1 68 | //@receiver nil 69 | //@param c byte 待映射的ASCII码 70 | //@return idx int 以c映射出的分叉下标 71 | func getIdx(c byte) (idx int) { 72 | if c >= 'a' && c <= 'z' { 73 | idx = int(c - 'a') 74 | } else if c >= 'A' && c <= 'Z' { 75 | idx = int(c-'A') + 26 76 | } else if c >= '0' && c <= '9' { 77 | idx = int(c-'0') + 52 78 | } else if c == '+' { 79 | idx = 62 80 | } else if c == '/' { 81 | idx = 63 82 | } else { 83 | idx = -1 84 | } 85 | return idx 86 | } 87 | 88 | //@title insert 89 | //@description 90 | // 以node单词查找树节点做接收者 91 | // 从n节点中继续插入以s为索引的元素e,且当前抵达的string位置为p 92 | // 当到达s终点时进行插入,如果此时node承载了元素则插入失败,否则成功 93 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可 94 | //@receiver n *node 接受者node的指针 95 | //@param s string 待插入元素的索引s 96 | //@param p int 索引当前抵达的位置 97 | //@param e interface{} 待插入元素e 98 | //@return b bool 是否插入成功? 99 | func (n *node) insert(s string, p int, e interface{}) (b bool) { 100 | if p == len(s) { 101 | if n.value != nil { 102 | return false 103 | } 104 | n.value = e 105 | n.num++ 106 | return true 107 | } 108 | idx := getIdx(s[p]) 109 | if idx == -1 { 110 | return false 111 | } 112 | ok := true 113 | if n.son[idx] == nil { 114 | //判断该子结点是否存在 115 | n.son[idx] = newNode(nil) 116 | ok = false 117 | } 118 | b = n.son[idx].insert(s, p+1, e) 119 | if b { 120 | n.num++ 121 | } else { 122 | if !ok { 123 | //插入失败且该子节点为新建结点则需要删除该子结点 124 | n.son[idx] = nil 125 | } 126 | } 127 | return b 128 | } 129 | 130 | //@title erase 131 | //@description 132 | // 以node单词查找树节点做接收者 133 | // 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p 134 | // 当到达s终点时进行删除,如果此时node未承载元素则删除失败,否则成功 135 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接失败 136 | //@receiver n *node 接受者node的指针 137 | //@param s string 待删除元素的索引s 138 | //@param p int 索引当前抵达的位置 139 | //@return b bool 是否删除成功? 140 | func (n *node) erase(s string, p int) (b bool) { 141 | if p == len(s) { 142 | if n.value != nil { 143 | n.value = nil 144 | n.num-- 145 | return true 146 | } 147 | return false 148 | } 149 | idx := getIdx(s[p]) 150 | if idx == -1 { 151 | return false 152 | } 153 | if n.son[idx] == nil { 154 | return false 155 | } 156 | b = n.son[idx].erase(s, p+1) 157 | if b { 158 | n.num-- 159 | if n.son[idx].num == 0 { 160 | n.son[idx] = nil 161 | } 162 | } 163 | return b 164 | } 165 | 166 | //@title delete 167 | //@description 168 | // 以node单词查找树节点做接收者 169 | // 从n节点中继续删除以s为索引的元素e,且当前抵达的string位置为p 170 | // 当到达s终点时进行删除,删除所有后续元素,并返回其后续元素的数量 171 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,若其分叉为nil则直接返回0 172 | //@receiver n *node 接受者node的指针 173 | //@param s string 待删除元素的索引s 174 | //@param p int 索引当前抵达的位置 175 | //@return num int 被删除元素的数量 176 | func (n *node) delete(s string, p int) (num int) { 177 | if p == len(s) { 178 | return n.num 179 | } 180 | idx := getIdx(s[p]) 181 | if idx == -1 { 182 | return 0 183 | } 184 | if n.son[idx] == nil { 185 | return 0 186 | } 187 | num = n.son[idx].delete(s, p+1) 188 | if num > 0 { 189 | n.num -= num 190 | if n.son[idx].num <= 0 { 191 | n.son[idx] = nil 192 | } 193 | } 194 | return num 195 | } 196 | 197 | //@title count 198 | //@description 199 | // 以node单词查找树节点做接收者 200 | // 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p 201 | // 当到达s终点时返回其值即可 202 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回0 203 | //@receiver n *node 接受者node的指针 204 | //@param s string 待查找元素的前缀索引 205 | //@param p int 索引当前抵达的位置 206 | //@return num int 以该s为前缀的string的数量 207 | func (n *node) count(s string, p int) (num int) { 208 | if p == len(s) { 209 | return n.num 210 | } 211 | idx := getIdx(s[p]) 212 | if idx == -1 { 213 | return 0 214 | } 215 | if n.son[idx] == nil { 216 | return 0 217 | } 218 | return n.son[idx].count(s, p+1) 219 | } 220 | 221 | //@title find 222 | //@description 223 | // 以node单词查找树节点做接收者 224 | // 从n节点中继续查找以s为前缀索引的元素e,且当前抵达的string位置为p 225 | // 当到达s终点时返回其承载的元素即可 226 | // 当未到达终点时,根据当前抵达的位置去寻找其子结点继续遍历即可,当其分叉为nil则直接返回nil 227 | //@receiver n *node 接受者node的指针 228 | //@param s string 待查找元素的前缀索引 229 | //@param p int 索引当前抵达的位置 230 | //@return e interface{} 该索引所指向的元素e 231 | func (n *node) find(s string, p int) (e interface{}) { 232 | if p == len(s) { 233 | return n.value 234 | } 235 | idx := getIdx(s[p]) 236 | if idx == -1 { 237 | return nil 238 | } 239 | if n.son[idx] == nil { 240 | return nil 241 | } 242 | return n.son[idx].find(s, p+1) 243 | } 244 | -------------------------------------------------------------------------------- /data_structure/trie/trie.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | //@Title trie 4 | //@Description 5 | // 单词查找树-Trie 6 | // 以多叉树的形式实现,本次实现中有64叉,即a~z,A~Z,0~9,'+','/'共64个,对应base64的字符 7 | // 当存储的string中出现其他字符则无法存储 8 | // 存储的string可以携带一个元素 9 | // 结点不允许覆盖,即插入值已经存在时会插入失败,需要先删除原值 10 | // 使用互斥锁实现并发控制 11 | 12 | import ( 13 | "github.com/hlccd/goSTL/utils/iterator" 14 | "sync" 15 | ) 16 | 17 | //trie单词查找树结构体 18 | //该实例存储单词查找树的根节点 19 | //同时保存该树已经存储了多少个元素 20 | //整个树不允许重复插入,若出现重复插入则直接失败 21 | type trie struct { 22 | root *node //根节点指针 23 | size int //存放的元素数量 24 | mutex sync.Mutex //并发控制锁 25 | } 26 | 27 | //trie单词查找树容器接口 28 | //存放了trie单词查找树可使用的函数 29 | //对应函数介绍见下方 30 | type trieer interface { 31 | Iterator() (i *Iterator.Iterator) //返回包含该trie的所有string 32 | Size() (num int) //返回该trie中保存的元素个数 33 | Clear() //清空该trie 34 | Empty() (b bool) //判断该trie是否为空 35 | Insert(s string, e interface{}) (b bool) //向trie中插入string并携带元素e 36 | Erase(s string) (b bool) //从trie中删除以s为索引的元素e 37 | Delete(s string) (num int) //从trie中删除以s为前缀的所有元素 38 | Count(s string) (num int) //从trie中寻找以s为前缀的string单词数 39 | Find(s string) (e interface{}) //从trie中寻找以s为索引的元素e 40 | } 41 | 42 | //@title New 43 | //@description 44 | // 新建一个trie单词查找树容器并返回 45 | // 初始根节点为nil 46 | //@receiver nil 47 | //@param nil 48 | //@return t *trie 新建的trie指针 49 | func New() (t *trie) { 50 | return &trie{ 51 | root: newNode(nil), 52 | size: 0, 53 | mutex: sync.Mutex{}, 54 | } 55 | } 56 | 57 | //@title Iterator 58 | //@description 59 | // 以trie单词查找树做接收者 60 | // 将该trie中所有存放的string放入迭代器中并返回 61 | //@receiver t *trie 接受者trie的指针 62 | //@param nil 63 | //@return i *iterator.Iterator 新建的Iterator迭代器指针 64 | func (t *trie) Iterator() (i *Iterator.Iterator) { 65 | if t == nil { 66 | return nil 67 | } 68 | t.mutex.Lock() 69 | //找到trie中存在的所有string 70 | es := t.root.inOrder("") 71 | i = Iterator.New(&es) 72 | t.mutex.Unlock() 73 | return i 74 | } 75 | 76 | //@title Size 77 | //@description 78 | // 以trie单词查找树做接收者 79 | // 返回该容器当前含有元素的数量 80 | // 如果容器为nil返回0 81 | //@receiver t *trie 接受者trie的指针 82 | //@param nil 83 | //@return num int 容器中实际使用元素所占空间大小 84 | func (t *trie) Size() (num int) { 85 | if t == nil { 86 | return 0 87 | } 88 | return t.size 89 | } 90 | 91 | //@title Clear 92 | //@description 93 | // 以trie单词查找树做接收者 94 | // 将该容器中所承载的元素清空 95 | // 将该容器的size置0 96 | //@receiver t *trie 接受者trie的指针 97 | //@param nil 98 | //@return nil 99 | func (t *trie) Clear() { 100 | if t == nil { 101 | return 102 | } 103 | t.mutex.Lock() 104 | t.root = newNode(nil) 105 | t.size = 0 106 | t.mutex.Unlock() 107 | } 108 | 109 | //@title Empty 110 | //@description 111 | // 以trie单词查找树做接收者 112 | // 判断该trie是否含有元素 113 | // 如果含有元素则不为空,返回false 114 | // 如果不含有元素则说明为空,返回true 115 | // 如果容器不存在,返回true 116 | //@receiver t *trie 接受者trie的指针 117 | //@param nil 118 | //@return b bool 该容器是空的吗? 119 | func (t *trie) Empty() (b bool) { 120 | if t == nil { 121 | return true 122 | } 123 | return t.size == 0 124 | } 125 | 126 | //@title Insert 127 | //@description 128 | // 以trie单词查找树做接收者 129 | // 向trie插入以string类型的s为索引的元素e 130 | // 若存在重复的s则插入失败,不允许覆盖 131 | // 否则插入成功 132 | //@receiver t *trie 接受者trie的指针 133 | //@param s string 待插入元素的索引s 134 | //@param e interface{} 待插入元素e 135 | //@return b bool 添加成功? 136 | func (t *trie) Insert(s string, e interface{}) (b bool) { 137 | if t == nil { 138 | return 139 | } 140 | if len(s) == 0 { 141 | return false 142 | } 143 | t.mutex.Lock() 144 | if t.root == nil { 145 | //避免根节点为nil 146 | t.root = newNode(nil) 147 | } 148 | //从根节点开始插入 149 | b = t.root.insert(s, 0, e) 150 | if b { 151 | //插入成功,size+1 152 | t.size++ 153 | } 154 | t.mutex.Unlock() 155 | return b 156 | } 157 | 158 | //@title Erase 159 | //@description 160 | // 以trie单词查找树做接收者 161 | // 从trie树中删除元素以s为索引的元素e 162 | //@receiver t *trie 接受者trie的指针 163 | //@param s string 待删除元素的索引 164 | //@return b bool 删除成功? 165 | func (t *trie) Erase(s string) (b bool) { 166 | if t == nil { 167 | return false 168 | } 169 | if t.Empty() { 170 | return false 171 | } 172 | if len(s) == 0 { 173 | //长度为0无法删除 174 | return false 175 | } 176 | if t.root == nil { 177 | //根节点为nil即无法删除 178 | return false 179 | } 180 | t.mutex.Lock() 181 | //从根节点开始删除 182 | b = t.root.erase(s, 0) 183 | if b { 184 | //删除成功,size-1 185 | t.size-- 186 | if t.size == 0 { 187 | //所有string都被删除,根节点置为nil 188 | t.root = nil 189 | } 190 | } 191 | t.mutex.Unlock() 192 | return b 193 | } 194 | 195 | //@title Delete 196 | //@description 197 | // 以trie单词查找树做接收者 198 | // 从trie树中删除以s为前缀的所有元素 199 | //@receiver t *trie 接受者trie的指针 200 | //@param s string 待删除元素的前缀 201 | //@return num int 被删除的元素的数量 202 | func (t *trie) Delete(s string) (num int) { 203 | if t == nil { 204 | return 0 205 | } 206 | if t.Empty() { 207 | return 0 208 | } 209 | if len(s) == 0 { 210 | //长度为0无法删除 211 | return 0 212 | } 213 | if t.root == nil { 214 | //根节点为nil即无法删除 215 | return 0 216 | } 217 | t.mutex.Lock() 218 | //从根节点开始删除 219 | num = t.root.delete(s, 0) 220 | if num > 0 { 221 | //删除成功 222 | t.size -= num 223 | if t.size <= 0 { 224 | //所有string都被删除,根节点置为nil 225 | t.root = nil 226 | } 227 | } 228 | t.mutex.Unlock() 229 | return num 230 | } 231 | 232 | //@title Count 233 | //@description 234 | // 以trie单词查找树做接收者 235 | // 从trie中查找以s为前缀的所有string的个数 236 | // 如果存在以s为前缀的则返回大于0的值即其数量 237 | // 如果未找到则返回0 238 | //@receiver t *trie 接受者trie的指针 239 | //@param s string 待查找的前缀s 240 | //@return num int 待查找前缀在trie树中存在的数量 241 | func (t *trie) Count(s string) (num int) { 242 | if t == nil { 243 | return 0 244 | } 245 | if t.Empty() { 246 | return 0 247 | } 248 | if t.root == nil { 249 | return 0 250 | } 251 | t.mutex.Lock() 252 | //统计所有以s为前缀的string的数量并返回 253 | num = int(t.root.count(s, 0)) 254 | t.mutex.Unlock() 255 | return num 256 | } 257 | 258 | //@title Find 259 | //@description 260 | // 以trie单词查找树做接收者 261 | // 从trie中查找以s为索引的元素e,找到则返回e 262 | // 如果未找到则返回nil 263 | //@receiver t *trie 接受者trie的指针 264 | //@param s string 待查找索引s 265 | //@return ans interface{} 待查找索引所指向的元素 266 | func (t *trie) Find(s string) (e interface{}) { 267 | if t == nil { 268 | return nil 269 | } 270 | if t.Empty() { 271 | return nil 272 | } 273 | if t.root == nil { 274 | return nil 275 | } 276 | t.mutex.Lock() 277 | //从根节点开始查找以s为索引的元素e 278 | e = t.root.find(s, 0) 279 | t.mutex.Unlock() 280 | return e 281 | } 282 | -------------------------------------------------------------------------------- /utils/comparator/bound.go: -------------------------------------------------------------------------------- 1 | package comparator 2 | 3 | //@Title comparator 4 | //@Description 5 | // 可查找有序序列中某一元素的上界和下届 6 | // 当该元素存在时,上界和下届返回的下标位置指向该元素 7 | // 当该元素不存在时,上界和下届指向下标错位且指向位置并非该元素 8 | 9 | //@title UpperBound 10 | //@description 11 | // 通过传入的比较函数对待查找数组进行查找以获取待查找元素的上界即不大于它的最大值的下标 12 | // 以传入的比较函数进行比较 13 | // 如果该元素存在,则上界指向元素为该元素 14 | // 如果该元素不存在,上界指向元素为该元素的前一个元素 15 | //@receiver nil 16 | //@param arr *[]interface{} 待查找数组 17 | //@param e interface{} 待查找元素 18 | //@param Cmp ...Comparator 比较函数 19 | //@return idx int 待查找元素的上界 20 | func UpperBound(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { 21 | if arr==nil || (*arr)==nil || len((*arr)) == 0 { 22 | return -1 23 | } 24 | //判断比较函数是否有效 25 | var cmp Comparator 26 | cmp = nil 27 | if len(Cmp) == 0 { 28 | cmp = GetCmp(e) 29 | } else { 30 | cmp = Cmp[0] 31 | } 32 | if cmp == nil { 33 | return -1 34 | } 35 | //寻找该元素的上界 36 | return upperBound(arr, e, cmp) 37 | } 38 | 39 | //@title upperBound 40 | //@description 41 | // 通过传入的比较函数对待查找数组进行查找以获取待查找元素的上界即不大于它的最大值的下标 42 | // 以传入的比较函数进行比较 43 | // 如果该元素存在,则上界指向元素为该元素,且为最右侧 44 | // 如果该元素不存在,上界指向元素为该元素的前一个元素 45 | // 以二分查找的方式寻找该元素的上界 46 | //@receiver nil 47 | //@param arr *[]interface{} 待查找数组 48 | //@param e interface{} 待查找元素 49 | //@param Cmp ...Comparator 比较函数 50 | //@return idx int 待查找元素的上界 51 | func upperBound(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { 52 | l, m, r := 0, len((*arr)) / 2, len((*arr))-1 53 | for l < r { 54 | m = (l + r + 1) / 2 55 | if cmp((*arr)[m], e) <= 0 { 56 | l = m 57 | } else { 58 | r = m - 1 59 | } 60 | } 61 | return l 62 | } 63 | 64 | //@title LowerBound 65 | //@description 66 | // 通过传入的比较函数对待查找数组进行查找以获取待查找元素的下界即不小于它的最小值的下标 67 | // 以传入的比较函数进行比较 68 | // 如果该元素存在,则上界指向元素为该元素 69 | // 如果该元素不存在,上界指向元素为该元素的后一个元素 70 | //@receiver nil 71 | //@param arr *[]interface{} 待查找数组 72 | //@param e interface{} 待查找元素 73 | //@param Cmp ...Comparator 比较函数 74 | //@return idx int 待查找元素的下界 75 | func LowerBound(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { 76 | if arr==nil || (*arr)==nil || len((*arr)) == 0 { 77 | return -1 78 | } 79 | //判断比较函数是否有效 80 | var cmp Comparator 81 | cmp = nil 82 | if len(Cmp) == 0 { 83 | cmp = GetCmp(e) 84 | } else { 85 | cmp = Cmp[0] 86 | } 87 | if cmp == nil { 88 | return -1 89 | } 90 | //寻找该元素的下界 91 | return lowerBound(arr, e, cmp) 92 | } 93 | 94 | //@title lowerBound 95 | //@description 96 | // 通过传入的比较函数对待查找数组进行查找以获取待查找元素的下界即不小于它的最小值的下标 97 | // 以传入的比较函数进行比较 98 | // 如果该元素存在,则上界指向元素为该元素,且为最右侧 99 | // 如果该元素不存在,上界指向元素为该元素的后一个元素 100 | //@receiver nil 101 | //@param arr *[]interface{} 待查找数组 102 | //@param e interface{} 待查找元素 103 | //@param Cmp ...Comparator 比较函数 104 | //@return idx int 待查找元素的下界 105 | func lowerBound(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { 106 | l, m, r := 0, len((*arr)) / 2, len((*arr)) 107 | for l < r { 108 | m = (l + r) / 2 109 | if cmp((*arr)[m], e) >= 0 { 110 | r = m 111 | } else { 112 | l = m + 1 113 | } 114 | } 115 | return l 116 | } 117 | -------------------------------------------------------------------------------- /utils/comparator/comparator.go: -------------------------------------------------------------------------------- 1 | package comparator 2 | 3 | //@Title comparator 4 | //@Description 5 | // 比较器 6 | // 定义了一个比较器类型,该类型可传入两个泛型并返回一个整数判断大小 7 | // 该比较器用于定义的数据结构中传入数据之间的比较 8 | // 该包内定义了一些自带类型的比较类型 9 | // 当使用自定义的数据结构时若不进行比较器的传入则使用默认比较器 10 | // 若传入类型非系统自带类型,则返回空比较器同时对数据的传入失败 11 | 12 | // 比较器将会返回数字num 13 | // num > 0 ,if a > b 14 | // num = 0 ,if a = b 15 | // num < 0 ,if a < b 16 | 17 | type Comparator func(a, b interface{}) int 18 | 19 | //比较器的特种——相等器 20 | //判断传入的两个元素是否相等 21 | type Equaler func(a, b interface{}) (B bool) 22 | 23 | //@title GetCmp 24 | //@description 25 | // 传入一个数据并根据该数据类型返回一个对应的比较器 26 | // 若该类型并非系统自带类型,则返回个空比较器 27 | // 若传入元素为nil则之间返回nil 28 | //@receiver nil 29 | //@param e interface{} 30 | //@return cmp Comparator 该类型对应的默认比较器 31 | func GetCmp(e interface{}) (cmp Comparator) { 32 | if e == nil { 33 | return nil 34 | } 35 | switch e.(type) { 36 | case bool: 37 | return boolCmp 38 | case int: 39 | return intCmp 40 | case int8: 41 | return int8Cmp 42 | case uint8: 43 | return uint8Cmp 44 | case int16: 45 | return int16Cmp 46 | case uint16: 47 | return uint16Cmp 48 | case int32: 49 | return int32Cmp 50 | case uint32: 51 | return uint32Cmp 52 | case int64: 53 | return int64Cmp 54 | case uint64: 55 | return uint64Cmp 56 | case float32: 57 | return float32Cmp 58 | case float64: 59 | return float64Cmp 60 | case complex64: 61 | return complex64Cmp 62 | case complex128: 63 | return complex128Cmp 64 | case string: 65 | return stringCmp 66 | } 67 | return nil 68 | } 69 | 70 | //@title GetEqual 71 | //@description 72 | // 传入一个数据并根据该数据类型返回一个对应的比较器 73 | // 若该类型并非系统自带类型,则返回个空比较器 74 | // 若传入元素为nil则之间返回nil 75 | //@receiver nil 76 | //@param e interface{} 77 | //@return cmp Comparator 该类型对应的默认比较器 78 | func GetEqual() (equ Equaler) { 79 | return basicEqual 80 | } 81 | 82 | //@title basicEqual 83 | //@description 84 | // 返回基本比较器 85 | // 即有且仅有判断量元素是否完全相等 86 | //@receiver a interface{} 待判断相等的第一个元素 87 | //@receiver b interface{} 待判断相等的第二个元素 88 | //@param nil 89 | //@return B bool 这两个元素是否相等? 90 | func basicEqual(a, b interface{}) (B bool) { 91 | return a == b 92 | } 93 | 94 | //以下为系统自带类型的默认比较器 95 | 96 | func boolCmp(a, b interface{}) int { 97 | if a == b { 98 | return 0 99 | } 100 | if a.(bool) { 101 | return 1 102 | } else if b.(bool) { 103 | return -1 104 | } 105 | return 0 106 | } 107 | func intCmp(a, b interface{}) int { 108 | if a == b { 109 | return 0 110 | } 111 | if a.(int) > b.(int) { 112 | return 1 113 | } else if a.(int) < b.(int) { 114 | return -1 115 | } 116 | return 0 117 | } 118 | func int8Cmp(a, b interface{}) int { 119 | if a == b { 120 | return 0 121 | } 122 | if a.(int8) > b.(int8) { 123 | return 1 124 | } else if a.(int8) < b.(int8) { 125 | return -1 126 | } 127 | return 0 128 | } 129 | func uint8Cmp(a, b interface{}) int { 130 | if a == b { 131 | return 0 132 | } 133 | if a.(uint8) > b.(uint8) { 134 | return 1 135 | } else if a.(uint8) < b.(uint8) { 136 | return -1 137 | } 138 | return 0 139 | } 140 | func int16Cmp(a, b interface{}) int { 141 | if a == b { 142 | return 0 143 | } 144 | if a.(int16) > b.(int16) { 145 | return 1 146 | } else if a.(int16) < b.(int16) { 147 | return -1 148 | } 149 | return 0 150 | } 151 | func uint16Cmp(a, b interface{}) int { 152 | if a == b { 153 | return 0 154 | } 155 | if a.(uint16) > b.(uint16) { 156 | return 1 157 | } else if a.(uint16) < b.(uint16) { 158 | return -1 159 | } 160 | return 0 161 | } 162 | func int32Cmp(a, b interface{}) int { 163 | if a == b { 164 | return 0 165 | } 166 | if a.(int32) > b.(int32) { 167 | return 1 168 | } else if a.(int32) < b.(int32) { 169 | return -1 170 | } 171 | return 0 172 | } 173 | func uint32Cmp(a, b interface{}) int { 174 | if a == b { 175 | return 0 176 | } 177 | if a.(uint32) > b.(uint32) { 178 | return 1 179 | } else if a.(uint32) < b.(uint32) { 180 | return -1 181 | } 182 | return 0 183 | } 184 | func int64Cmp(a, b interface{}) int { 185 | if a == b { 186 | return 0 187 | } 188 | if a.(int64) > b.(int64) { 189 | return 1 190 | } else if a.(int64) < b.(int64) { 191 | return -1 192 | } 193 | return 0 194 | } 195 | func uint64Cmp(a, b interface{}) int { 196 | if a == b { 197 | return 0 198 | } 199 | if a.(uint64) > b.(uint64) { 200 | return 1 201 | } else if a.(uint64) < b.(uint64) { 202 | return -1 203 | } 204 | return 0 205 | } 206 | func float32Cmp(a, b interface{}) int { 207 | if a == b { 208 | return 0 209 | } 210 | if a.(float32) > b.(float32) { 211 | return 1 212 | } else if a.(float32) < b.(float32) { 213 | return -1 214 | } 215 | return 0 216 | } 217 | func float64Cmp(a, b interface{}) int { 218 | if a == b { 219 | return 0 220 | } 221 | if a.(float64) > b.(float64) { 222 | return 1 223 | } else if a.(float64) < b.(float64) { 224 | return -1 225 | } 226 | return 0 227 | } 228 | func complex64Cmp(a, b interface{}) int { 229 | if a == b { 230 | return 0 231 | } 232 | if real(a.(complex64)) > real(b.(complex64)) { 233 | return 1 234 | } else if real(a.(complex64)) < real(b.(complex64)) { 235 | return -1 236 | } else { 237 | if imag(a.(complex64)) > imag(b.(complex64)) { 238 | return 1 239 | } else if imag(a.(complex64)) < imag(b.(complex64)) { 240 | return -1 241 | } 242 | } 243 | return 0 244 | } 245 | func complex128Cmp(a, b interface{}) int { 246 | if a == b { 247 | return 0 248 | } 249 | if real(a.(complex128)) > real(b.(complex128)) { 250 | return 1 251 | } else if real(a.(complex128)) < real(b.(complex128)) { 252 | return -1 253 | } else { 254 | if imag(a.(complex128)) > imag(b.(complex128)) { 255 | return 1 256 | } else if imag(a.(complex128)) < imag(b.(complex128)) { 257 | return -1 258 | } 259 | } 260 | return 0 261 | } 262 | func stringCmp(a, b interface{}) int { 263 | if a == b { 264 | return 0 265 | } 266 | if len(a.(string)) > len(b.(string)) { 267 | return 1 268 | } else if len(a.(string)) < len(b.(string)) { 269 | return -1 270 | } else { 271 | if a.(string) > b.(string) { 272 | return 1 273 | } else if a.(string) < b.(string) { 274 | return -1 275 | } 276 | } 277 | return 0 278 | } 279 | -------------------------------------------------------------------------------- /utils/comparator/nth_element.go: -------------------------------------------------------------------------------- 1 | package comparator 2 | 3 | //@Title comparator 4 | //@Description 5 | // 该包内通过利用比较函数重排传入的数组,使得下标为n的元素必然是第n+1大的(考虑到下标从0开始) 6 | // 对二分排序的变形,当只对该节点位置存在的某一局部进行查找即可 7 | 8 | //@title NthElement 9 | //@description 10 | // 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 11 | // 通过利用比较函数重排传入的数组,使得下标为n的元素必然是第n+1大的(考虑到下标从0开始) 12 | // 若n大于数组长度,直接结束,否则对第n+1大的元素排序后返回该元素 13 | //@receiver nil 14 | //@param begin *[]interface{} 待查找的元素数组指针 15 | //@param n int 待查找的是第n位,从0计数 16 | //@param Cmp ...Comparator 比较函数 17 | //@return value interface{} 第n+1大的元素 18 | func NthElement(arr *[]interface{}, n int, Cmp ...Comparator) (value interface{}){ 19 | if arr==nil || (*arr)==nil || len((*arr)) == 0 { 20 | return nil 21 | } 22 | //判断比较函数是否有效 23 | var cmp Comparator 24 | cmp = nil 25 | if len(Cmp) > 0 { 26 | cmp = Cmp[0] 27 | } else { 28 | cmp = GetCmp((*arr)[0]) 29 | } 30 | if cmp == nil { 31 | return nil 32 | } 33 | //判断待确认的第n位是否在该集合范围内 34 | if len((*arr)) < n || n<0 { 35 | return nil 36 | } 37 | //进行查找 38 | nthElement(arr,0,len((*arr))-1, n, cmp) 39 | return (*arr)[n] 40 | } 41 | 42 | //@title nthElement 43 | //@description 44 | // 对传入的开启和结尾的两个比较器中的值进行查找 45 | // 以传入的比较器进行比较 46 | // 通过局部二分的方式进行查找并将第n小的元素放到第n位置(大小按比较器进行确认,默认未小) 47 | //@receiver nil 48 | //@param begin *[]interface{} 待查找的元素数组指针 49 | //@param l int 查找范围的左下标 50 | //@param r int 查找范围的右下标 51 | //@param n int 待查找的是第n位,从0计数 52 | //@param Cmp ...Comparator 比较函数 53 | func nthElement(arr *[]interface{},l,r int, n int, cmp Comparator){ 54 | //二分该区域并对此进行预排序 55 | if l >= r { 56 | return 57 | } 58 | m := (*arr)[(r + l) / 2] 59 | i, j := l-1, r+1 60 | for i < j { 61 | i++ 62 | for cmp((*arr)[i], m) < 0 { 63 | i++ 64 | } 65 | j-- 66 | for cmp((*arr)[j], m) > 0 { 67 | j-- 68 | } 69 | if i < j { 70 | (*arr)[i],(*arr)[j]=(*arr)[j],(*arr)[i] 71 | } 72 | } 73 | //确认第n位的范围进行局部二分 74 | if n-1 >= i { 75 | nthElement(arr,j+1,r, n, cmp) 76 | } else { 77 | nthElement(arr,l,j, n, cmp) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /utils/comparator/search.go: -------------------------------------------------------------------------------- 1 | package comparator 2 | 3 | //@Title comparator 4 | //@Description 5 | // 该部分为对带查找数组中元素进行二分查找 6 | // warning:仅对有序元素集合有效 7 | 8 | //@title Search 9 | //@description 10 | // 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 11 | // 通过比较函数对传入的数组中的元素集合进行二分查找 12 | // 若并未传入比较函数则寻找默认比较函数 13 | // 找到后返回该元素的下标 14 | // 若该元素不在该部分内存在,则返回-1 15 | //@receiver nil 16 | //@param arr *[]interface{} 待查找的有序数组 17 | //@param e interface{} 待查找元素 18 | //@param Cmp ...Comparator 比较函数 19 | //@return idx int 待查找元素下标 20 | func Search(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { 21 | if arr==nil || (*arr)==nil || len((*arr)) == 0 { 22 | return 23 | } 24 | //判断比较函数是否有效,若无效则寻找默认比较函数 25 | var cmp Comparator 26 | cmp = nil 27 | if len(Cmp) == 0 { 28 | cmp = GetCmp(e) 29 | } else { 30 | cmp = Cmp[0] 31 | } 32 | if cmp == nil { 33 | //若并非默认类型且未传入比较器则直接结束 34 | return -1 35 | } 36 | //查找开始 37 | return search(arr, e, cmp) 38 | } 39 | 40 | //@title search 41 | //@description 42 | // 通过比较函数对传入的数组中的元素集合进行二分查找 43 | // 找到后返回该元素的下标 44 | // 若该元素不在该部分内存在,则返回-1 45 | //@receiver nil 46 | //@param arr *[]interface{} 待查找的有序数组 47 | //@param e interface{} 待查找元素 48 | //@param Cmp ...Comparator 比较函数 49 | //@return idx int 待查找元素下标 50 | func search(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { 51 | //通过二分查找的方式寻找该元素 52 | l, m, r := 0, (len((*arr))-1)/2, len((*arr)) 53 | for l < r { 54 | m = (l + r) / 2 55 | if cmp((*arr)[m], e) < 0 { 56 | l = m + 1 57 | } else { 58 | r = m 59 | } 60 | } 61 | //查找结束 62 | if (*arr)[l] == e { 63 | //该元素存在,返回下标 64 | return l 65 | } 66 | //该元素不存在,返回-1 67 | return -1 68 | } 69 | -------------------------------------------------------------------------------- /utils/comparator/sort.go: -------------------------------------------------------------------------------- 1 | package comparator 2 | 3 | //@Title comparator 4 | //@Description 5 | // 该包内通过待比较数组和比较函数进行排序 6 | // 当前支持二分排序和归并排序 7 | 8 | 9 | //@title Sort 10 | //@description 11 | // 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 12 | // 对传入的数组进行通过比较函数进行比较 13 | // 若未传入比较函数则寻找默认比较器,默认比较器排序结果为升序 14 | // 若该泛型类型并非系统默认类型之一,则不进行排序 15 | // 当待排序元素个数超过2^16个时使用归并排序 16 | // 当待排序元素个数少于2^16个时使用二分排序 17 | //@receiver nil 18 | //@param arr *[]interface{} 待排序数组的指针 19 | //@param Cmp ...Comparator 比较函数 20 | //@return nil 21 | func Sort(arr *[]interface{}, Cmp ...Comparator) { 22 | //如果传入一个空数组或nil,则直接结束 23 | if arr==nil || (*arr)==nil || len((*arr)) == 0 { 24 | return 25 | } 26 | var cmp Comparator 27 | cmp = nil 28 | if len(Cmp) > 0 { 29 | cmp = Cmp[0] 30 | } else { 31 | cmp = GetCmp((*arr)[0]) 32 | } 33 | if cmp == nil { 34 | //未传入比较器且并非默认类型导致未找到默认比较器则直接终止排序 35 | return 36 | } 37 | //根据数组长度进行分类选择排序函数 38 | if len((*arr)) < 2^26 { 39 | //当长度小于2^16时使用二分排序 40 | binary(arr,0,len((*arr))-1, cmp) 41 | } else { 42 | merge(arr,0,len((*arr))-1, cmp) 43 | } 44 | } 45 | 46 | //@title binary 47 | //@description 48 | // 二分排序 49 | // 对传入的待比较数组中的元素使用比较函数进行二分排序 50 | //@receiver nil 51 | //@param arr *[]interface{} 待排序数组指针 52 | //@param l int 待排序数组的左下标 53 | //@param r int 待排序数组的右下标 54 | //@param cmp Comparator 比较函数 55 | //@return nil 56 | func binary(arr *[]interface{},l,r int, cmp Comparator) { 57 | //对当前部分进行预排序,使得两侧都大于或小于中间值 58 | if l >= r { 59 | return 60 | } 61 | m := (*arr)[(r + l) / 2] 62 | i, j := l-1, r+1 63 | for i < j { 64 | i++ 65 | for cmp((*arr)[i], m) < 0 { 66 | i++ 67 | } 68 | j-- 69 | for cmp((*arr)[j],m) > 0 { 70 | j-- 71 | } 72 | if i < j { 73 | (*arr)[i],(*arr)[j]=(*arr)[j],(*arr)[i] 74 | } 75 | } 76 | //对分好的两侧进行迭代二分排序 77 | binary(arr,l,j, cmp) 78 | binary(arr,j+1,r, cmp) 79 | } 80 | 81 | //@title merge 82 | //@description 83 | // 归并排序 84 | // 对传入的两个迭代器中的内容使用比较器进行归并排序 85 | //@receiver nil 86 | //@param arr *[]interface{} 待排序数组指针 87 | //@param l int 待排序数组的左下标 88 | //@param r int 待排序数组的右下标 89 | //@param cmp Comparator 比较函数 90 | //@return nil 91 | func merge(arr *[]interface{},l,r int, cmp Comparator) { 92 | //对当前部分进行分组排序,将该部分近似平均的拆为两部分进行比较排序 93 | if l >= r { 94 | return 95 | } 96 | m := (r + l) / 2 97 | //对待排序内容进行二分 98 | merge(arr,l,m, cmp) 99 | merge(arr,m+1,r, cmp) 100 | //二分结束后依次比较进行归并 101 | i, j := l, m+1 102 | var tmp []interface{}=make([]interface{},0,r-l+1) 103 | for i <= m && j <= r { 104 | if cmp((*arr)[i], (*arr)[j]) <= 0 { 105 | tmp = append(tmp, (*arr)[i]) 106 | i++ 107 | } else { 108 | tmp = append(tmp, (*arr)[j]) 109 | j++ 110 | } 111 | } 112 | //当一方比较到头时将另一方剩余内容全部加入进去 113 | for ; i <= m; i++ { 114 | tmp = append(tmp, (*arr)[i]) 115 | } 116 | for ; j <= r; j++ { 117 | tmp = append(tmp, (*arr)[j]) 118 | } 119 | //将局部排序结果放入迭代器中 120 | for i, j = l, 0; i <= r; i, j = i+1, j+1 { 121 | (*arr)[i]=tmp[j] 122 | } 123 | } -------------------------------------------------------------------------------- /utils/iterator/Iterator.go: -------------------------------------------------------------------------------- 1 | package Iterator 2 | 3 | //@Title Iterator 4 | //@Description 5 | // 迭代器 6 | // 定义了一套迭代器接口和迭代器类型 7 | // 本套接口定义了迭代器所要执行的基本函数 8 | // 数据结构在使用迭代器时需要重写函数 9 | // 其中主要包括:生成迭代器,移动迭代器,判断是否可移动 10 | 11 | //Iterator迭代器 12 | //包含泛型切片和该迭代器当前指向元素的下标 13 | //可通过下标和泛型切片长度来判断是否可以前移或后移 14 | //当index不小于0时迭代器可前移 15 | //当index小于data的长度时可后移 16 | type Iterator struct { 17 | data *[]interface{} //该迭代器中存放的元素集合的指针 18 | index int //该迭代器当前指向的元素下标,-1即不存在元素 19 | } 20 | 21 | //Iterator迭代器接口 22 | //定义了一套迭代器接口函数 23 | //函数含义详情见下列描述 24 | type Iteratorer interface { 25 | Begin() (I *Iterator) //将该迭代器设为位于首节点并返回新迭代器 26 | End() (I *Iterator) //将该迭代器设为位于尾节点并返回新迭代器 27 | Get(idx int) (I *Iterator) //将该迭代器设为位于第idx节点并返回该迭代器 28 | Value() (e interface{}) //返回该迭代器下标所指元素 29 | HasNext() (b bool) //判断该迭代器是否可以后移 30 | Next() (b bool) //将该迭代器后移一位 31 | HasPre() (b bool) //判罚该迭代器是否可以前移 32 | Pre() (b bool) //将该迭代器前移一位 33 | } 34 | 35 | //@title New 36 | //@description 37 | // 新建一个Iterator迭代器容器并返回 38 | // 传入的切片指针设为迭代器所承载的元素集合 39 | // 若传入下标,则将传入的第一个下标设为该迭代器当前指向下标 40 | // 若该下标超过元素集合范围,则寻找最近的下标 41 | // 若元素集合为空,则下标设为-1 42 | //@receiver nil 43 | //@param data *[]interface{} 迭代器所承载的元素集合的指针 44 | //@param Idx ...int 预设的迭代器的下标 45 | //@return i *Iterator 新建的Iterator迭代器指针 46 | func New(data *[]interface{}, Idx ...int) (i *Iterator) { 47 | //迭代器下标 48 | var idx int 49 | if len(Idx) <= 0 { 50 | //没有传入下标,则将下标设为0 51 | idx = 0 52 | } else { 53 | //有传入下标,则将传入下标第一个设为迭代器下标 54 | idx = Idx[0] 55 | } 56 | if len((*data)) > 0 { 57 | //如果元素集合非空,则判断下标是否超过元素集合范围 58 | if idx >= len((*data)) { 59 | //如果传入下标超过元素集合范围则寻找最近的下标值 60 | idx = len((*data)) - 1 61 | } 62 | } else { 63 | //如果元素集合为空则将下标设为-1 64 | idx = -1 65 | } 66 | //新建并返回迭代器 67 | return &Iterator{ 68 | data: data, 69 | index: idx, 70 | } 71 | } 72 | 73 | //@title Begin 74 | //@description 75 | // 以Iterator迭代器指针做接收者 76 | // 如果迭代器为空,直接结束 77 | // 如果该迭代器元素集合为空,则将下标设为-1 78 | // 如果该迭代器元素集合不为空,则将下标设为0 79 | // 随后返回新迭代器指针 80 | //@receiver i *Iterator 迭代器指针 81 | //@param nil 82 | //@return I *Iterator 修改后的新迭代器指针 83 | func (i *Iterator) Begin() (I *Iterator) { 84 | if i == nil { 85 | //迭代器为空,直接结束 86 | return nil 87 | } 88 | if len((*i.data)) == 0 { 89 | //迭代器元素集合为空,下标设为-1 90 | i.index = -1 91 | } else { 92 | //迭代器元素集合非空,下标设为0 93 | i.index = 0 94 | } 95 | //返回修改后的新指针 96 | return &Iterator{ 97 | data: i.data, 98 | index: i.index, 99 | } 100 | } 101 | 102 | //@title End 103 | //@description 104 | // 以Iterator迭代器指针做接收者 105 | // 如果迭代器为空,直接结束 106 | // 如果该迭代器元素集合为空,则将下标设为-1 107 | // 如果该迭代器元素集合不为空,则将下标设为元素集合的最后一个元素的下标 108 | // 随后返回新迭代器指针 109 | //@receiver i *Iterator 迭代器指针 110 | //@param nil 111 | //@return I *Iterator 修改后的新迭代器指针 112 | func (i *Iterator) End() (I *Iterator) { 113 | if i == nil { 114 | //迭代器为空,直接返回 115 | return nil 116 | } 117 | if len((*i.data)) == 0 { 118 | //元素集合为空,下标设为-1 119 | i.index = -1 120 | } else { 121 | //元素集合非空,下标设为最后一个元素的下标 122 | i.index = len((*i.data)) - 1 123 | } 124 | //返回修改后的该指针 125 | return &Iterator{ 126 | data: i.data, 127 | index: i.index, 128 | } 129 | } 130 | 131 | //@title Get 132 | //@description 133 | // 以Iterator迭代器指针做接收者 134 | // 如果迭代器为空,直接结束 135 | // 如果该迭代器元素集合为空,则将下标设为-1 136 | // 如果该迭代器元素集合不为空,则将下标设为传入的预设下标 137 | // 如果预设下标超过元素集合范围,则将下标设为最近元素的下标 138 | // 随后返回该迭代器指针 139 | //@receiver i *Iterator 迭代器指针 140 | //@param idx int 预设下标 141 | //@return I *Iterator 修改后的该迭代器指针 142 | func (i *Iterator) Get(idx int) (I *Iterator) { 143 | if i == nil { 144 | //迭代器为空,直接返回 145 | return nil 146 | } 147 | if idx <= 0 { 148 | //预设下标超过元素集合范围,将下标设为最近元素的下标,此状态下为首元素下标 149 | idx = 0 150 | } else if idx >= len((*i.data))-1 { 151 | //预设下标超过元素集合范围,将下标设为最近元素的下标,此状态下为尾元素下标 152 | idx = len((*i.data)) - 1 153 | } 154 | if len((*i.data)) > 0 { 155 | //元素集合非空,迭代器下标设为预设下标 156 | i.index = idx 157 | } else { 158 | //元素集合为空,迭代器下标设为-1 159 | i.index = -1 160 | } 161 | //返回修改后的迭代器指针 162 | return i 163 | } 164 | 165 | //@title Value 166 | //@description 167 | // 以Iterator迭代器指针做接收者 168 | // 返回迭代器当前下标所指元素 169 | // 若迭代器为nil或元素集合为空,返回nil 170 | // 否则返回迭代器当前下标所指向的元素 171 | // 如果该下标超过元素集合范围,则返回距离最近的元素 172 | //@receiver i *Iterator 迭代器指针 173 | //@param nil 174 | //@return e interface{} 迭代器下标所指元素 175 | func (i *Iterator) Value() (e interface{}) { 176 | if i == nil { 177 | //迭代器为nil,返回nil 178 | return nil 179 | } 180 | if len((*i.data)) == 0 { 181 | //元素集合为空,返回nil 182 | return nil 183 | } 184 | if i.index <= 0 { 185 | //下标超过元素集合范围下限,最近元素为首元素 186 | i.index = 0 187 | } 188 | if i.index >= len((*i.data)) { 189 | //下标超过元素集合范围上限,最近元素为尾元素 190 | i.index = len((*i.data)) - 1 191 | } 192 | //返回下标指向元素 193 | return (*i.data)[i.index] 194 | } 195 | 196 | //@title HasNext 197 | //@description 198 | // 以Iterator迭代器指针做接收者 199 | // 判断该迭代器是否可以后移 200 | // 当迭代器为nil时不能后移 201 | // 当元素集合为空时不能后移 202 | // 当下标到达元素集合范围上限时不能后移 203 | // 否则可以后移 204 | //@author hlccd 2021-07-1 205 | //@receiver i *Iterator 迭代器指针 206 | //@param nil 207 | //@return b bool 迭代器下标可以后移? 208 | func (i *Iterator) HasNext() (b bool) { 209 | if i == nil { 210 | //迭代器为nil时不能后移 211 | return false 212 | } 213 | if len((*i.data)) == 0 { 214 | //元素集合为空时不能后移 215 | return false 216 | } 217 | //下标到达元素集合上限时不能后移,否则可以后移 218 | return i.index < len((*i.data)) 219 | } 220 | 221 | //@title Next 222 | //@description 223 | // 以Iterator迭代器指针做接收者 224 | // 将迭代器下标后移 225 | // 当满足后移条件时进行后移同时返回true 226 | // 当不满足后移条件时将下标设为尾元素下标同时返回false 227 | // 当迭代器为nil时返回false 228 | // 当元素集合为空时下标设为-1同时返回false 229 | //@receiver i *Iterator 迭代器指针 230 | //@param nil 231 | //@return b bool 迭代器下标后移成功? 232 | func (i *Iterator) Next() (b bool) { 233 | if i == nil { 234 | //迭代器为nil时返回false 235 | return false 236 | } 237 | if i.HasNext() { 238 | //满足后移条件时进行后移 239 | i.index++ 240 | return true 241 | } 242 | if len((*i.data)) == 0 { 243 | //元素集合为空时下标设为-1同时返回false 244 | i.index = -1 245 | return false 246 | } 247 | //不满足后移条件时将下标设为尾元素下标并返回false 248 | i.index = len((*i.data)) - 1 249 | return false 250 | } 251 | 252 | //@title HasPre 253 | //@description 254 | // 以Iterator迭代器指针做接收者 255 | // 判断该迭代器是否可以前移 256 | // 当迭代器为nil时不能前移 257 | // 当元素集合为空时不能前移 258 | // 当下标到达元素集合范围下限时不能前移 259 | // 否则可以前移 260 | //@receiver i *Iterator 迭代器指针 261 | //@param nil 262 | //@return b bool 迭代器下标可以前移? 263 | func (i *Iterator) HasPre() (b bool) { 264 | if i == nil { 265 | //迭代器为nil时不能前移 266 | return false 267 | } 268 | if len((*i.data)) == 0 { 269 | //元素集合为空时不能前移 270 | return false 271 | } 272 | //下标到达元素集合范围下限时不能前移,否则可以后移 273 | return i.index >= 0 274 | } 275 | 276 | //@title Pre 277 | //@description 278 | // 以Iterator迭代器指针做接收者 279 | // 将迭代器下标前移 280 | // 当满足前移条件时进行前移同时返回true 281 | // 当不满足前移条件时将下标设为首元素下标同时返回false 282 | // 当迭代器为nil时返回false 283 | // 当元素集合为空时下标设为-1同时返回false 284 | //@receiver i *Iterator 迭代器指针 285 | //@param nil 286 | //@return b bool 迭代器下标前移成功? 287 | func (i *Iterator) Pre() (b bool) { 288 | if i == nil { 289 | //迭代器为nil时返回false 290 | return false 291 | } 292 | if i.HasPre() { 293 | //满足后移条件时进行前移 294 | i.index-- 295 | return true 296 | } 297 | if len((*i.data)) == 0 { 298 | //元素集合为空时下标设为-1同时返回false 299 | i.index = -1 300 | return false 301 | } 302 | //不满足后移条件时将下标设为尾元素下标并返回false 303 | i.index = 0 304 | return false 305 | } 306 | --------------------------------------------------------------------------------