繁体   English   中英

如何在 Haskell 中的列表上实现尾递归以生成子列表?

[英]How can I implement Tail Recursion on list in Haskell to generate sublists?

我想让 bigersort function 在列表的尾部递归地重新调用自己。 我下面的代码有效并为我提供了以下 output:

[6,7,8]

我想继续从 3 开始 next 然后 1.. 到最后一个元素。

我想要的是这样的:

[[6,7,8],[3,5,7,8],[1,5,7,8]..]

我的代码:

 import Data.List
 import System.IO
  biggersort :: Ord a => [a] -> [a]
  biggersort []     = []
  biggersort (p:xs) =  [p] ++ (biggersort greater) 
  where
    greater = filter (>= p) xs

  main = do
  print $ biggersort [6,3,1,5,2,7,8,1]

您可以使用tails从每个 position 开始访问列表,因此根据您拥有的 function,您想要的 function 的一个特别简洁的实现是:

biggersorts = map biggersort . tails

不过,此实现有一个非常明显的缺点(和一个不太明显的缺点)。 明显的缺点是在处理较长列表时会重复对较短列表的计算,从而导致 O(n^2) 最佳情况时间; 不太明显的缺点是结果列表的元素之间没有 memory 共享,导致 O(n^2) 最坏情况 memory 的使用。 这些界限可以改进为 O(n) 平均情况/O(n^2) 最坏情况时间*和 O(n) 最坏情况 memory 用法。

这个想法是从列表的末尾开始,向前面构建。 在每一步,我们都会查看所有 rest 个结果,看看是否有一个我们可以重复使用。 所以:

biggersorts :: Ord a => [a] -> [[a]]
biggersorts [] = [[]]
biggersorts (a:as) = (a:as') : rec where
    as' = fromMaybe [] (find bigger rec)
    rec = biggersorts as
    bigger (a':_) = a <= a'
    bigger _ = False -- True is also fine

请注意,由于共享,公平比较这两者的性能可能会很棘手。 全面评估这个 function 的 output 的常用技巧并不能很好地分享; 所以写一些明显完全评估输出但也访问每个子项 O(1) 次的东西是很棘手的(我认为后一个属性是显而易见的不太重要)。 最明显的方法(对我来说)涉及使用一些稍微高级的技术重写这两个函数,所以我将在这里省略它。

*似乎应该可以将其改进为 O(n*log(n)) 最坏情况时间。 在递归过程中,构建cache:: Map a [a]到 go 与rec:: [[a]] ; cache的直觉是它告诉rec在每个现有“边界”值处a哪个元素。 在每一步更新缓存都涉及将其拆分为当前值并丢弃下半部分。

我发现这个变体的平均案例时间分析更难; 还是O(n)吗? Map在此变体运行期间的平均大小似乎是 O(1),但我无法说服自己相信这个猜测。 如果不是,是否有另一种变体可以实现 O(n) 平均情况/O(n*log(n)) 最佳情况? ...有 O(n) 最坏情况吗? (可能用于限制排序运行时的相同计数参数将此排除...?)

不知道!

您可以制作一个 function,它将使用biggersort作为助手 function,因此:

biggersort :: Ord a => [a] -> [a]
biggersort [] = []
biggersort (p:xs) =  p : biggersort (filter (>= p) xs)

biggersorts :: Ord a => [a] -> [[a]]
biggersorts [] = []
biggersorts xa@(_:xs) = biggersort xa : biggersorts xs

main = print (biggersorts [6,3,1,5,2,7,8,1])

然后打印:

Prelude> biggersorts [6,3,1,5,2,7,8,1]
[[6,7,8],[3,5,7,8],[1,5,7,8],[5,7,8],[2,7,8],[7,8],[8],[1]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM