是否有内置程序来检查列表是否在Scheme(R5RS)中是循环的?何时列表是循环的(根据定义)?我试图找到一些程序来检查这个,以及它是如何实现的,但我还是找不到。
答案 0 :(得分:2)
如果尾部的cdr
(最后一个元素)指向列表的头部,则列表为circular per definition。但是,您也可以使用循环列表,其中尾部的cdr
指向列表中的任意元素。 A good algorithm检测循环列表是乌龟和野兔算法。 this page给出了一个示例实现。
代码如下(归功于上面链接的页面的作者):
编辑:我修改了代码,因为它包含了Sylwester指出的错误。
(define (has-cycle-h slow-ls fast-ls)
(cond
((null? fast-ls) #f)
((null? (cdr fast-ls)) #f)
((eq? slow-ls fast-ls) #t)
(else (has-cycle-h (cdr slow-ls) (cddr fast-ls)))))
(define (has-cycle? ls)
(cond
((null? ls) #f)
(else (has-cycle-h ls (cdr ls)))))
;; Create cyclic list
(define l (cons 1 (cons 2 (cons 3 (cons 4 '())))))
(set-cdr! (cdr (cdr (cdr l))) l)
;; Results in:
;+---+ +---+ +---+ +---+
;| 1 +--->| 2 +-->| 3 +--->| 4 |
;+-+-+ +---+ +---+ +-+-+
; ^ |
; | |
; +-------------------------+
(has-cycle? l) ; Evaluates to #t
;; Create list
(define l (cons 1 (cons 2 (cons 3 (cons 4 '())))))
;; Make it circular by pointing the tail to the second element.
(set-cdr! (cdr (cdr (cdr l))) (cdr l))
;; Results in:
;+---+ +---+ +---+ +---+
;| 1 +--->| 2 +-->| 3 +--->| 4 |
;+---+ +-+-+ +---+ +-+-+
; ^ |
; | |
; +----------------+
(has-cycle? l) ; Evaluatores to #t
; Regular list
(has-cycle? '(1 1 1 1 1 1 1)) ; Evaluates to #f
没有用于检测循环列表的BIF。
答案 1 :(得分:1)
SRFI 1中有circular-list?
个谓词.SRFI 1中循环列表的定义是:“循环列表是一个值,对于每个n> = 0,cdr ^ n(x)是一对“。这意味着列表没有结尾。第一对循环列表不需要是循环的一部分。最终通过跟随cdrs达到一个循环就足够了。
SRFI 1在非循环列表中有此描述:
(not (circular-list? x)) = (or (proper-list? x) (dotted-list? x))
SRFI 1本身不在R5RS中,但我知道的所有实现都附带了srfi 1。请注意,如果srfi1在运行时中实现,则来自srfi 1的circular-list?
谓词可能比乌龟和野兔算法的Scheme实现更快。对您的选择实施进行基准测试,以了解您的实施行为。