File: cf_sbheap.ml

package info (click to toggle)
pagodacf 0.10-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 1,204 kB
  • ctags: 2,320
  • sloc: ml: 8,458; ansic: 3,338; makefile: 171; sh: 27
file content (243 lines) | stat: -rw-r--r-- 7,185 bytes parent folder | download | duplicates (6)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
(*---------------------------------------------------------------------------*
  IMPLEMENTATION  cf_sbheap.ml

  Copyright (c) 2002-2006, James H. Woodyatt
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

    Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in
    the documentation and/or other materials provided with the
    distribution

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  OF THE POSSIBILITY OF SUCH DAMAGE. 
 *---------------------------------------------------------------------------*)

type 'a node_t = 'a tree_t list
and 'a tree_t = N of int * 'a * 'a list * 'a node_t

module type Node_T = sig
    module Key: Cf_ordered.Total_T
    type +'a t
    val compare: 'a t -> 'a t -> int
end

module Core(N: Node_T) = struct
    module N = N
        
    let nil = []
    let empty h = (h = [])
    
    let rec size = function hd :: tl -> (size_tree_ hd + size tl) | [] -> 0
    and size_tree_ (N (_, _, xs, ts)) = 1 + List.length xs + size ts
        
    let rank_ (N (r, _, _, _)) = r
    let root_ (N (_, x, _, _)) = x
    
    let link_ t1 t2 =
        let N (r, x1, xs1, c1) = t1
        and N (_, x2, xs2, c2) = t2
        in
        let r = succ r in
        if N.compare x1 x2 < 0
            then N (r, x1, xs1, t2 :: c1)
            else N (r, x2, xs2, t1 :: c2)
    
    let skew_link_ x t1 t2 =
        let N (r, y, ys, c) = link_ t1 t2 in
        if N.compare x y < 0
            then N (r, x, y :: ys, c)
            else N (r, y, x :: ys, c)
    
    let rec insert_tree_ t = function
        | [] ->
            [ t ]
        | hd :: tl as ts ->
            if rank_ t < rank_ hd
                then t :: ts
                else insert_tree_ (link_ t hd) tl
    
    let rec merge_trees_ ts1 ts2 =
        match ts1, ts2 with
        | _, [] -> ts1
        | [], _ -> ts2
        | t1 :: ts1', t2 :: ts2' ->
            if rank_ t1 < rank_ t2 then
                t1 :: merge_trees_ ts1' ts2
            else if rank_ t2 < rank_ t1 then
                t2 :: merge_trees_ ts1 ts2'
            else
                insert_tree_ (link_ t1 t2) (merge_trees_ ts1' ts2')
    
    let normalize_ = function
        | [] -> []
        | hd :: tl -> insert_tree_ hd tl
    
    let put x = function
        | t1 :: t2 :: tail as ts ->
            if rank_ t1 = rank_ t2
                then skew_link_ x t1 t2 :: tail
                else N (0, x, [], []) :: ts
        | ts ->
            N (0, x, [], []) :: ts
    
    let merge ts1 ts2 = merge_trees_ (normalize_ ts1) (normalize_ ts2)
    
    let rec shift_tree_ = function
        | [] -> raise Not_found
        | x :: [] -> x
        | hd :: tl ->
            let hd' = shift_tree_ tl in
            let x = root_ hd and y = root_ hd' in
            if N.compare x y < 0 then hd else hd'
    
    let head ts = root_ (shift_tree_ ts)

    let rec remove_tree_ = function
        | [] -> raise Not_found
        | x :: [] -> x, []
        | hd :: tl ->
            let hd', tl' = remove_tree_ tl in
            let x = root_ hd in
            let y = root_ hd' in
            if N.compare x y < 0
                then hd, tl
                else hd', hd :: tl'
        
    let rec tail_loop_ ts = function
        | x :: xs' -> tail_loop_ (put x ts) xs'
        | [] -> ts

    let tail ts =
        let N (_, _, xs, ts1), ts2 = remove_tree_ ts in
        tail_loop_ (merge (List.rev ts1) ts2) xs
    
    let pop ts = try Some (head ts, tail ts) with Not_found -> None
    
    let rec iterate f =
        let sub (N (_, x, xs, ts)) = f x; List.iter f xs; iterate f ts in
        function
        | hd :: tl -> sub hd; iterate f tl
        | [] -> ()
    
    let rec predicate f =
        let sub (N (_, x, xs, ts)) =
            f x && List.for_all f xs && predicate f ts
        in
        function
        | hd :: tl -> sub hd && predicate f tl
        | [] -> true
    
    let rec fold f =
        let sub x0 (N (_, x, xs, ts)) =
            let x0 = fold f x0 ts in
            let x0 = List.fold_left f x0 xs in
            f x0 x
        in
        fun x0 ->
            function
            | hd :: tl -> fold f (sub x0 hd) tl
            | [] -> x0
    
    let filter f =
        let g h x = if f x then put x h else h in
        fun ts -> fold g nil ts
    
    let partition f =
        let g (h0, h1) x = if f x then put x h0, h1 else h0, put x h1 in
        fun ts -> fold g (nil, nil) ts
    
    let of_list =
        let rec loop acc = function
            | hd :: tl -> loop (put hd acc) tl
            | [] -> acc
        in
        fun z ->
            loop nil z
    
    let of_seq =
        let rec loop acc seq =
            match Lazy.force seq with
            | Cf_seq.P (hd, tl) -> loop (put hd acc) tl
            | Cf_seq.Z -> acc
        in
        fun seq ->
            loop nil seq

    let rec to_seq h =
        lazy begin
            try
                Cf_seq.P (head h, to_seq (tail h))
            with
            | Not_found ->
                Cf_seq.Z
        end
    
    let rec to_seq2 h =
        lazy begin
            try
                let N (_, x, xs, ts1), ts2 = remove_tree_ h in
                let tl = tail_loop_ (merge (List.rev ts1) ts2) xs in
                Cf_seq.P ((x, tl), to_seq2 tl)
            with
            | Not_found ->
                Cf_seq.Z
        end
end

module Heap(E: Cf_ordered.Total_T) = struct
    include Core(struct
        module Key = E
        
        type 'a t = E.t
        
        let compare x y = E.compare x y
    end)
    
    module Element = E
    type t = E.t node_t
end

module PQueue(K: Cf_ordered.Total_T) = struct
    include Core(struct
        module Key = K
        type 'a t = Key.t * 'a
        
        let compare (x, _) (y, _) = Key.compare x y
    end)

    module Key = K
    
    type 'a t = 'a N.t node_t
    
    let map f =
        let g h (k, _ as x) = put (k, f x) h in
        fun ts -> fold g nil ts
    
    let optmap f =
        let g h (k, _ as x) =
            match f x with
            | Some x -> put (k, x) h
            | None -> h
        in
        fun ts -> fold g nil ts
end

(*--- End of File [ cf_sbheap.ml ] ---*)