【问题标题】:Procedure to check if list is cyclic (Scheme)检查列表是否循环的过程(方案)
【发布时间】:2015-05-28 23:11:17
【问题描述】:

Scheme (R5RS) 中是否有检查列表是否循环的内置程序?什么时候列表是循环的(根据定义)?我试图找到一些程序来检查这一点,以及它是如何实现的,但我一直找不到。

【问题讨论】:

    标签: list scheme r5rs cyclic


    【解决方案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 实现更快。对您选择的实现进行基准测试,以了解您的实现的行为方式。

    http://srfi.schemers.org/srfi-1/srfi-1.html#circular-list-p

    【讨论】:

      【解决方案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。

      【讨论】:

      • (eq? (car slow-ls) (car fast-ls)) 似乎是错误的。应该是(eq? slow-ls fast-ls)。试试'(#f #f #f)
      • 这似乎是真的。我只是复制粘贴的代码。我会更新的!谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多