You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell:如何缓存函数调用结果优化树搜索实现

优化Haskell树搜索函数:避免重复递归调用

首先是你定义的代数数据类型:

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

data Step = StepL | StepR
  deriving (Show, Eq)

你的原始search实现存在重复调用searchHelper的问题:每次判断左/右子树搜索结果是否有效时,会先执行一次递归调用,确认非空后又重复执行一次完全相同的调用,既浪费计算资源,代码也不够简洁。

方案1:用let绑定缓存递归结果

通过let绑定把左子树的搜索结果缓存起来,之后直接复用这个结果即可,无需重复调用:

searchHelper :: Eq a => a -> Tree a -> [Step] -> Maybe [Step]
searchHelper _ Empty _ = Nothing
searchHelper targetValue (Node nodeValue leftChild rightChild) stepsSoFar
  | targetValue == nodeValue = Just stepsSoFar
  | otherwise =
      let leftResult = searchHelper targetValue leftChild (stepsSoFar ++ [StepL])
      in case leftResult of
           Just _ -> leftResult
           Nothing -> searchHelper targetValue rightChild (stepsSoFar ++ [StepR])

search :: Eq a => a -> Tree a -> Maybe [Step]
search targetValue root = searchHelper targetValue root []

方案2:利用Maybe的Alternative特性(更简洁)

Maybe类型是Alternative类型类的实例,<|>操作符会优先返回左侧的Just值,若左侧为Nothing则返回右侧结果。借助这个特性可以写出更简洁的代码:

searchHelper :: Eq a => a -> Tree a -> [Step] -> Maybe [Step]
searchHelper _ Empty _ = Nothing
searchHelper targetValue (Node nodeValue leftChild rightChild) stepsSoFar
  | targetValue == nodeValue = Just stepsSoFar
  | otherwise = leftResult <|> rightResult
  where
    leftResult = searchHelper targetValue leftChild (stepsSoFar ++ [StepL])
    rightResult = searchHelper targetValue rightChild (stepsSoFar ++ [StepR])

search :: Eq a => a -> Tree a -> Maybe [Step]
search targetValue root = searchHelper targetValue root []

额外优化:提升路径构建效率

原代码中用++拼接列表效率较低(因为++需要遍历整个左侧列表),可以改为在列表头部添加步骤,最后找到目标节点时反转路径:

searchHelper :: Eq a => a -> Tree a -> [Step] -> Maybe [Step]
searchHelper _ Empty _ = Nothing
searchHelper targetValue (Node nodeValue leftChild rightChild) stepsSoFar
  | targetValue == nodeValue = Just (reverse stepsSoFar)
  | otherwise = leftResult <|> rightResult
  where
    leftResult = searchHelper targetValue leftChild (StepL : stepsSoFar)
    rightResult = searchHelper targetValue rightChild (StepR : stepsSoFar)

search :: Eq a => a -> Tree a -> Maybe [Step]
search targetValue root = searchHelper targetValue root []

内容的提问来源于stack exchange,提问作者coderodde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:20:28