我注意到Scheme和Lisp(我猜)支持循环列表,并且我在C/C++中使用循环列表来“简化”元素的插入和删除,但是它们有什么用处?
Scheme确保它们可以构建和处理,但是用于什么目的?
是否存在需要循环或尾循环的“杀手级”数据结构?
我注意到Scheme和Lisp(我猜)支持循环列表,并且我在C/C++中使用循环列表来“简化”元素的插入和删除,但是它们有什么用处?
Scheme确保它们可以构建和处理,但是用于什么目的?
是否存在需要循环或尾循环的“杀手级”数据结构?
(#0=(1 2) (x y . #0#))
;此外,Scheme的list?
谓词指定循环列表不是列表——或者这是特定实现的结果? - philcolbournset-car!
和 set-cdr!
操作来改变该列表。 - philcolbourn你曾经玩过大富翁吗?
如果不考虑使用符号、模数等游戏元素,如何在计算机实现中表示大富翁棋盘呢?一个循环列表是很自然的。
在列表的开头添加和删除元素是廉价的。要从列表的末尾添加或删除元素,您必须遍历整个列表。
使用循环列表,您可以拥有一种固定长度的队列。
设置一个长度为5的循环列表:
> (import (srfi :1 lists))
> (define q (circular-list 1 2 3 4 5))
让我们向列表中添加一个数字:
> (set-car! q 6)
> (set! q (cdr q))
> (take q 5)
(2 3 4 5 6)
因此,您可以将其视为一个队列,在此队列中,元素从列表末尾进入并从头部移除。
让我们将7添加到列表中:
> (set-car! q 7)
> (set! q (cdr q))
> (take q 5)
(3 4 5 6 7)
无论如何,这是我使用循环列表的一种方式。
我在一个OpenGL演示中使用了这种技术,该演示是我从Processing书籍中的一个示例移植而来。
Ed
例如,双向链表数据结构在Scheme/LISP的视角中是“循环”的,即如果您尝试将cons结构输出打印出来,则会得到反向引用,即“循环”。因此,它实际上不是关于具有看起来像“环”的数据结构,任何具有某种类型的反向指针的数据结构都是从Scheme/LISP的角度来看是“循环”的。
“正常”的LISP列表是单向链表,这意味着从列表中删除项目的破坏性突变是O(n)操作;对于双向链表,它是O(1)。这是双向链表的“杀手功能”,在Scheme/LISP上下文中是“循环”的。
val
添加到lst
的每个元素中,我们可以编写以下代码:(map + (circular-list val) lst)
例如:
(map + (circular-list 10) (list 0 1 2 3 4 5))
返回:
(10 11 12 13 14 15)
+
替换为(lambda (x) (+ x val))
来实现此目的,但有时上述习惯用法可能更方便。请注意,这仅适用于srfi-1版本的map,该版本可以接受不同大小的列表。