用scheme最基本的元素定义排序函数
用到的元素有9个:
define,if,null?,cons car,cdr,lambda,let,named let,
其实let 和 named let可以去掉.但那样会带来性能和可读性下降的问题.
排序类型选的是经典的快速排序.
;筛选函数 (define (filter f x) (let recur ((x x)) (if (null? x) '() (if (f (car x)) (cons (car x) (recur (cdr x))) (recur (cdr x)))))) ;三元合并函数,形如'(1 2) , 3 , '(4 5)合并为'(1 2 3 4 5) (define (merge x y z) (let recur ((x x)) (if (null? x) (cons y z) (cons (car x) (recur (cdr x)))))) ;最原始的排序函数形式(升序) (define (sorted x) (if (null? x) '() (if (null? (cdr x)) x (merge (sorted (filter (lambda (i) (< i (car x))) (cdr x))) (car x) (sorted (filter (lambda (i) (>= i (car x))) (cdr x))))))) ;加入默认参数功能,控制升降序且高性能版本 (define (sort x . y) (let ((lef (if (null? y) < (if (= (car y) 0) < >=))) (rig (if (null? y) >= (if (= (car y) 0) >= <)))) (let recur ((x x)) (if (null? x) '() (let ((fir (car x))(rest (cdr x))) (if (null? rest) x (merge (recur (filter (lambda (i) (lef i fir)) rest)) fir (recur (filter (lambda (i) (rig i fir)) rest))))))))) (sorted '(4 3 2 1 0)) (sort '(4 3 2 1 0) 0) (sort '(4 3 2 1 0)) (sort '(5 6 7 8 9) 1) (sort '(5 6 7 8 9))
结果:
(0 1 2 3 4) (0 1 2 3 4) (0 1 2 3 4) (9 8 7 6 5) (5 6 7 8 9) >
这次的主要收获是发现应该大胆采用let来避免重复计算,例子中的lef, rig, fir, rest 就是很好的证明.
不要觉得这样会导致代码层次过多,性能才更重要.
更何况有时let也能提高可读性.