寻找通用的`bisect`函数

时间:2012-03-24 22:42:34

标签: haskell

我在Haskell中寻找类似于Python的bisect和朋友的bisect_left()操作。输入将是下限,上限,非递减函数(Ord a)=&gt;(Int-> a),其必须针对下限和上限之间的所有整数以及搜索值来定义。返回值是ilower <= i <= upper的最高整数f(i) < search_term。性能应为O(log(n))。

为此感到高兴:

(Ord a)=>(Int->a)->Int->Int->a->Int

不会产生任何结果。

某个库中是否有标准的通用二进制搜索运算符?

3 个答案:

答案 0 :(得分:7)

Ross Paterson关于Hackage的binary-search软件包可以满足您的需求。具体来说,请参阅searchFromTo,其中包含类型签名

searchFromTo :: Integral a => (a -> Bool) -> a -> a -> Maybe a

正如Tikhon指出的那样,Haskell中的[a]链表而不是数组。由于链接列表仅支持顺序访问,因此无法在[a]数据结构上进行对数时间搜索。相反,您应该使用真正的数组数据结构 - 请参阅vector库以获取数组的首选实现。

Dan Doel为矢量包中的 mutable 向量编写了一系列二进制搜​​索函数:请参阅Data.Vector.Algorithms.Search库中的vector-algorithms。与提供纯API的Ross Paterson库相比,Data.Vector.Algorithms.Search中的API是monadic(即,它必须在ST monad或IO monad中运行。 / p>

答案 1 :(得分:3)

bisect_left这样的函数(假设我正确阅读了它的文档)对于列表来说并不存在。

这是有道理的 - 因为你没有在列表中的O(1)中进行随机访问(记住Haskell列表是链表,而Python使用的东西更像是向量),你无法真正获得O(logn)二进制搜索。

特别是,只是到达列表的中间需要O(n / 2)(这只是O(n))步骤,因此涉及列表中间的算法(如二进制搜索)必须是在Ω(n)。

简而言之 - 二进制搜索在列表上没有意义。如果您正在进行大量搜索,则可能需要不同的数据结构。特别是,请查看内部使用二叉树的Data.Set

答案 2 :(得分:0)

binary_search :: Ord a, Integral b => (b -> a) -> b -> b -> a -> b
binary_search f low hi a = go low hi
     where
        go low hi | low + 1 == hi = low
        go low hi = go low' hi'
           where
              mid = (low + hi) `div` 2
              (low',hi') = if f mid < a then (mid,hi) else (low, mid)

(这可能有一个错误。)