binary-heap.scm 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. ;;; Binary heap (borrowed from Chickadee)
  2. ;;; Copyright (C) 2017 David Thompson <dthompson2@worcester.edu>
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Binary min-heap for use as a priority queue.
  18. ;;;
  19. ;;; Code:
  20. (define-module (hoot binary-heap)
  21. #:use-module (ice-9 format)
  22. #:use-module (rnrs base)
  23. #:use-module (srfi srfi-9)
  24. #:use-module (srfi srfi-9 gnu)
  25. #:export (make-heap
  26. heap?
  27. heap-empty?
  28. heap-size
  29. heap-min
  30. heap-insert!
  31. heap-remove!
  32. heap-clear!))
  33. (define-record-type <heap>
  34. (%make-heap vector size <)
  35. heap?
  36. (vector heap-vector set-heap-vector!)
  37. (size heap-size set-heap-size!)
  38. (< heap-<))
  39. (define (display-heap heap port)
  40. (format port "#<heap size: ~d>" (heap-size heap)))
  41. (set-record-type-printer! <heap> display-heap)
  42. (define* (make-heap #:optional (< <))
  43. "Return a new heap that uses the @var{<} procedure to determine order."
  44. (%make-heap (make-vector 32 #f) 0 <))
  45. (define (heap-empty? heap)
  46. "Return @code{#t} if @var{heap} is empty."
  47. (zero? (heap-size heap)))
  48. (define (heap-capacity heap)
  49. (1- (vector-length (heap-vector heap))))
  50. (define (heap-full? heap)
  51. (= (heap-size heap) (heap-capacity heap)))
  52. (define (double-heap-capacity! heap)
  53. (let* ((old-vec (heap-vector heap))
  54. (new-vec (make-vector (* (vector-length old-vec) 2) #f)))
  55. (vector-copy! new-vec 0 old-vec)
  56. (set-heap-vector! heap new-vec)))
  57. (define (heap-min heap)
  58. "Return the minimum element of @var{heap}."
  59. (if (zero? (heap-size heap))
  60. (error "empty heap" heap)
  61. (vector-ref (heap-vector heap) 1)))
  62. (define (heap-set! heap i item)
  63. (vector-set! (heap-vector heap) i item))
  64. (define (heap-ref heap i)
  65. (vector-ref (heap-vector heap) i))
  66. (define (heap-insert! heap item)
  67. "Add @var{item} to @var{heap}."
  68. (when (heap-full? heap)
  69. (double-heap-capacity! heap))
  70. (let ((hole (1+ (heap-size heap)))
  71. (< (heap-< heap)))
  72. (set-heap-size! heap hole)
  73. (let loop ((hole hole))
  74. (let* ((parent-hole (div hole 2))
  75. (parent-item (heap-ref heap parent-hole)))
  76. (if (and (> hole 1) (< item parent-item))
  77. (begin
  78. (heap-set! heap hole parent-item)
  79. (loop parent-hole))
  80. (heap-set! heap hole item))))))
  81. (define (heap-remove! heap)
  82. "Remove the minimum element of @var{heap}."
  83. (let ((size (1- (heap-size heap)))
  84. (< (heap-< heap)))
  85. (define (finish hole)
  86. (heap-set! heap (heap-size heap) #f)
  87. (heap-set! heap 0 #f)
  88. (set-heap-size! heap size)
  89. *unspecified*)
  90. (define (leaf? hole)
  91. (> (* hole 2) size))
  92. (define (smallest-child hole)
  93. (let ((left-child (* hole 2))
  94. (right-child (1+ (* hole 2))))
  95. (if (or (= left-child size)
  96. (< (heap-ref heap left-child) (heap-ref heap right-child)))
  97. left-child
  98. right-child)))
  99. (heap-set! heap 1 (heap-ref heap (heap-size heap)))
  100. (let loop ((hole 1))
  101. (if (leaf? hole)
  102. (finish hole)
  103. (let ((child (smallest-child hole)))
  104. (if (< (heap-ref heap hole) (heap-ref heap child))
  105. (finish hole)
  106. (begin
  107. (heap-set! heap 0 (heap-ref heap hole))
  108. (heap-set! heap hole (heap-ref heap child))
  109. (heap-set! heap child (heap-ref heap 0))
  110. (loop child))))))))
  111. (define (heap-clear! heap)
  112. "Remove all elements from @var{heap}."
  113. (vector-fill! (heap-vector heap) #f)
  114. (set-heap-size! heap 0))