我很难理解这个二元搜索功能是如何工作的:
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 = 4
和ys2 = [4]
如何进行比较?
编辑:我认为,bsearch [4] 4
是执行bsearch xs x
的新l = length xs 'div' 2 = length [4] 'div' 2 = 0
新drop 0 [4] = [4] = (4:[])
。因此4 < 4
和4 > 4
为False
else True
。
这是这个函数为我的例子执行的方式吗?
如果有人能帮我解决这个问题,我会很高兴。
答案 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执行线性搜索,因为列表必须从头部遍历并且可能是无限的。 Arrays或vectors提供随机访问权限,因此确实存在Data.Vector.Algorithms.Search.binarySearch。