Haskell,插入有序列表

时间:2016-03-18 17:07:49

标签: list haskell nodes

我开始了解Haskell并一直密切关注http://learnyouahaskell.com的指南和https://wiki.haskell.org/How_to_work_on_lists的文档。我最近一直在使用节点和二叉树,并遇到了一个我似乎无法找出正确语法的问题。

如果我有一个有序的节点列表:

[(2 , Nil, Nil), (4, Nil, Nil), (10, Nil, Nil)]

我想在列表中插入一个新节点(3, Nil, Nil),以便它可以表示为:

[(2, Nil, Nil), (3, Nil, Nil),(4, Nil, Nil), (10, Nil, Nil)]

这样做最优雅的解决方案是什么?从我所看到的here看来,一旦检测到正确的位置,你就必须将列表分成两部分,但作为初学者,我不知道如何做到这一点。显然,伪代码将是For every Node in the list, compare its number value versus the count value of the new Node . Once this value is greater than or equal to the current index, split the list into two parts (a and b) and then combine the list in this order a ++ [newElement] ++ b

的一长串

在我的脑海中(再次,在初学者级别)尝试实现它时,它看起来像:

sortedInsert

3 个答案:

答案 0 :(得分:3)

模式匹配是常用的。

这是一般情况:

insertOrdered :: Ord a => a -> [a] -> [a]
insertOrdered a [] = [a]
insertOrdered a bs'@(b:bs)
  | a <= b     = a : bs'
  | otherwise = b : insertOrdered a bs

轮到你了:用你的一些代码替换undefined;)

注意

  • 无论Nil是什么,你必须使它成为Ord的实例,或者你必须更改函数才能直接处理元组的第一个组件

我选择使用:

data Nil = Nil
         deriving (Show, Eq, Ord)

它将按原样运行:

λ> let xs = [(2 , Nil, Nil), (4, Nil, Nil), (10, Nil, Nil)]
λ> insertOrdered (3,Nil,Nil) xs
[(2,Nil,Nil),(3,Nil,Nil),(4,Nil,Nil),(10,Nil,Nil)]

但也许你必须为此改变这个:

insertOrdered :: Ord a => (a,b,c) -> [(a,b,c)] -> [(a,b,c)]
insertOrdered x [] = undefined
insertOrdered x@(a,_,_) ((a',_,_):ys)
  | a <= a'   = undefined
  | otherwise = undefined -- probably something with insertOrdered?

答案 1 :(得分:1)

我建议从简单列表开始,比如Nums列表。这是一个在列表中插入成员的函数,只要可以比较元素:

insertOrdered :: Ord a => a -> [a] -> [a]   -- Ord means the elements of the list can be ordered
insertOrdered item [] = [item]              -- Empty list, return list with a single argument
insertOrdered item (first:ls)               -- Split list between first element and the rest of it
    | item <= first = item : first : ls     -- Append our item at the start and merge everything
    | otherwise = first : (insertOrdered item ls)   -- Merge the first element with the result of calling this again

您可以立即使用以下内容进行测试:

insertOrdered 1 [0, 2, 3]    -- [0, 1, 2, 3]

现在它适用于简单的情况,你可以考虑你的难度。这意味着告诉Haskell您可以订购您输入的内容以及如何操作,您可以学习here

答案 2 :(得分:0)

我的建议看起来很像Carsten's,但我认为使用辅助go函数来避免必须手动传递x参数更好一些常:

insertOrdered :: Ord a => x -> [a] -> [a]
insertOrdered x = go where
  go [] = [x]
  go all@(y:ys) | x < y = x : all
                | otherwise = y : go ys