【问题标题】:Finding a leaf with value x in a binary tree在二叉树中查找值为 x 的叶子
【发布时间】:2012-11-11 11:07:46
【问题描述】:

我有这个问题要做:

"定义一个函数findpath:: BTree a -> a -> Path(其中Btree a 定义如前面的问题),给定二叉树t 和值x,返回从t 的根开始的路径如果有一个叶子,则值为x,否则值为Nothing。程序的运行时间应该与树中的节点数成线性关系。"

到目前为止我有:

data Maybe a = Nothing | Just a
data BTree a = Leaf a | Fork (BTree a) (BTree a)
type Path = Maybe [Dir]
data Dir = Left | Right

findpath :: Eq a => BTree a -> a -> Path
findpath (Leaf y) x = if y==x then ??? else Nothing
findpath (Fork l r) x = nodepath (findpath l x) (findpath r x) where
   nodepath :: Path -> Path -> Path
   nodepath Nothing Nothing = Nothing
   nodepath Nothing pathr = Just [R]
   nodepath pathl Nothing = Just [L]

我仍然无法在(Leaf y) 案例中构建最终答案

【问题讨论】:

  • 您的findpath 类型表明它返回[Dir],它不是接受值Nothing 的类型。该问题表明findpath 应该返回Path,即Maybe [Dir],考虑到失败的可能性。我还想知道类型是否应该是findpath :: Eq a => BTree a -> a -> Path,这将允许您测试您寻求的值是否等于存储在树的叶子中的值。
  • 是的,我认为类型签名中也应该有一个 Eq a。

标签: haskell tree binary-tree


【解决方案1】:

你的语言,关于你认为程序应该做什么,向我暗示你需要帮助才能摆脱命令式思维的陷阱。让我试着提供一些帮助,基于对事物是的思考,而不是事物做什么。

对于findpath (Leaf y) x,您正朝着正确的方向前进。你只需要给if 一个小写的i,然后想想Leaf 的正确Path 必须是什么。

现在,让我们考虑另一种可能性。你知道的不仅仅是t。你知道你真的想弄清楚是什么

findpath (Node l r) x

是(确实是=),因为这是BTree 的另一种可能性。考虑通过询问“这是BTree 和(Leaf y) 还是(Node l r)?”来拆分问题。作为程序设计的一个概念步骤。现在,为了弄清楚上面的左侧等于什么,您有权获得一些递归计算的信息,即什么

findpath l x

和

findpath r x

是。如果您知道l 和r 的Path 信息,您能说出整个Node l r 的Path 是什么吗?让我用 Haskell 来改写这个问题:

findpath :: Eq a => BTree a -> a -> Path
findpath (Leaf y)   x = if y==x then ??? else Nothing
findpath (Node l r) x = nodepath (findpath l x) (findpath r x) where
  nodepath :: Path -> Path -> Path
  nodepath ???

我通过引入一个 帮助函数 nodepath 表达了我的问题,该函数将递归计算的信息作为参数。现在您可以尝试通过模式匹配分别为左右子树的这两条路径来实现nodepath。如果你知道它们是(Just p) 还是Nothing,那么你应该能够说出整个节点的路径必须是什么。

第一课,有用的思想是这样的形式:“如果这是某某,那么那一定是某某。”。存在,不做。

第二课,对数据类型进行编程的基本方法是:拆分为构造函数案例(Leaf vs Node,Just vs Nothing);通过递归调用从任何子结构中收集有用的信息;说出整个结构的价值必须是什么。

如果您遵循我的建议并弄清楚nodepath 应该是什么,您可能会发现它足够简单,不值得单独命名定义。在这种情况下,只需将nodepath 调用替换为其含义并删除where 子句。但最好从引入nodepath 开始,因为它表达了解决问题的一个有用的概念性步骤。

【讨论】:

  • 感谢您的回答。你的观察很准确。我在命令式语言方面做了很多工作,但是这门函数式编程课程对我来说是一场真正的艰苦战斗。
  • 我已经按照你说的修改了程序,但我还是有点卡住了。我对新代码提出了问题,您能再看一下吗?
  • 嗯,这当然是进步。您现在需要的是,在成功的Leaf 案例的输出中,以及成功的路径-来自-children 的模式中,使用Just、Maybe 的构造函数来成功。那么对于Leaf 的情况,想一想“如果整棵树就是这片叶子,那么路径是什么?”。在nodepath 的模式中,使用Just 可以让您掌握从成功子节点到相关叶节点的步骤列表:您可以使用它来构建父节点Node 的步骤列表,其中到目前为止,您只是迈出了第一步。
猜你喜欢
  • 2016-01-24
  • 1970-01-01
  • 2019-11-21
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多