将所有文件的目录结构进行调整,以保证使用者下载即可用

This commit is contained in:
hlccd
2021-12-29 00:32:14 +08:00
committed by GitHub
parent d105904a78
commit e1b6fae026
38 changed files with 8943 additions and 0 deletions

116
utils/comparator/bound.go Normal file
View File

@@ -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
}

View File

@@ -0,0 +1,278 @@
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
//比较器的特种——相等器
//判断传入的两个元素是否相等
type Equaler func(a, b interface{}) (B bool)
//@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
}
//@title GetEqual
//@description
// 传入一个数据并根据该数据类型返回一个对应的比较器
// 若该类型并非系统自带类型,则返回个空比较器
// 若传入元素为nil则之间返回nil
//@receiver nil
//@param e interface{}
//@return cmp Comparator 该类型对应的默认比较器
func GetEqual() (equ Equaler) {
return basicEqual
}
//@title basicEqual
//@description
// 返回基本比较器
// 即有且仅有判断量元素是否完全相等
//@receiver a interface{} 待判断相等的第一个元素
//@receiver b interface{} 待判断相等的第二个元素
//@param nil
//@return B bool 这两个元素是否相等?
func basicEqual(a, b interface{}) (B bool) {
return a == b
}
//以下为系统自带类型的默认比较器
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
}

View File

@@ -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)
}
}

View File

@@ -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
}

123
utils/comparator/sort.go Normal file
View File

@@ -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]
}
}