首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell树分割:有人能解释一下这行吗?

Haskell树分割:有人能解释一下这行吗?
EN

Stack Overflow用户
提问于 2013-04-29 04:29:45
回答 1查看 724关注 0票数 19
代码语言:javascript
复制
split s (Root x lst rst)
 | s < x = let (nlt, nrt) = split s lst in
     (nlt, Root x nrt rst)

有人能解释一下这条线吗?我真的不理解let的部分。

我试着想一想,我不知道我是否做对了:我们将(nlt, nrt)绑定到split s lst的结果上;split s lst本身将是(nlt, Root x nrt rst)

是这样吗?

下面是完整的代码:

代码语言:javascript
复制
split :: Ord a => a -> Tree a -> (Tree a, Tree a)
split _ Empty = (Empty, Empty)
split s (Root x lst rst)
 | s < x = let (nlt, nrt) = split s lst in
     (nlt, Root x nrt rst)
 | s > x = let (nlt, nrt) = split s rst in
         (Root x lst nlt, nrt)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-29 04:34:23

我们将(nlt, nrt)绑定到split s lst的结果

Yup - split s lst是一个对,我们给这对中的两个元素分别命名为nltnrt

split s lst本身将是(nlt, Root x nrt rst)

不,split s (Root x lst rst) (整个函数的结果)将为(nlt, Root x nrt rst)

但是整个函数做了什么呢?

代码语言:javascript
复制
split :: Ord a => a -> Tree a -> (Tree a, Tree a)
split _ Empty = (Empty, Empty)
split s (Root x lst rst)
 | s < x = let (nlt, nrt) = split s lst in
     (nlt, Root x nrt rst)
 | s > x = let (nlt, nrt) = split s rst in
         (Root x lst nlt, nrt)

让我们在一些示例数据上尝试一下:

代码语言:javascript
复制
> split 300 (Root 512 (Root 256 (Root 128 Empty Empty) (Root 384 Empty Empty)) Empty)
(Root 256 (Root 128 Empty Empty) Empty,Root 512 (Root 384 Empty Empty) Empty)

因此,我们选取一棵以512为根的树,并将左子树中所有小于512的条目拆分,以便第一棵树由小于300的条目组成,而在第二棵树中包含大于300的条目。它看起来像这样:

这条线路是如何工作的?

首先,让我们用扩展名称重写代码:

代码语言:javascript
复制
split :: Ord a => a -> Tree a -> (Tree a, Tree a)
split _ Empty = (Empty, Empty)
split s (Root x left_subtree right_subtree)
 | s < x = let (new_left_tree, new_right_tree) = split s left_subtree in
     (new_left_tree, Root x new_right_tree right_subtree)
 | s > x = let (new_left_tree, new_right_tree) = split s right_subtree in
         (Root x left_subtree new_left_tree, new_right_tree)

guard |s < x意味着我们在这个x应该在右边的情况下。

首先,我们拆分左子树split s left_subtree,给我们一个new_left_treenew_right_treenew_left_tree是应该放在左边的东西,但是new_right_treex和原始right_subtree组合在一起,组成了s右边的部分。

我们可以从这个函数中学到什么呢?

right_subtree不会出现,因为s属于x的左侧,所以该函数假定树已经排序,在Root x l r中,l中的所有内容都在x之下,而r中的所有内容都在x之上。

left_subtree被拆分,因为其中一些位可能小于s,而其他位可能大于s

现在属于右侧的split s left_subtree部分(因为它比s更多)称为new_right_tree,并且因为整个left_subtree小于xright_subtree,所以所有new_right_tree仍然应该位于xright_subtree的左侧。这就是为什么我们让Root x new_right_tree right_subtree作为对中的右手答案( new_left_tree在对中的左边)。

这是一个前后关系图:

那么为什么不使用更具描述性的名称呢?

问得好。让我们开始吧:

代码语言:javascript
复制
split :: Ord a => a -> Tree a -> (Tree a, Tree a)
split _ Empty = (Empty, Empty)
split s (Root this below_this above_this)

 | s < this = let (below_this_below_s, below_this_above_s) = split s below_this in
     (below_this_below_s,  Root  this  below_this_above_s  above_this)

 | s > this = let (above_this_below_s, above_this_above_s) = split s above_this in
         (Root  this  below_this above_this_below_s,  above_this_above_s)

好吧,我想这回答了我的问题:有时描述性名称也会让人感到困惑!

票数 43
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16267497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档