在haskell中反转列表

t3psigkw  于 2022-11-30  发布在  其他
关注(0)|答案(7)|浏览(212)

我在试着把名单倒过来。
下面是我的代码:

reverseList :: [Int] -> [Int]
reverseList [] = []
reverseList (x:xs) =  x:reverseList xs

最后发生的事情是我最终得到了相同顺序的列表。我甚至有一个解决方案,如何扭转列表,但我试图了解我在这里做错了什么?我是非常新的haskell所以认为我应该专注于了解更多,然后我可以轻松地解决更多的问题。我知道有很多解决这个问题的方法,但是我需要更多的帮助来理解,特别是我在这段代码中做错了什么。

g6ll5ycj

g6ll5ycj1#

在Haskell中有几种方法可以解决这个问题,最简单的方法是使用连接函数++

reverseList [] = []
reverseList (x:xs) = reverseList xs ++ [x]

然而,这对于大型列表来说会非常慢,因为Haskell列表实际上是单向链表,所以为了追加一个元素,你必须遍历整个列表。另一种选择是在helper函数中跟上你正在构建的列表:

reverseList = go []
    where
        go acc [] = acc
        go acc (x:xs) = go (x:acc) xs

但是,这实际上只是fold模式:

reverseList = foldl (\acc x -> x : acc) []

但是\acc x -> x : acc就是flip (:),所以可以写成

reverseList = foldl (flip (:)) []

然而,最简单的方法可能是在Prelude中使用reverse函数。
我想指出的是,你的reverseList :: [Int] -> [Int]类型可以推广到:: [a] -> [a],你没有对列表的元素做任何特殊的处理,你只是用它们构建一个新的列表。

g0czyy6m

g0czyy6m2#

你把列表分成头和尾,然后按照相同的顺序重新组合列表。以列表[1, 2, 3]为例:
在第一次调用中,x将变为1xs将变为[2, 3],然后创建一个新的列表,其中x(因此为1)位于前面,reverseList [2, 3]位于后面。

0kjbasz6

0kjbasz63#

在Haskell中有几种方法可以解决这个问题。下面是一个带有cons和last/init的解决方案:

reverseList  [] = []
reverseList  xs = last xs : reverseList (init xs)

或使用foldl:

reverseList xs = foldl (\x y -> y:x) [] xs
tyg4sfes

tyg4sfes4#

基本上是使用附加的简单算法

revList [] = []
revList (x:xs) = revList xs ++ [x]

O(n(n-1)/2)~ O(n^2)的时间复杂度是O(n(n-1)/2)~ O(n^2)的时间复杂度是O(n(n-1)/2)~ O(n^2)的时间复杂度。
因此,对于这种附加繁重的任务,存在差异列表数据类型。
一个不同的列表就是一个用函数表示的列表。我的意思是,一个像[1,2,3]这样的列表,当用DList类型表示时,将是\xs -> [1,2,3] ++ xs或简称为([1,2,3] ++)

type DList a = [a] -> [a]

toDList :: [a] -> DList a
toDList xs  = (xs ++ )

fromDList :: DList a -> [a]
fromDList f = f []

这有点酷,因为DList是函数,我们可以通过组合(.)运算符将其追加,得到一个新的DList。换句话说,toDList (xs ++ ys) == (toDList xs) . (toDList ys)
这是一个复杂度为O(n)的问题,因为每一个函数组合都是O(1)的,所以它的时间复杂度为O(n),而每一个函数组合都是O(1)的。

revList' :: [a] -> DList a
revList' []     = toDList []
revList' (x:xs) = revList' xs . toDList [x]

现在我们已经在DList a类型中得到了反向的[a],我们需要应用fromDList

fastReverse :: [a] -> [a]
fastReverse = fromDList . revList'

Difference List数据类型并不像上面所示的那么简单。它可以有Monoid、Functor和MonadT示例。有关这个有用数据类型的更多信息,请查看Data.DList

ctzwtxfj

ctzwtxfj5#

简单。使用内置的reverse函数:

print (reverse [1,2,3,4,5]) -- [5,4,3,2,1]
wnavrhmk

wnavrhmk6#

在Haskell中,使用列表解析定义了反向函数。

rev1::  [a] -> [a]
rev1 xs = [xs !! (length xs - a)  | (a,b) <- zip [1..] xs]
bq8i3lrv

bq8i3lrv7#

此反转功能与累加器和fold1一起工作。

reverse :: [a] -> [a]
reverse  = foldl (\acc x -> x : acc ) []

这个使用递归。

reverse :: [a] -> [a]
reverse (x:xs) = reverse xs ++ [x]

相关问题