这个二进制搜索功能究竟是什么?

时间:2018-05-27 19:27:15

标签: list haskell binary-search

我很难理解这个二元搜索功能是如何工作的:

bsearch :: Ord a => [a] -> a -> Bool
bsearch [] _ = False
bsearch xs x =
   if x < y then bsearch ys1 x
   else if x > y then bsearch ys2 x
   else True
  where
    ys1 = take l xs
    (y:ys2) = drop l xs
    l = length xs `div` 2

我试着通过一个例子来考虑:bsearch [1,2,3,4] 4 但我不明白这个功能在哪里开始。我喜欢相信首先计算l = length xs 'div' 2。结果是l = 2。 现在我将变量放在(y:ys2) = drop l xs (y:ys2) = 3:[4] 等于drop 2 [1,2,3,4] = [3,4]。下一个else if 4 > 3 then bsearch ys2 x会在ys2 = [4]x = 4处执行。接下来发生什么? x = 4ys2 = [4]如何进行比较?

编辑:我认为,bsearch [4] 4是执行bsearch xs x的新l = length xs 'div' 2 = length [4] 'div' 2 = 0drop 0 [4] = [4] = (4:[])。因此4 < 44 > 4False else True。 这是这个函数为我的例子执行的方式吗?

如果有人能帮我解决这个问题,我会很高兴。

1 个答案:

答案 0 :(得分:2)

您对绑定如何扩展的解释是正确的。该函数基本上通过将有限排序列表按需转换为二叉搜索树来操作。我可以重写函数的一部分只是为了显示树结构(注意where部分没有改变):

data Tree a = Node (Tree a) a (Tree a) | Empty
  deriving Show

tree [] = Empty
tree xs = Node (tree ys1) y (tree ys2)
  where
    ys1 = take l xs
    (y:ys2) = drop l xs
    l = length xs `div` 2

然后可以生成树形式:

*Main> tree [1..4]
Node (Node (Node Empty 1 Empty) 2 Empty) 3 (Node Empty 4 Empty)

递归上部部分仅涉及遍历树的相关部分。

bsearchT Empty _ = False
bsearchT (Node ys1 y ys2) x =
   if      x < y then bsearchT ys1 x
   else if x > y then bsearchT ys2 x
   else               True

bsearch xs x = bsearchT (tree xs) x

操作本身确实表明普通列表不是合适的数据类型;我们可以观察到Data.List.Ordered.member执行线性搜索,因为列表必须从头部遍历并且可能是无限的。 Arraysvectors提供随机访问权限,因此确实存在Data.Vector.Algorithms.Search.binarySearch