From 0dad68e716ffc297083b900461b01f69f1416db7 Mon Sep 17 00:00:00 2001 From: hlccd <56643462+hlccd@users.noreply.github.com> Date: Mon, 18 Oct 2021 18:06:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E6=AF=94=E8=BE=83?= =?UTF-8?q?=E5=99=A8=E5=8F=8A=E5=85=B6=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- goSTL/data_structure/vector/vector.go | 335 ++++++++++++++++++++++++++ goSTL/utils/comparator/bound.go | 116 +++++++++ goSTL/utils/comparator/comparator.go | 250 +++++++++++++++++++ goSTL/utils/comparator/nth_element.go | 79 ++++++ goSTL/utils/comparator/search.go | 68 ++++++ goSTL/utils/comparator/sort.go | 123 ++++++++++ goSTL/utils/iterator/Iterator.go | 34 +++ 7 files changed, 1005 insertions(+) create mode 100644 goSTL/data_structure/vector/vector.go create mode 100644 goSTL/utils/comparator/bound.go create mode 100644 goSTL/utils/comparator/comparator.go create mode 100644 goSTL/utils/comparator/nth_element.go create mode 100644 goSTL/utils/comparator/search.go create mode 100644 goSTL/utils/comparator/sort.go create mode 100644 goSTL/utils/iterator/Iterator.go diff --git a/goSTL/data_structure/vector/vector.go b/goSTL/data_structure/vector/vector.go new file mode 100644 index 0000000..f333363 --- /dev/null +++ b/goSTL/data_structure/vector/vector.go @@ -0,0 +1,335 @@ +package vector + +//@Title vector +//@Description +// vector向量容器包 +// 以切片数组的形式实现 +// 该容器可以在尾部实现线性增减元素 +// 通过interface实现泛型 +// 可接纳不同类型的元素 +// 但建议在同一个vector中使用相同类型的元素 +// 可通过配合比较器competitor和迭代器iterator对该vector容器进行排序或查找 + +import ( + "sync" +) + +//vector向量结构体 +//包含泛型切片和该切片的尾指针 +//当删除节点时仅仅需要前移尾指针一位即可 +//当剩余长度小于实际占用空间长度的一半时会重新规划以释放掉多余占用的空间 +//当添加节点时若未占满全部已分配空间则尾指针后移一位同时进行覆盖存放 +//当添加节点时尾指针大于已分配空间长度,则新增空间 + +type vector struct { + data []interface{} //泛型切片 + end int //尾指针 + mutex sync.Mutex //并发控制锁 +} + +//vector向量容器接口 +//存放了vector容器可使用的函数 +//对应函数介绍见下方 + +type vectorer interface { + Size() (num int) //返回vector的长度 + Clear() //清空vector + Empty() (b bool) //返回vector是否为空,为空则返回true反之返回false + PushBack(e interface{}) //向vector末尾插入一个元素 + PopBack() //弹出vector末尾元素 + Insert(idx int, e interface{}) //向vector第idx的位置插入元素e,同时idx后的其他元素向后退一位 + Erase(idx int) //删除vector的第idx个元素 + Reverse() //逆转vector中的数据顺序 + At(idx int) (e interface{}) //返回vector的第idx的元素 + Front() (e interface{}) //返回vector的第一个元素 + Back() (e interface{}) //返回vector的最后一个元素 +} + +//@title New +//@description +// 新建一个vector向量容器并返回 +// 初始vector的切片数组为空 +// 初始vector的尾指针置0 +//@receiver nil +//@param nil +//@return v *vector 新建的vector指针 +func New() (v *vector) { + return &vector{ + data: make([]interface{}, 1), + end: 0, + mutex: sync.Mutex{}, + } +} + + +//@title Size +//@description +// 以vector向量容器做接收者 +// 返回该容器当前含有元素的数量 +// 该长度并非实际占用空间数量 +// 如果容器为nil返回-1 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return num int 容器中实际使用元素所占空间大小 +func (v *vector) Size() (num int) { + if v == nil { + return -1 + } + return v.end +} + +//@title Clear +//@description +// 以vector向量容器做接收者 +// 将该容器中所承载的元素清空 +// 将该容器的尾指针置0 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return nil +func (v *vector) Clear() { + if v == nil { + return + } + v.mutex.Lock() + v.data = v.data[0:0] + v.end = 0 + v.mutex.Unlock() +} + +//@title Empty +//@description +// 以vector向量容器做接收者 +// 判断该vector向量容器是否含有元素 +// 如果含有元素则不为空,返回false +// 如果不含有元素则说明为空,返回true +// 如果容器不存在,返回true +// 该判断过程通过尾指针数值进行判断 +// 当尾指针数值为0时说明不含有元素 +// 当尾指针数值大于0时说明含有元素 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return b bool 该容器是空的吗? +func (v *vector) Empty() (b bool) { + if v == nil { + return true + } + return v.Size() <= 0 +} + +//@title PushBack +//@description +// 以vector向量容器做接收者 +// 在容器尾部插入元素 +// 若尾指针小于切片实际使用长度,则对当前指针位置进行覆盖,同时尾指针后移一位 +// 若尾指针等于切片实际使用长度,则新增切片长度同时使尾指针后移一位 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param e interface{} 待插入元素 +//@return nil +func (v *vector) PushBack(e interface{}) { + if v == nil { + return + } + v.mutex.Lock() + if v.end < len(v.data) { + v.data[v.end] = e + } else { + v.data = append(v.data, e) + } + v.end++ + v.mutex.Unlock() +} + +//@title PopBack +//@description +// 以vector向量容器做接收者 +// 弹出容器最后一个元素,同时尾指针前移一位 +// 当尾指针小于容器切片实际使用空间的一半时,重新分配空间释放未使用部分 +// 若容器为空,则不进行弹出 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return nil +func (v *vector) PopBack() { + if v == nil { + return + } + if v.Empty() { + return + } + v.mutex.Lock() + v.end-- + if v.end*2 <= len(v.data) { + v.data = v.data[0:v.end] + } + v.mutex.Unlock() +} + +//@title Insert +//@description +// 以vector向量容器做接收者 +// 向容器切片中插入一个元素 +// 当idx不大于0时,则在容器切片的头部插入元素 +// 当idx不小于切片使用长度时,在容器末尾插入元素 +// 否则在切片中间第idx位插入元素,同时后移第idx位以后的元素 +// idx从0计算 +// 尾指针同步后移一位 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param idx int 待插入节点的位置 +//@param e interface{} 待插入元素 +//@return nil +func (v *vector) Insert(idx int, e interface{}) { + if v == nil { + return + } + v.mutex.Lock() + if idx <= 0 { + v.data = append(append([]interface{}{}, e), v.data[:v.end]...) + v.end++ + } else if idx >= v.Size() { + v.PushBack(e) + } else { + es := append([]interface{}{}, v.data[idx:v.end]...) + v.data = append(append(v.data[:idx], e), es...) + v.end++ + } + v.mutex.Unlock() +} + +//@title Erase +//@description +// 以vector向量容器做接收者 +// 向容器切片中删除一个元素 +// 当idx不大于0时,则在容器切片的头部删除 +// 当idx不小于切片使用长度时,在容器末尾删除 +// 否则在切片中间第idx位删除元素,同时前移第idx位以后的元素 +// idx从0计算 +// 尾指针同步后移以为 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param idx int 待删除节点的位置 +//@return nil +func (v *vector) Erase(idx int) { + if v == nil { + return + } + if v.Empty() { + return + } + v.mutex.Lock() + idx++ + if idx <= 1 { + idx = 1 + } else if idx >= v.Size() { + idx = v.Size() + } + es := append([]interface{}{}, v.data[:idx-1]...) + v.data = append(es, v.data[idx:]...) + v.end-- + v.mutex.Unlock() +} + +//@title Reverse +//@description +// 以vector向量容器做接收者 +// 将vector容器中不使用空间释放掉 +// 将该容器中的泛型切片中的所有元素顺序逆转 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return nil +func (v *vector) Reverse() { + if v == nil { + return + } + v.mutex.Lock() + if v.end > 0 { + v.data = v.data[:v.end] + } else { + v.data = make([]interface{}, 0, 0) + } + for i := 0; i < v.end/2; i++ { + v.data[i], v.data[v.end-i-1] = v.data[v.end-i-1], v.data[i] + } + v.mutex.Unlock() +} + +//@title At +//@description +// 以vector向量容器做接收者 +// 根据传入的idx寻找位于第idx位的元素 +// 当idx不在容器中泛型切片的使用范围内 +// 即当idx小于0或者idx大于容器所含有的元素个数时返回nil +// 反之返回对应位置的元素 +// idx从0计算 +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param idx int 待查找元素的位置 +//@return e interface{} 从容器中查找的第idx位元素 +func (v *vector) At(idx int) (e interface{}) { + if v == nil { + return nil + } + v.mutex.Lock() + if idx < 0 && idx >= v.Size() { + v.mutex.Unlock() + return nil + } + if v.Size() > 0 { + e = v.data[idx] + v.mutex.Unlock() + return e + } + v.mutex.Unlock() + return nil +} + +//@title Front +//@description +// 以vector向量容器做接收者 +// 返回该容器的第一个元素 +// 若该容器当前为空,则返回nil +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return e interface{} 容器的第一个元素 +func (v *vector) Front() (e interface{}) { + if v == nil { + return nil + } + v.mutex.Lock() + if v.Size() > 0 { + e = v.data[0] + v.mutex.Unlock() + return e + } + v.mutex.Unlock() + return nil +} + +//@title Back +//@description +// 以vector向量容器做接收者 +// 返回该容器的最后一个元素 +// 若该容器当前为空,则返回nil +//@auth hlccd 2021-07-4 +//@receiver v *vector 接受者vector的指针 +//@param nil +//@return e interface{} 容器的最后一个元素 +func (v *vector) Back() (e interface{}) { + if v == nil { + return nil + } + v.mutex.Lock() + if v.Size() > 0 { + e = v.data[v.end-1] + v.mutex.Unlock() + return e + } + v.mutex.Unlock() + return nil +} diff --git a/goSTL/utils/comparator/bound.go b/goSTL/utils/comparator/bound.go new file mode 100644 index 0000000..6336693 --- /dev/null +++ b/goSTL/utils/comparator/bound.go @@ -0,0 +1,116 @@ +package comparator + +//@Title comparator +//@Description +// 可查找有序序列中某一元素的上界和下届 +// 当该元素存在时,上界和下届返回的下标位置指向该元素 +// 当该元素不存在时,上界和下届指向下标错位且指向位置并非该元素 + +//@title UpperBound +//@description +// 通过传入的比较函数对待查找数组进行查找以获取待查找元素的上界即不大于它的最大值的下标 +// 以传入的比较函数进行比较 +// 如果该元素存在,则上界指向元素为该元素 +// 如果该元素不存在,上界指向元素为该元素的前一个元素 +//@receiver nil +//@param arr *[]interface{} 待查找数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素的上界 +func UpperBound(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { + if arr==nil || (*arr)==nil || len((*arr)) == 0 { + return -1 + } + //判断比较函数是否有效 + var cmp Comparator + cmp = nil + if len(Cmp) == 0 { + cmp = GetCmp(e) + } else { + cmp = Cmp[0] + } + if cmp == nil { + return -1 + } + //寻找该元素的上界 + return upperBound(arr, e, cmp) +} + +//@title upperBound +//@description +// 通过传入的比较函数对待查找数组进行查找以获取待查找元素的上界即不大于它的最大值的下标 +// 以传入的比较函数进行比较 +// 如果该元素存在,则上界指向元素为该元素,且为最右侧 +// 如果该元素不存在,上界指向元素为该元素的前一个元素 +// 以二分查找的方式寻找该元素的上界 +//@receiver nil +//@param arr *[]interface{} 待查找数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素的上界 +func upperBound(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { + l, m, r := 0, len((*arr)) / 2, len((*arr))-1 + for l < r { + m = (l + r + 1) / 2 + if cmp((*arr)[m], e) <= 0 { + l = m + } else { + r = m - 1 + } + } + return l +} + +//@title LowerBound +//@description +// 通过传入的比较函数对待查找数组进行查找以获取待查找元素的下界即不小于它的最小值的下标 +// 以传入的比较函数进行比较 +// 如果该元素存在,则上界指向元素为该元素 +// 如果该元素不存在,上界指向元素为该元素的后一个元素 +//@receiver nil +//@param arr *[]interface{} 待查找数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素的下界 +func LowerBound(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { + if arr==nil || (*arr)==nil || len((*arr)) == 0 { + return -1 + } + //判断比较函数是否有效 + var cmp Comparator + cmp = nil + if len(Cmp) == 0 { + cmp = GetCmp(e) + } else { + cmp = Cmp[0] + } + if cmp == nil { + return -1 + } + //寻找该元素的下界 + return lowerBound(arr, e, cmp) +} + +//@title lowerBound +//@description +// 通过传入的比较函数对待查找数组进行查找以获取待查找元素的下界即不小于它的最小值的下标 +// 以传入的比较函数进行比较 +// 如果该元素存在,则上界指向元素为该元素,且为最右侧 +// 如果该元素不存在,上界指向元素为该元素的后一个元素 +//@receiver nil +//@param arr *[]interface{} 待查找数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素的下界 +func lowerBound(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { + l, m, r := 0, len((*arr)) / 2, len((*arr)) + for l < r { + m = (l + r) / 2 + if cmp((*arr)[m], e) >= 0 { + r = m + } else { + l = m + 1 + } + } + return l +} diff --git a/goSTL/utils/comparator/comparator.go b/goSTL/utils/comparator/comparator.go new file mode 100644 index 0000000..5aac92b --- /dev/null +++ b/goSTL/utils/comparator/comparator.go @@ -0,0 +1,250 @@ +package comparator + +//@Title comparator +//@Description +// 比较器 +// 定义了一个比较器类型,该类型可传入两个泛型并返回一个整数判断大小 +// 该比较器用于定义的数据结构中传入数据之间的比较 +// 该包内定义了一些自带类型的比较类型 +// 当使用自定义的数据结构时若不进行比较器的传入则使用默认比较器 +// 若传入类型非系统自带类型,则返回空比较器同时对数据的传入失败 + +// 比较器将会返回数字num +// num > 0 ,if a > b +// num = 0 ,if a = b +// num < 0 ,if a < b + +type Comparator func(a, b interface{}) int + +//@title GetCmp +//@description +// 传入一个数据并根据该数据类型返回一个对应的比较器 +// 若该类型并非系统自带类型,则返回个空比较器 +// 若传入元素为nil则之间返回nil +//@receiver nil +//@param e interface{} +//@return cmp Comparator 该类型对应的默认比较器 +func GetCmp(e interface{}) (cmp Comparator) { + if e==nil{ + return nil + } + switch e.(type) { + case bool: + return boolCmp + case int: + return intCmp + case int8: + return int8Cmp + case uint8: + return uint8Cmp + case int16: + return int16Cmp + case uint16: + return uint16Cmp + case int32: + return int32Cmp + case uint32: + return uint32Cmp + case int64: + return int64Cmp + case uint64: + return uint64Cmp + case float32: + return float32Cmp + case float64: + return float64Cmp + case complex64: + return complex64Cmp + case complex128: + return complex128Cmp + case string: + return stringCmp + } + return nil +} + +//以下为系统自带类型的默认比较器 + +func boolCmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(bool) { + return 1 + } else if b.(bool) { + return -1 + } + return 0 +} +func intCmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(int) > b.(int) { + return 1 + } else if a.(int) < b.(int) { + return -1 + } + return 0 +} +func int8Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(int8) > b.(int8) { + return 1 + } else if a.(int8) < b.(int8) { + return -1 + } + return 0 +} +func uint8Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(uint8) > b.(uint8) { + return 1 + } else if a.(uint8) < b.(uint8) { + return -1 + } + return 0 +} +func int16Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(int16) > b.(int16) { + return 1 + } else if a.(int16) < b.(int16) { + return -1 + } + return 0 +} +func uint16Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(uint16) > b.(uint16) { + return 1 + } else if a.(uint16) < b.(uint16) { + return -1 + } + return 0 +} +func int32Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(int32) > b.(int32) { + return 1 + } else if a.(int32) < b.(int32) { + return -1 + } + return 0 +} +func uint32Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(uint32) > b.(uint32) { + return 1 + } else if a.(uint32) < b.(uint32) { + return -1 + } + return 0 +} +func int64Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(int64) > b.(int64) { + return 1 + } else if a.(int64) < b.(int64) { + return -1 + } + return 0 +} +func uint64Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(uint64) > b.(uint64) { + return 1 + } else if a.(uint64) < b.(uint64) { + return -1 + } + return 0 +} +func float32Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(float32) > b.(float32) { + return 1 + } else if a.(float32) < b.(float32) { + return -1 + } + return 0 +} +func float64Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if a.(float64) > b.(float64) { + return 1 + } else if a.(float64) < b.(float64) { + return -1 + } + return 0 +} +func complex64Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if real(a.(complex64)) > real(b.(complex64)) { + return 1 + } else if real(a.(complex64)) < real(b.(complex64)) { + return -1 + } else { + if imag(a.(complex64)) > imag(b.(complex64)) { + return 1 + } else if imag(a.(complex64)) < imag(b.(complex64)) { + return -1 + } + } + return 0 +} +func complex128Cmp(a, b interface{}) int { + if a == b { + return 0 + } + if real(a.(complex128)) > real(b.(complex128)) { + return 1 + } else if real(a.(complex128)) < real(b.(complex128)) { + return -1 + } else { + if imag(a.(complex128)) > imag(b.(complex128)) { + return 1 + } else if imag(a.(complex128)) < imag(b.(complex128)) { + return -1 + } + } + return 0 +} +func stringCmp(a, b interface{}) int { + if a == b { + return 0 + } + if len(a.(string)) > len(b.(string)) { + return 1 + } else if len(a.(string)) < len(b.(string)) { + return -1 + } else { + if a.(string) > b.(string) { + return 1 + } else if a.(string) < b.(string) { + return -1 + } + } + return 0 +} diff --git a/goSTL/utils/comparator/nth_element.go b/goSTL/utils/comparator/nth_element.go new file mode 100644 index 0000000..4934cf6 --- /dev/null +++ b/goSTL/utils/comparator/nth_element.go @@ -0,0 +1,79 @@ +package comparator + +//@Title comparator +//@Description +// 该包内通过利用比较函数重排传入的数组,使得下标为n的元素必然是第n+1大的(考虑到下标从0开始) +// 对二分排序的变形,当只对该节点位置存在的某一局部进行查找即可 + +//@title NthElement +//@description +// 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 +// 通过利用比较函数重排传入的数组,使得下标为n的元素必然是第n+1大的(考虑到下标从0开始) +// 若n大于数组长度,直接结束,否则对第n+1大的元素排序后返回该元素 +//@receiver nil +//@param begin *[]interface{} 待查找的元素数组指针 +//@param n int 待查找的是第n位,从0计数 +//@param Cmp ...Comparator 比较函数 +//@return value interface{} 第n+1大的元素 +func NthElement(arr *[]interface{}, n int, Cmp ...Comparator) (value interface{}){ + if arr==nil || (*arr)==nil || len((*arr)) == 0 { + return nil + } + //判断比较函数是否有效 + var cmp Comparator + cmp = nil + if len(Cmp) > 0 { + cmp = Cmp[0] + } else { + cmp = GetCmp((*arr)[0]) + } + if cmp == nil { + return nil + } + //判断待确认的第n位是否在该集合范围内 + if len((*arr)) < n || n<0 { + return nil + } + //进行查找 + nthElement(arr,0,len((*arr))-1, n, cmp) + return (*arr)[n] +} + +//@title nthElement +//@description +// 对传入的开启和结尾的两个比较器中的值进行查找 +// 以传入的比较器进行比较 +// 通过局部二分的方式进行查找并将第n小的元素放到第n位置(大小按比较器进行确认,默认未小) +//@receiver nil +//@param begin *[]interface{} 待查找的元素数组指针 +//@param l int 查找范围的左下标 +//@param r int 查找范围的右下标 +//@param n int 待查找的是第n位,从0计数 +//@param Cmp ...Comparator 比较函数 +func nthElement(arr *[]interface{},l,r int, n int, cmp Comparator){ + //二分该区域并对此进行预排序 + if l >= r { + return + } + m := (*arr)[(r + l) / 2] + i, j := l-1, r+1 + for i < j { + i++ + for cmp((*arr)[i], m) < 0 { + i++ + } + j-- + for cmp((*arr)[j], m) > 0 { + j-- + } + if i < j { + (*arr)[i],(*arr)[j]=(*arr)[j],(*arr)[i] + } + } + //确认第n位的范围进行局部二分 + if n-1 >= i { + nthElement(arr,j+1,r, n, cmp) + } else { + nthElement(arr,l,j, n, cmp) + } +} diff --git a/goSTL/utils/comparator/search.go b/goSTL/utils/comparator/search.go new file mode 100644 index 0000000..fa50f12 --- /dev/null +++ b/goSTL/utils/comparator/search.go @@ -0,0 +1,68 @@ +package comparator + +//@Title comparator +//@Description +// 该部分为对带查找数组中元素进行二分查找 +// warning:仅对有序元素集合有效 + +//@title Search +//@description +// 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 +// 通过比较函数对传入的数组中的元素集合进行二分查找 +// 若并未传入比较函数则寻找默认比较函数 +// 找到后返回该元素的下标 +// 若该元素不在该部分内存在,则返回-1 +//@receiver nil +//@param arr *[]interface{} 待查找的有序数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素下标 +func Search(arr *[]interface{}, e interface{}, Cmp ...Comparator) (idx int) { + if arr==nil || (*arr)==nil || len((*arr)) == 0 { + return + } + //判断比较函数是否有效,若无效则寻找默认比较函数 + var cmp Comparator + cmp = nil + if len(Cmp) == 0 { + cmp = GetCmp(e) + } else { + cmp = Cmp[0] + } + if cmp == nil { + //若并非默认类型且未传入比较器则直接结束 + return -1 + } + //查找开始 + return search(arr, e, cmp) +} + +//@title search +//@description +// 通过比较函数对传入的数组中的元素集合进行二分查找 +// 找到后返回该元素的下标 +// 若该元素不在该部分内存在,则返回-1 +//@receiver nil +//@param arr *[]interface{} 待查找的有序数组 +//@param e interface{} 待查找元素 +//@param Cmp ...Comparator 比较函数 +//@return idx int 待查找元素下标 +func search(arr *[]interface{}, e interface{}, cmp Comparator) (idx int) { + //通过二分查找的方式寻找该元素 + l, m, r := 0, (len((*arr))-1)/2, len((*arr)) + for l < r { + m = (l + r) / 2 + if cmp((*arr)[m], e) < 0 { + l = m + 1 + } else { + r = m + } + } + //查找结束 + if (*arr)[l] == e { + //该元素存在,返回下标 + return l + } + //该元素不存在,返回-1 + return -1 +} diff --git a/goSTL/utils/comparator/sort.go b/goSTL/utils/comparator/sort.go new file mode 100644 index 0000000..bcfaa86 --- /dev/null +++ b/goSTL/utils/comparator/sort.go @@ -0,0 +1,123 @@ +package comparator + +//@Title comparator +//@Description +// 该包内通过待比较数组和比较函数进行排序 +// 当前支持二分排序和归并排序 + + +//@title Sort +//@description +// 若数组指针为nil或者数组为nil或数组长度为0则直接结束即可 +// 对传入的数组进行通过比较函数进行比较 +// 若未传入比较函数则寻找默认比较器,默认比较器排序结果为升序 +// 若该泛型类型并非系统默认类型之一,则不进行排序 +// 当待排序元素个数超过2^16个时使用归并排序 +// 当待排序元素个数少于2^16个时使用二分排序 +//@receiver nil +//@param arr *[]interface{} 待排序数组的指针 +//@param Cmp ...Comparator 比较函数 +//@return nil +func Sort(arr *[]interface{}, Cmp ...Comparator) { + //如果传入一个空数组或nil,则直接结束 + if arr==nil || (*arr)==nil || len((*arr)) == 0 { + return + } + var cmp Comparator + cmp = nil + if len(Cmp) > 0 { + cmp = Cmp[0] + } else { + cmp = GetCmp((*arr)[0]) + } + if cmp == nil { + //未传入比较器且并非默认类型导致未找到默认比较器则直接终止排序 + return + } + //根据数组长度进行分类选择排序函数 + if len((*arr)) < 2^26 { + //当长度小于2^16时使用二分排序 + binary(arr,0,len((*arr))-1, cmp) + } else { + merge(arr,0,len((*arr))-1, cmp) + } +} + +//@title binary +//@description +// 二分排序 +// 对传入的待比较数组中的元素使用比较函数进行二分排序 +//@receiver nil +//@param arr *[]interface{} 待排序数组指针 +//@param l int 待排序数组的左下标 +//@param r int 待排序数组的右下标 +//@param cmp Comparator 比较函数 +//@return nil +func binary(arr *[]interface{},l,r int, cmp Comparator) { + //对当前部分进行预排序,使得两侧都大于或小于中间值 + if l >= r { + return + } + m := (*arr)[(r + l) / 2] + i, j := l-1, r+1 + for i < j { + i++ + for cmp((*arr)[i], m) < 0 { + i++ + } + j-- + for cmp((*arr)[j],m) > 0 { + j-- + } + if i < j { + (*arr)[i],(*arr)[j]=(*arr)[j],(*arr)[i] + } + } + //对分好的两侧进行迭代二分排序 + binary(arr,l,j, cmp) + binary(arr,j+1,r, cmp) +} + +//@title merge +//@description +// 归并排序 +// 对传入的两个迭代器中的内容使用比较器进行归并排序 +//@receiver nil +//@param arr *[]interface{} 待排序数组指针 +//@param l int 待排序数组的左下标 +//@param r int 待排序数组的右下标 +//@param cmp Comparator 比较函数 +//@return nil +func merge(arr *[]interface{},l,r int, cmp Comparator) { + //对当前部分进行分组排序,将该部分近似平均的拆为两部分进行比较排序 + if l >= r { + return + } + m := (r + l) / 2 + //对待排序内容进行二分 + merge(arr,l,m, cmp) + merge(arr,m+1,r, cmp) + //二分结束后依次比较进行归并 + i, j := l, m+1 + var tmp []interface{}=make([]interface{},0,r-l+1) + for i <= m && j <= r { + if cmp((*arr)[i], (*arr)[j]) <= 0 { + tmp = append(tmp, (*arr)[i]) + i++ + } else { + tmp = append(tmp, (*arr)[j]) + j++ + } + } + //当一方比较到头时将另一方剩余内容全部加入进去 + for ; i <= m; i++ { + tmp = append(tmp, (*arr)[i]) + } + for ; j <= r; j++ { + tmp = append(tmp, (*arr)[j]) + } + //将局部排序结果放入迭代器中 + for i, j = l, 0; i <= r; i, j = i+1, j+1 { + (*arr)[i]=tmp[j] + } +} \ No newline at end of file diff --git a/goSTL/utils/iterator/Iterator.go b/goSTL/utils/iterator/Iterator.go new file mode 100644 index 0000000..f0287f4 --- /dev/null +++ b/goSTL/utils/iterator/Iterator.go @@ -0,0 +1,34 @@ +package Iterator + +//@Title Iterator +//@Description +// 迭代器 +// 定义了一套迭代器接口和迭代器类型 +// 本套接口定义了迭代器所要执行的基本函数 +// 数据结构在使用迭代器时需要重写函数 +// 其中主要包括:生成迭代器,移动迭代器,判断是否可移动 + +//Iterator迭代器 +//包含泛型切片和该迭代器当前指向元素的下标 +//可通过下标和泛型切片长度来判断是否可以前移或后移 +//当index不小于0时迭代器可前移 +//当index小于data的长度时可后移 +type Iterator struct { + data *[]interface{} //该迭代器中存放的元素集合的指针 + index int //该迭代器当前指向的元素下标,-1即不存在元素 +} + +//Iterator迭代器接口 +//定义了一套迭代器接口函数 +//函数含义详情见下列描述 +type Iteratorer interface { + New(data *[]interface{}) (I *Iteratorer) //传输元素创建一个新迭代器 + Begin() (I *Iterator) //将该迭代器设为位于首节点并返回新迭代器 + End() (I *Iterator) //将该迭代器设为位于尾节点并返回新迭代器 + Get(idx int) (I *Iterator) //将该迭代器设为位于第idx节点并返回该迭代器 + Value() (e interface{}) //返回该迭代器下标所指元素 + HasNext() (b bool) //判断该迭代器是否可以后移 + Next() (b bool) //将该迭代器后移一位 + HasPre() (b bool) //判罚该迭代器是否可以前移 + Pre() (b bool) //将该迭代器前移一位 +}