如何从链接列表中删除第n个元素?

时间:2018-02-05 19:23:50

标签: haskell

如何从链接列表中删除第n个元素?

import Data.List 

data LinkedList = LLEmpty  | LLNode Int LinkedList deriving (Eq, Show, Ord)                 

在第n个位置插入一个整数

linkListInsertNPosition :: Int -> Int -> LinkedList -> LinkedList                       
linkListInsertNPosition pos val listL =
    let ninsertion = insertionN val (lengthL listL - pos) listL
        in ninsertion

insertionN :: Int -> Int -> LinkedList -> LinkedList           
insertionN val count listL =
    case listL of
        LLEmpty -> LLEmpty
        (LLNode a b) -> if (count <=0)
                            then LLNode val (LLNode a b)
                       else LLNode a (insertionN val (count - 1) b)            

最后,链接列表的尾部和头部

lastL :: LinkedList -> Int                             
lastL listL =
    case listL of
        LLNode a b -> a

tailL :: LinkedList -> LinkedList                   
tailL listL =
    case listL of
    LLEmpty -> LLEmpty
    LLNode a b -> b

headL :: LinkedList -> Int                   --100
headL listL =
case listL of 
    LLNode a LLEmpty -> a
    LLNode a b -> headL (tailL b)

获取链表的长度

lengthL :: LinkedList -> Int                    
lengthL listL =
case listL of
    LLEmpty -> 0
    LLNode a b -> 1 + (lengthL (tailL listL))

我一直在删除链接列表中的第n个元素。任何人都可以帮助我并建议一种方式。 删除第n个元素后如何加入链接列表?或者我需要做一个新的链接列表?

3 个答案:

答案 0 :(得分:2)

链接列表LListEmpty或包含值和另一个链接列表。

data LList a = Empty | Node a LList

如果我们为内置(:)链接列表定义一个运算符(如[]),这可能会更容易

data LList a = Empty | a :+: LList
--   much like:
-- data [a]  = []    | a :   [a]

您的列表具体为Int s,因此我们可以删除多态性

data LList = Empty | Int :+: LList
  deriving (Eq, Show, Ord)

-- and, useful for testing:
fromList :: [Int] -> LList
fromList = foldr (:+:) Empty

n之后插入只是推送链接列表n次并在此时重新链接。

import Data.Either (partitionEithers)
-- partitionEithers :: [Either a b] -> ([a], [b])

-- fun fact, I had to look this one up, but this is how haskell implements (++)
(|++|) :: LList -> LList -> LList
Empty    |++| ys    = ys
xs       |++| Empty = xs
(x:+:xs) |++| ys    = x :+: (xs |++| ys)

mySplitAt :: Int -> LList -> (LList, LList)
mySplitAt n = partitionEithers . map (go n) . zip [0..]
  where
  go n (i, x) | i < n     = Left x
              | otherwise = Right x

insertAfter :: Int -> Int -> LList -> LList
insertAfter n x xs = before |++| (x :+: after)
  where (before, after) = mySplitAt n xs

这意味着删除第n个值只是在特定节点之后重新链接

delete :: Int -> LList -> LList
delete n xs = before |++| after
  where (before, _ :+: after) = mySplitAt n xs

答案 1 :(得分:1)

也许这会给你一些想法

Prelude> let removeAt n = map snd . filter ((/=n) . fst) . zip [1..]
Prelude> removeAt 3 [1..10]
[1,2,4,5,6,7,8,9,10]

要么可以递归计算位置,要么使用zip添加索引并处理该索引。

答案 2 :(得分:0)

你可以这样做。

removeNth :: Int -> [a] -> [a]
removeNth n ls = let (pref, suff) = splitAt n ls
                 in  pref ++ (tail suff)