我是一名C ++程序员,我编写了这段代码,看看我是否可以在功能上思考:) 任何提高它的提示?
(define (append listOne listTwo)
(cond
((null? listOne) listTwo)
(else (cons (car listOne) (append (cdr listOne) listTwo)))))
(define (merge listOne listTwo)
(cond
((null? listOne) listTwo)
((null? listTwo) listOne)
((< (car listOne) (car listTwo))
(append (cons (car listOne) '())
(merge (cdr listOne) listTwo)))
((= (car listOne) (car listTwo))
(append (cons (car listOne) '())
(merge (cdr listOne) listTwo)))
(else (append (cons (car listTwo) '())
(merge listOne (cdr listTwo))))))
(define (mergesort lis)
(cond
((null? lis) '())
((null? (cdr lis)) lis)
(else (merge (cons (car lis) '())
(mergesort (cdr lis))))))
(mergesort '(99 77 88 66 44 55 33 11 22 0))
答案 0 :(得分:3)
我看到的只有一个小改进:
(append (cons (car listTwo) '())
(merge listOne (cdr listTwo))))
可以在任何地方简化为
(cons (car listTwo)
(merge listOne (cdr listTwo)))
我认为你在想类似的东西(用Python式语法):
[car(listTwo)] + merge(listOne, cdr(listTwo))
但是,cons会将一个项目直接添加到列表的前面,就像功能push
一样,所以它就像下面的代码:
push(car(listTwo), merge(listOne, cdr(listTwo)))
最终额外附加只会导致每个项目的双重细胞分配,所以这不是什么大问题。
另外,如果你让mergesort
更加漂亮,我认为你可能会获得更好的表现,以便它保持列表长度并在每一步对列表的两半进行排序。不过,这可能不适合像这样的学习例子。
类似的东西:
(define (mergesort l)
(let sort-loop ((l l) (len (length l)))
(cond
((null? l) '())
((null? (cdr l)) l)
(else (merge (sort-loop (take (/ len 2) l) (/ len 2)))
(sort-loop (drop (/ len 2) l) (/ len 2)))))))))
(define (take n l)
(if (= n 0)
'()
(cons (car l) (take (sub1 n) (cdr l)))))
(define (drop n l)
(if (= n 0)
l
(drop (sub1 n) (cdr l))))
答案 1 :(得分:1)
一般来说,mergesort
正在进行大量的列表操作,因此通过“就地”对子部分进行排序来破坏性地做事要好得多。您可以看到implementation of sort
in PLT Scheme例如源自SLIB的公共代码。 (第一眼看上去可能看起来令人生畏,但是如果你阅读评论并忽略旋钮和优化,那么你会在那里看到它。)
此外,您应该查看SRFI-32以获得有关排序界面的扩展讨论。