从第一个元素列表数据结构进行功能 O(1) 追加和 O(n) 迭代
我正在寻找一种支持以下操作的函数式数据结构:
- 追加,O(1)
- 按顺序迭代,O(n)
普通函数链表仅支持 O(n) 追加,而我可以使用普通的 LL 和然后反转它,反转操作将是 O(n) ,这也(部分)否定 O(1) cons 操作。
I'm looking for a functional data structure that supports the following operations:
- Append, O(1)
- In order iteration, O(n)
A normal functional linked list only supports O(n) append, while I could use a normal LL and then reverse it, the reverse operation would be O(n) also which (partially) negates the O(1) cons operation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用 John Hughes 的常量时间附加列表,现在它被称为
DList
。表示是一个从列表到列表的函数:空列表是恒等函数;附加是组合,单例是缺点(部分应用)。在此表示中,每个枚举都会花费您n
次分配,因此这可能不太好。另一种方法是使用与数据结构相同的代数:
枚举是树遍历,这将花费一些堆栈空间或需要某种拉链表示。这是一个转换为列表但使用堆栈空间的树遍历:
这是相同的,但使用常量堆栈空间:
您可以编写一个访问相同元素但实际上并不具体化列表的折叠函数;只需用更通用的东西替换 cons 和 nil :
这就是你的线性时间、常量堆栈枚举。玩得开心!
You can use John Hughes's constant-time append lists, which seem nowadays to be called
DList
. The representation is a function from lists to lists: the empty list is the identity function; append is composition, and singleton is cons (partially applied). In this representation every enumeration will cost youn
allocations, so that may not be so good.The alternative is to make the same algebra as a data structure:
Enumeration is a tree walk, which will either cost some stack space or will require some kind of zipper representation. Here's a tree walk that converts to list but uses stack space:
Here's the same, but using constant stack space:
You can write a fold function that visits the same elements but doesn't actually reify the list; just replace cons and nil with something more general:
That's your linear-time, constant-stack enumeration. Have fun!
我相信你可以只使用标准函数链表:
(即 O(N)),然后遍历它,这也是 O(N) (并且 2xO(N) 仍然只是O(N))。
I believe you can just use standard functional linked list:
(which is O(N)) and then traverse it, which is also O(N) (and 2xO(N) is still just O(N)).
差异清单怎么样?
How about a difference list?
您可以创建一个函数式双端队列,它提供
O(1)
添加到任一端,以及O(N)
进行任一方向的迭代。 Eric Lippert 写了一篇关于不可变双端队列的有趣版本 在他的博客上请注意,如果您环顾四周,您会发现该系列的其他部分,但这是对最终产品的解释。另请注意,通过一些调整,可以将其修改为利用 F# 可区分联合和模式匹配(尽管这取决于您)。此版本的另一个有趣的属性,
O(1)
从任一端查看、删除和添加(即 dequeueLeft、dequeueRight、dequeueLeft、dequeueRight 等,仍然是 O(N),而 O( N*N),采用双列表方法)。You could create a functional Deque, which provides
O(1)
adding to either end, andO(N)
for iteration in either direction. Eric Lippert wrote about an interesting version of an immutable Deque on his blog note that if you look around you will find the other parts of the series, but that is the explanation of the final product. Note also that with a bit of tweaking it can be modified to utilize F# discriminated unions and pattern matching (although that is up to you).Another interesting property of this version,
O(1)
peek, removal, and add, from either end (i.e. dequeueLeft, dequeueRight, dequeueLeft, dequeueRight, etc. is still O(N), versus O(N*N) with a double list method).循环链表怎么样?它支持 O(1) 追加和 O(n) 迭代。
What about a circularly-linked list? It supports O(1) appends and O(n) iteration.