File: heap.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (94 lines) | stat: -rw-r--r-- 2,675 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(*
 * This implements a priority queue using a heap
 * 
 * -- Allen
 *)

structure PriorityHeap :> PRIORITY_QUEUE =
struct
   structure A = Array
   exception EmptyPriorityQueue
   exception Unimplemented

   datatype 'a priority_queue = 
       HEAP of { less : 'a * 'a -> bool,
                 heap : 'a A.array,
                 size : int ref
               }

   fun createN(less,N,dummy) = 
       HEAP{less=less, heap = A.array(N,dummy), size = ref 0}

   fun unimplemented() = raise Unimplemented
   
   fun create _ = unimplemented()
   fun merge _ = unimplemented()
   fun mergeInto _ = unimplemented()
   fun toList _ = unimplemented()
  
   fun isEmpty (HEAP{ size = ref 0, ... }) = true
     | isEmpty _ = false

   fun clear (HEAP{ size, ... }) = size := 0

   fun min(HEAP{ size = ref 0, ... }) = raise EmptyPriorityQueue
     | min(HEAP{ heap, ... }) = A.sub(heap, 0)


   fun insert(HEAP{ size, heap, less, ...}) x =
   let val N = !size
       fun siftup 0 = 0
         | siftup i =
       let val j = (i-1) div 2
           val y = A.sub(heap,j)
       in  if less(x,y) then (A.update(heap,i,y); siftup j)
           else i
       end 
   in  size := N + 1;
       A.update(heap,siftup N,x)
   end

   fun siftDown(heap, less, N, i, x) =
   let fun siftdown (i, x) = 
       let val j = i + i + 1
           val k = j + 1
       in  if j >= N then i
           else let val y = A.sub(heap,j)
                in  if k >= N then
                       if less(y,x) then go(i,x,j,y) else i 
                    else 
                       let val z = A.sub(heap,k)
                       in  if less(y,x) then
                              if less(z,y) then go(i,x,k,z) 
                              else go(i,x,j,y)
                           else if less(z,x) then go(i,x,k,z)
                           else i
                       end
                end
       end
       and go(i,x,j,y) = (A.update(heap,i,y); siftdown(j,x))
       val pos_x = siftdown(i, x) 
   in  A.update(heap, pos_x, x); 
       pos_x 
   end
 
   fun deleteMin(HEAP{ size = ref 0, ...}) = raise EmptyPriorityQueue
     | deleteMin(HEAP{ size, heap, less, ...}) =
   let val N = !size - 1
       val min   = A.sub(heap,0)
       val x     = A.sub(heap,N)
       val x_pos = siftDown(heap, less, N, 0, x)
   in  size := N;
       min
   end

   fun fromList less data =
   let val heap = A.fromList data
       val N    = A.length heap
       fun make_heap ~1 = ()
         | make_heap i = 
           (siftDown(heap,less,N,i,A.sub(heap,i)); make_heap(i-1))
   in  if N >= 2 then make_heap((N+1) div 2) else ();
       HEAP{ less = less, heap = heap, size = ref N } 
   end
end