Extend heaps to allow removing arbitrary elements via an additional equality operator.
This commit is contained in:
parent
d3ddd3a0d4
commit
4e20ede1f2
|
@ -109,6 +109,15 @@ empty, an exception is raised.
|
|||
(heap-min a-heap)]
|
||||
}
|
||||
|
||||
@defproc[(heap-remove! [h heap?] [v any/c] [#:same? same? (-> any/c any/c any/c) equal?]) void?]{
|
||||
Removes @racket[v] from the heap @racket[h] if it exists.
|
||||
@examples[#:eval the-eval
|
||||
(define a-heap (make-heap string<=? string=?))
|
||||
(heap-add! a-heap "a" "b" "c")
|
||||
(heap-remove! a-heap "b")
|
||||
(for/list ([a (in-heap a-heap)]) a)]
|
||||
}
|
||||
|
||||
@defproc[(vector->heap [<=? (-> any/c any/c any/c)] [items vector?]) heap?]{
|
||||
|
||||
Builds a heap with the elements from @racket[items]. The vector is not
|
||||
|
|
|
@ -156,6 +156,35 @@
|
|||
(set-heap-vec! h (shrink-vector vec)))
|
||||
(set-heap-count! h (sub1 size))]))
|
||||
|
||||
(define (heap-get-index h v same?)
|
||||
(match h
|
||||
[(heap vec size <=?)
|
||||
(and (not (eq? 0 size))
|
||||
(let search ([n 0] [n-key (vector-ref vec 0)])
|
||||
(cond
|
||||
[(same? n-key v) n]
|
||||
;; The heap property ensures n-key <= all its children
|
||||
[else
|
||||
(define (search-right)
|
||||
(define right (vt-rightchild n))
|
||||
(and (< right size)
|
||||
(let ([right-key (vector-ref vec right)])
|
||||
(and (<=? right-key v)
|
||||
(search right right-key)))))
|
||||
;; Try going left if the left child is <= v
|
||||
(define left (vt-leftchild n))
|
||||
(and (< left size) ;; if no left, there can't be a right.
|
||||
(let ([left-key (vector-ref vec left)])
|
||||
;; If left <= v, try left side.
|
||||
(if (<=? left-key v)
|
||||
(or (search left left-key) (search-right))
|
||||
(search-right))))])))]))
|
||||
|
||||
(define (heap-remove! h v #:same? [same? equal?])
|
||||
(match (heap-get-index h v same?)
|
||||
[#f (void)]
|
||||
[n (heap-remove-index! h n)]))
|
||||
|
||||
(define (in-heap h)
|
||||
(in-heap/consume! (heap-copy h)))
|
||||
|
||||
|
@ -211,6 +240,7 @@
|
|||
[heap-add-all! (-> heap? (or/c list? vector? heap?) void?)]
|
||||
[heap-min (-> heap? any/c)]
|
||||
[heap-remove-min! (-> heap? void?)]
|
||||
[heap-remove! (->* (heap? any/c) [#:same? (-> any/c any/c any/c)] void?)]
|
||||
|
||||
[vector->heap (-> (-> any/c any/c any/c) vector? heap?)]
|
||||
[heap->vector (-> heap? vector?)]
|
||||
|
|
|
@ -32,6 +32,12 @@
|
|||
(heap->vector h))
|
||||
'#(4 6 8 10))
|
||||
|
||||
(test-equal? "heap-remove!"
|
||||
(let ([h (mkheap)])
|
||||
(heap-remove! h 4)
|
||||
(heap->vector h))
|
||||
'#(2 6 8 10))
|
||||
|
||||
(define (rand-test range count1 count2 count3)
|
||||
(let ([h (make-heap <=)]
|
||||
[xs null]) ;; mutated
|
||||
|
|
Loading…
Reference in New Issue
Block a user