我正在尝试使用向量在Scheme中实现mergesort算法。我知道我可以使用的其他排序方法,但我想完成我的代码。我到目前为止的内容如下:
(define (split v)
(define (helper k v1 v2)
(let ((m (floor (/ (vector-length v) 2))))
(if (>= k m)
(if (= k (vector-length v))
(cons v1 v2)
(helper (+ k 1) v1 (vector-append v2 (vector (vector-ref v k)))))
(helper (+ k 1) (vector-append v1 (vector (vector-ref v k))) v2))))
(helper 0 #() #()))
(define (merge v1 v2)
(if (< (vector-ref v1 0) (vector-ref v2 0))
(vector-append v1 v2)
(vector-append v2 v1)))
(define (mergesort v)
(if (<= (vector-length v) 1)
v
(merge (mergesort (car (split v))) (mergesort (cdr (split v))))))
我非常接近我的回答,但我错过了一些东西。这里有什么帮助吗?
答案 0 :(得分:2)
实现的主要障碍是您的merge
函数未正确实现合并算法。在合并算法中:
下面我的merge-into!
函数实现了这种方法。
除此之外,另一个主要问题是你的split
函数试图逐步构建向量,遗憾的是,这是一个缓慢的过程:它必须每次都将所有元素复制到一个新的向量中。它不像cons
!使用向量时,不要犹豫使用vector-set!
;任何不可变的向量更新都会变得缓慢而低效,所以只需咬紧牙关并使其变得可变。 : - )
作为参考,我从头开始编写了一个新的实现(在Racket中):
(define (split-halves vec)
(vector-split-at vec (quotient (vector-length vec) 2)))
(define (merge lhs rhs)
(define result (make-vector (+ (vector-length lhs)
(vector-length rhs))))
(merge-into! result lhs rhs))
(define (merge-into! result lhs rhs)
(let loop ((i 0) (j 0) (k 0))
(define (take-left)
(vector-set! result k (vector-ref lhs i))
(loop (add1 i) j (add1 k)))
(define (take-right)
(vector-set! result k (vector-ref rhs j))
(loop i (add1 j) (add1 k)))
(cond ((= k (vector-length result)) result)
((= i (vector-length lhs))
(take-right))
((= j (vector-length rhs))
(take-left))
((< (vector-ref rhs j) (vector-ref lhs i))
(take-right))
(else
(take-left)))))
(define (mergesort vec)
(case (vector-length vec)
((0 1) vec)
(else (let-values (((lhs rhs) (split-halves vec)))
(merge (mergesort lhs) (mergesort rhs))))))
merge-into!
函数允许轻松编写mergesort
的变异版本:
(define (mergesort! vec)
(case (vector-length vec)
((0 1) vec)
(else (let-values (((lhs rhs) (split-halves vec)))
(mergesort! lhs)
(mergesort! rhs)
(merge-into! vec lhs rhs)))))
如果您不使用Racket,您可能需要以下其他定义(需要SRFI 43;如果您没有,请参阅帖子的底部):
(define (vector-split-at vec pos)
(values (vector-copy vec 0 pos)
(vector-copy vec pos (vector-length vec))))
(define (add1 x)
(+ x 1))
let-values
在SRFI 11中定义。如果您没有,请使用mergesort
的{{1}}版本:
call-with-values
(define (mergesort vec)
(case (vector-length vec)
((0 1) vec)
(else (call-with-values (lambda () (split-halves vec))
(lambda (lhs rhs)
(merge (mergesort lhs) (mergesort rhs)))))))
在SRFI 43中定义。如果你没有,那么这是一个简化版本:
vector-copy