Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell树中查找最接近整数参数的键_Haskell_Functional Programming_Binary Search Tree - Fatal编程技术网

在Haskell树中查找最接近整数参数的键

在Haskell树中查找最接近整数参数的键,haskell,functional-programming,binary-search-tree,Haskell,Functional Programming,Binary Search Tree,在命令式语言中,如何在二叉树中找到最接近的上下键有很多解决方案,但在Haskell这样的纯函数式风格中,缺少相同的问题。我很想知道,在遇到两个最近的键之前,如何绕过一棵二叉树。到目前为止,我已经完成了一个函数和一些模式匹配: data TreeMap v = Leaf | Node { pair::(Integer, v), l::TreeMap v, r::TreeMap v} deriving (Show, Read, Eq, Ord) closestLess :: Integer -&g

在命令式语言中,如何在二叉树中找到最接近的上下键有很多解决方案,但在Haskell这样的纯函数式风格中,缺少相同的问题。我很想知道,在遇到两个最近的键之前,如何绕过一棵二叉树。到目前为止,我已经完成了一个函数和一些模式匹配:

data TreeMap v = Leaf | Node { pair::(Integer, v), l::TreeMap v, r::TreeMap v} deriving (Show, Read, Eq, Ord)

closestLess :: Integer -> TreeMap v -> (Integer, v)
closestLess i Leaf = error "Tree doesn't include any element"
closestLess i (Node pair tree_r tree_l)
        | i < fst pair = closestLess i tree_l
        | i == fst pair = closestLess i tree_r
        | otherwise = precise i pair tree_r 
data TreeMap v=Leaf | Node{pair::(整数,v),l::TreeMap v,r::TreeMap v}派生(显示,读取,Eq,Ord)
无闭::整数->树映射v->(整数,v)
closestLess i Leaf=错误“树不包含任何元素”
无闭i(节点对树\u r树\u l)
|i
我使用这个函数来获取一个较低的键,但最接近整数参数。在我看来,除了实现“精确”这样的辅助功能外,没有别的必要,尽管我不清楚它到底需要什么定义。我的建议是将整数值节点放入“精确”的右子树中,也可以找到离目标最近的任何键。因此,我会有一些提示或假设,如何使它为较低和较高的关键以及

以下是我的做法:

data TreeMap v = Leaf | Node Integer v (TreeMap v) (TreeMap v) deriving (Show, Read, Eq, Ord)

closestLess :: Integer -> TreeMap v -> Maybe (Integer, v)
closestLess i = precise Nothing where
  precise :: Maybe (Integer, v) -> TreeMap v -> Maybe (Integer, v)
  precise closestSoFar Leaf = closestSoFar
  precise closestSoFar (Node k v l r) = case i `compare` k of
    LT -> precise closestSoFar l
    EQ -> Just (k, v)
    GT -> precise (Just (k, v)) r
关于此操作与您的尝试之间的差异,请注意以下几点:

  • 您为
    节点
    构造函数使用了记录语法。在sum类型上使用记录语法是一种糟糕的形式,因为这样函数将是部分函数(例如,
    pairleaf
    将位于底部)。因为你实际上没有使用这些,而且它们也不是必需的,所以我把它们拿走了
  • 您将键和值包装在一个元组中,没有明显的原因。我把它们分开,直接放在打字机上
  • 您的
    closestLess
    函数的返回类型为
    (Integer,v)
    ,尽管它不能始终返回该类型的内容。我将它改为
    Maybe(Integer,v)
    ,这样它就可以返回
    Nothing
    ,而不必使用
    error
    。(旁注:您的错误消息在技术上是错误的。如果在搜索值小于所有节点的情况下调用
    closestLess
    ,则即使树中有元素,也会失败。)
  • 您的代码在节点的左分支和右分支方面不一致。在我的代码中,左分支始终是数据构造函数中位于左侧的分支
  • 您在单独的保护中使用了
    i
    i==fst对
    。通过对
    compare
    的输出进行大小写匹配,您只需执行一次而不是两次比较
  • 您需要一个
    精确的
    功能,这是正确的,但是
    无触点
    中的许多逻辑实际上需要在其中
下面是一个快速测试用例,使用您链接的站点上的示例:

Prelude> tree = Node 9 () (Node 4 () (Node 3 () Leaf Leaf) (Node 6 () (Node 5 () Leaf Leaf) (Node 7 () Leaf Leaf))) (Node 17 () Leaf (Node 22 () (Node 20 () Leaf Leaf) Leaf))
Prelude> closestLess 4 tree
Just (4,())
Prelude> closestLess 18 tree
Just (17,())
Prelude> closestLess 12 tree
Just (9,())
Prelude> closestLess 2 tree
Nothing

您还可以让它变得更懒惰(只要找到一个候选者,就产生外部的
,代价是变得更复杂:

import Data.Functor.Identity data TreeMap v = Leaf | Node Integer v (TreeMap v) (TreeMap v) deriving (Show, Read, Eq, Ord) closestLess :: Integer -> TreeMap v -> Maybe (Integer, v) closestLess i = precise Nothing where precise :: Applicative t => t (Integer, v) -> TreeMap v -> t (Integer, v) precise closestSoFar Leaf = closestSoFar precise closestSoFar (Node k v l r) = case i `compare` k of LT -> precise closestSoFar l EQ -> pure (k, v) GT -> pure . runIdentity $ precise (Identity (k, v)) r 导入Data.Functor.Identity 数据树映射v=叶|节点整数v(树映射v)(树映射v)派生(显示、读取、等式、Ord) 无闭::整数->树映射v->可能(整数,v) 无闭合i=精确无 哪里 精确::应用程序t=>t(整数,v)->树映射v->t(整数,v) 精确的closestSoFar叶=closestSoFar 精确闭合时间(节点k v l r)=案例i`compare`k of LT->精确关闭至左侧 等式->纯(k,v) GT->pure。runIdentity$precise(Identity(k,v))r
有关它的更多详细信息,请参阅。

我不知道您希望
precise
函数做什么。此外,避免在纯函数中抛出
错误
s,而是为结果找到更好的表示形式(如使用
Maybe
)您是否可以发布一个有效的
最接近的下键的命令式版本
,以便我们能够确切地了解您希望haskell版本做什么?按照@Bergi的请求,我添加了类型定义。对不起mistake@Bergi我需要解决的问题是,正如本教程中C++程序员所说的,我认为你可以很好地遵循他们的算法——除了那些怪异的、可变的<代码> MimoDIFI和 MimiDeopyKyth参数,更糟糕的是,它还有一些无值值,如
MAX\u INTEGER
-1
。编写一个函数
Integer->TreeMap v->Maybe(Integer,v)->Maybe(Integer,v)
,其中包含参数
searchValue
tree
,以及
closestSoFar
。它工作得非常好,谢谢。事实上,这是对这个案例解决方案的一个非常出色的解释——作为函数式编程的新手,我非常感谢您对所有这些的评论和结论。