goSTL/utils/comparator/nth_element.go

80 lines
2.4 KiB
Go

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