首页 > 代码库 > 关于length

关于length

写Scheme代码时,经常要判断表的长度。长度为0时一个操作,长度为1时,另一个操作,长度为2时,第三种操作 ...。最容易想到的方法是(define (length=? m l)  (= m (length l)))但这个 length=? 很低效。它要先计算表的长度n。length 的复杂度是O (n),。这个函数的复杂度也是O (n)。改进一实际上表的长度等不等于m,在计算表的长度*时*,就可以确定,不必等到计算表的长度*后*。【不多不少原则】length 可以这样写(define (length l)  (if (null? l)      0      (+ 1 (length (cdr l)))))要在计算 length 的时候就判断其长度是否等于 m ,就可以这样写(define (length=? m l)  (if (null? l)      (zero? m)      (length=? (- m 1) (cdr l))))[根据 length 来写 length=? 是很简单的小技巧]改进二上面的改进是考察表的长度得到的。这里我们把另外一参数 m 也考虑进去。高效的 length=? 的复杂度应该是 min (m,n)。也就是说当m比n小时,m步就可以判定了。(define (length=? m l)  (cond ((null? l) (zero? m))        ((zero? m) #f)        (else (length=? (- m 1) (cdr l)))))类似地,要判断表的长度是否相等就可以这样(define (same-length? l1 l2)  (cond ((null? l1) (null? l2))        ((null? l2) #f)        (else (same-length? (cdr l1) (cdr l2)))))如果要判断两个以上的表的长度是否相等呢?方法应该还是一样的。1. 如果其中一个表是空表,看其他表是否也都是空表。2. 否则去掉所有表的头部,递归。这就要两个辅助函数 any? 和 all?(define (any? p? ls)  (define anyloop    (lambda (ls)      (if (null? ls)          #f          (if (p? (car ls))              #t              (anyloop (cdr ls))))))  (anyloop ls))(define (all? p? ls)  (define allloop    (lambda (ls)      (if (null? ls)          #t          (if (not (p? (car ls)))              #f              (allloop (cdr ls))))))  (allloop ls))(define (same-length? l1 l2 . ls)  (define args (cons l1 (cons l2 ls)))  (cond ((any? null? args)         (all? null? args))        (else          (apply same-length?                (map cdr args)))))不过这个函数的复杂度,我就不愿意分析了,因为不会呵呵。length=? 也可以作类似扩展。

 

关于length