~ubuntu-branches/ubuntu/raring/agda-stdlib/raring-proposed

« back to all changes in this revision

Viewing changes to src/Data/AVL.agda

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2010-01-08 23:35:09 UTC
  • Revision ID: james.westby@ubuntu.com-20100108233509-l6ejt9xji64xysfb
Tags: upstream-0.3
Import upstream version 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
------------------------------------------------------------------------
 
2
-- AVL trees
 
3
------------------------------------------------------------------------
 
4
 
 
5
-- AVL trees are balanced binary search trees. The search tree
 
6
-- invariant is not statically enforced in the current implementation,
 
7
-- just the balance invariant.
 
8
 
 
9
open import Level
 
10
open import Relation.Binary
 
11
 
 
12
module Data.AVL (OrderedKeySet : StrictTotalOrder zero zero zero)
 
13
                (Value : StrictTotalOrder.Carrier OrderedKeySet → Set)
 
14
                where
 
15
 
 
16
open import Data.Nat hiding (compare)
 
17
open StrictTotalOrder OrderedKeySet renaming (Carrier to Key)
 
18
open import Data.Product
 
19
open import Data.Maybe
 
20
open import Data.Bool
 
21
open import Data.List as List using (List)
 
22
import Data.DifferenceList as DiffList
 
23
open import Relation.Binary.PropositionalEquality
 
24
 
 
25
------------------------------------------------------------------------
 
26
-- Types and functions which are used to keep track of invariants
 
27
 
 
28
module Invariants where
 
29
 
 
30
  -- Bits. (I would use Fin 2 instead if Agda had "defined patterns",
 
31
  -- so that I could pattern match on 1# instead of suc zero; the text
 
32
  -- "suc zero" takes up a lot more space.)
 
33
 
 
34
  data ℕ₂ : Set where
 
35
    0# : ℕ₂
 
36
    1# : ℕ₂
 
37
 
 
38
  -- Addition.
 
39
 
 
40
  infixl 6 _⊕_
 
41
 
 
42
  _⊕_ : ℕ₂ → ℕ → ℕ
 
43
  0# ⊕ n = n
 
44
  1# ⊕ n = 1 + n
 
45
 
 
46
  -- i ⊕ n -1 = pred (i ⊕ n).
 
47
 
 
48
  _⊕_-1 : ℕ₂ → ℕ → ℕ
 
49
  i ⊕ zero  -1 = 0
 
50
  i ⊕ suc n -1 = i ⊕ n
 
51
 
 
52
  infix 4 _∼_
 
53
 
 
54
  -- If m ∼ n, then the difference between m and n is at most 1. _∼_
 
55
  -- is used to record the balance factor of the AVL trees, and also
 
56
  -- to ensure that the absolute value of the balance factor is never
 
57
  -- more than 1.
 
58
 
 
59
  data _∼_ : ℕ → ℕ → Set where
 
60
    ∼+ : ∀ {n} →     n ∼ 1 + n
 
61
    ∼0 : ∀ {n} →     n ∼ n
 
62
    ∼- : ∀ {n} → 1 + n ∼ n
 
63
 
 
64
  -- The maximum of m and n.
 
65
 
 
66
  max : ∀ {m n} → m ∼ n → ℕ
 
67
  max (∼+ {n}) = 1 + n
 
68
  max (∼0 {n}) =     n
 
69
  max (∼- {n}) = 1 + n
 
70
 
 
71
  -- Some lemmas.
 
72
 
 
73
  1+ : ∀ {m n} → m ∼ n → 1 + m ∼ 1 + n
 
74
  1+ ∼+ = ∼+
 
75
  1+ ∼0 = ∼0
 
76
  1+ ∼- = ∼-
 
77
 
 
78
  max∼ : ∀ {i j} (bal : i ∼ j) → max bal ∼ i
 
79
  max∼ ∼+ = ∼-
 
80
  max∼ ∼0 = ∼0
 
81
  max∼ ∼- = ∼0
 
82
 
 
83
  ∼max : ∀ {i j} (bal : i ∼ j) → j ∼ max bal
 
84
  ∼max ∼+ = ∼0
 
85
  ∼max ∼0 = ∼0
 
86
  ∼max ∼- = ∼+
 
87
 
 
88
  max∼max : ∀ {i j} (bal : i ∼ j) → max (max∼ bal) ∼ max (∼max bal)
 
89
  max∼max ∼+ = ∼0
 
90
  max∼max ∼0 = ∼0
 
91
  max∼max ∼- = ∼0
 
92
 
 
93
  max-lemma : ∀ {m n} (bal : m ∼ n) →
 
94
              1 + max (1+ (max∼max bal)) ≡ 2 + max bal
 
95
  max-lemma ∼+ = refl
 
96
  max-lemma ∼0 = refl
 
97
  max-lemma ∼- = refl
 
98
 
 
99
------------------------------------------------------------------------
 
100
-- AVL trees
 
101
 
 
102
-- Key/value pairs.
 
103
 
 
104
KV : Set
 
105
KV = Σ Key Value
 
106
 
 
107
module Indexed where
 
108
 
 
109
  open Invariants
 
110
 
 
111
  -- The trees are indexed on their height. (bal is the balance
 
112
  -- factor.)
 
113
 
 
114
  data Tree : ℕ → Set where
 
115
    leaf : Tree 0
 
116
    node : ∀ {hˡ hʳ}
 
117
           (l : Tree hˡ) (k : KV) (r : Tree hʳ) (bal : hˡ ∼ hʳ) →
 
118
           Tree (1 + max bal)
 
119
 
 
120
  -- Various constant-time functions which construct trees out of
 
121
  -- smaller pieces, sometimes using rotation.
 
122
 
 
123
  joinˡ⁺ : ∀ {hˡ hʳ} →
 
124
           (∃ λ i → Tree (i ⊕ hˡ)) → KV → Tree hʳ → (bal : hˡ ∼ hʳ) →
 
125
           ∃ λ i → Tree (i ⊕ (1 + max bal))
 
126
  joinˡ⁺ (1# , node t₁ k₂
 
127
                 (node t₃ k₄ t₅ bal)
 
128
                             ∼+) k₆ t₇ ∼-  = (0# , subst Tree (max-lemma bal)
 
129
                                                     (node (node t₁ k₂ t₃ (max∼ bal))
 
130
                                                           k₄
 
131
                                                           (node t₅ k₆ t₇ (∼max bal))
 
132
                                                           (1+ (max∼max bal))))
 
133
  joinˡ⁺ (1# , node t₁ k₂ t₃ ∼-) k₄ t₅ ∼-  = (0# , node t₁ k₂ (node t₃ k₄ t₅ ∼0) ∼0)
 
134
  joinˡ⁺ (1# , node t₁ k₂ t₃ ∼0) k₄ t₅ ∼-  = (1# , node t₁ k₂ (node t₃ k₄ t₅ ∼-) ∼+)
 
135
  joinˡ⁺ (1# , t₁)               k₂ t₃ ∼0  = (1# , node t₁ k₂ t₃ ∼-)
 
136
  joinˡ⁺ (1# , t₁)               k₂ t₃ ∼+  = (0# , node t₁ k₂ t₃ ∼0)
 
137
  joinˡ⁺ (0# , t₁)               k₂ t₃ bal = (0# , node t₁ k₂ t₃ bal)
 
138
 
 
139
  joinʳ⁺ : ∀ {hˡ hʳ} →
 
140
           Tree hˡ → KV → (∃ λ i → Tree (i ⊕ hʳ)) → (bal : hˡ ∼ hʳ) →
 
141
           ∃ λ i → Tree (i ⊕ (1 + max bal))
 
142
  joinʳ⁺ t₁ k₂ (1# , node
 
143
                       (node t₃ k₄ t₅ bal)
 
144
                             k₆ t₇ ∼-) ∼+  = (0# , subst Tree (max-lemma bal)
 
145
                                                     (node (node t₁ k₂ t₃ (max∼ bal))
 
146
                                                           k₄
 
147
                                                           (node t₅ k₆ t₇ (∼max bal))
 
148
                                                           (1+ (max∼max bal))))
 
149
  joinʳ⁺ t₁ k₂ (1# , node t₃ k₄ t₅ ∼+) ∼+  = (0# , node (node t₁ k₂ t₃ ∼0) k₄ t₅ ∼0)
 
150
  joinʳ⁺ t₁ k₂ (1# , node t₃ k₄ t₅ ∼0) ∼+  = (1# , node (node t₁ k₂ t₃ ∼+) k₄ t₅ ∼-)
 
151
  joinʳ⁺ t₁ k₂ (1# , t₃)               ∼0  = (1# , node t₁ k₂ t₃ ∼+)
 
152
  joinʳ⁺ t₁ k₂ (1# , t₃)               ∼-  = (0# , node t₁ k₂ t₃ ∼0)
 
153
  joinʳ⁺ t₁ k₂ (0# , t₃)               bal = (0# , node t₁ k₂ t₃ bal)
 
154
 
 
155
  joinˡ⁻ : ∀ hˡ {hʳ} →
 
156
           (∃ λ i → Tree (i ⊕ hˡ -1)) → KV → Tree hʳ → (bal : hˡ ∼ hʳ) →
 
157
           ∃ λ i → Tree (i ⊕ max bal)
 
158
  joinˡ⁻ zero    (0# , t₁) k₂ t₃ bal = (1# , node t₁ k₂ t₃ bal)
 
159
  joinˡ⁻ zero    (1# , t₁) k₂ t₃ bal = (1# , node t₁ k₂ t₃ bal)
 
160
  joinˡ⁻ (suc _) (0# , t₁) k₂ t₃ ∼+  = joinʳ⁺ t₁ k₂ (1# , t₃) ∼+
 
161
  joinˡ⁻ (suc _) (0# , t₁) k₂ t₃ ∼0  = (1# , node t₁ k₂ t₃ ∼+)
 
162
  joinˡ⁻ (suc _) (0# , t₁) k₂ t₃ ∼-  = (0# , node t₁ k₂ t₃ ∼0)
 
163
  joinˡ⁻ (suc _) (1# , t₁) k₂ t₃ bal = (1# , node t₁ k₂ t₃ bal)
 
164
 
 
165
  joinʳ⁻ : ∀ {hˡ} hʳ →
 
166
           Tree hˡ → KV → (∃ λ i → Tree (i ⊕ hʳ -1)) → (bal : hˡ ∼ hʳ) →
 
167
           ∃ λ i → Tree (i ⊕ max bal)
 
168
  joinʳ⁻ zero    t₁ k₂ (0# , t₃) bal = (1# , node t₁ k₂ t₃ bal)
 
169
  joinʳ⁻ zero    t₁ k₂ (1# , t₃) bal = (1# , node t₁ k₂ t₃ bal)
 
170
  joinʳ⁻ (suc _) t₁ k₂ (0# , t₃) ∼-  = joinˡ⁺ (1# , t₁) k₂ t₃ ∼-
 
171
  joinʳ⁻ (suc _) t₁ k₂ (0# , t₃) ∼0  = (1# , node t₁ k₂ t₃ ∼-)
 
172
  joinʳ⁻ (suc _) t₁ k₂ (0# , t₃) ∼+  = (0# , node t₁ k₂ t₃ ∼0)
 
173
  joinʳ⁻ (suc _) t₁ k₂ (1# , t₃) bal = (1# , node t₁ k₂ t₃ bal)
 
174
 
 
175
  -- Extracts the smallest element from the tree, plus the rest.
 
176
  -- Logarithmic in the size of the tree.
 
177
 
 
178
  headTail : ∀ {h} → Tree (1 + h) →
 
179
             KV × ∃ λ i → Tree (i ⊕ h)
 
180
  headTail (node leaf k₁ t₂ ∼+) = (k₁ , 0# , t₂)
 
181
  headTail (node leaf k₁ t₂ ∼0) = (k₁ , 0# , t₂)
 
182
  headTail (node {hˡ = suc _} t₁₂ k₃ t₄ bal) with headTail t₁₂
 
183
  ... | (k₁ , t₂) = (k₁ , joinˡ⁻ _ t₂ k₃ t₄ bal)
 
184
 
 
185
  -- Extracts the largest element from the tree, plus the rest.
 
186
  -- Logarithmic in the size of the tree.
 
187
 
 
188
  initLast : ∀ {h} → Tree (1 + h) →
 
189
             ∃ (λ i → Tree (i ⊕ h)) × KV
 
190
  initLast (node t₁ k₂ leaf ∼-) = ((0# , t₁) , k₂)
 
191
  initLast (node t₁ k₂ leaf ∼0) = ((0# , t₁) , k₂)
 
192
  initLast (node {hʳ = suc _} t₁ k₂ t₃₄ bal) with initLast t₃₄
 
193
  ... | (t₃ , k₄) = (joinʳ⁻ _ t₁ k₂ t₃ bal , k₄)
 
194
 
 
195
  -- Another joining function. Logarithmic in the size of the tree.
 
196
 
 
197
  join : ∀ {hˡ hʳ} →
 
198
         Tree hˡ → Tree hʳ → (bal : hˡ ∼ hʳ) →
 
199
         ∃ λ i → Tree (i ⊕ max bal)
 
200
  join t₁ leaf ∼0 = (0# , t₁)
 
201
  join t₁ leaf ∼- = (0# , t₁)
 
202
  join {hʳ = suc _} t₁ t₂₃ bal with headTail t₂₃
 
203
  ... | (k₂ , t₃) = joinʳ⁻ _ t₁ k₂ t₃ bal
 
204
 
 
205
  -- An empty tree.
 
206
 
 
207
  empty : Tree 0
 
208
  empty = leaf
 
209
 
 
210
  -- A singleton tree.
 
211
 
 
212
  singleton : (k : Key) → Value k → Tree 1
 
213
  singleton k v = node leaf (k , v) leaf ∼0
 
214
 
 
215
  -- Inserts a key into the tree. If the key already exists, then it
 
216
  -- is replaced. Logarithmic in the size of the tree (assuming
 
217
  -- constant-time comparisons).
 
218
 
 
219
  insert : ∀ {h} → (k : Key) → Value k → Tree h →
 
220
           ∃ λ i → Tree (i ⊕ h)
 
221
  insert k v leaf             = (1# , singleton k v)
 
222
  insert k v (node l p r bal) with compare k (proj₁ p)
 
223
  ... | tri< _ _ _ = joinˡ⁺ (insert k v l) p r bal
 
224
  ... | tri≈ _ _ _ = (0# , node l (k , v) r bal)
 
225
  ... | tri> _ _ _ = joinʳ⁺ l p (insert k v r) bal
 
226
 
 
227
  -- Deletes the key/value pair containing the given key, if any.
 
228
  -- Logarithmic in the size of the tree (assuming constant-time
 
229
  -- comparisons).
 
230
 
 
231
  delete : ∀ {h} → Key → Tree h →
 
232
           ∃ λ i → Tree (i ⊕ h -1)
 
233
  delete k leaf             = (0# , leaf)
 
234
  delete k (node l p r bal) with compare k (proj₁ p)
 
235
  ... | tri< _ _ _ = joinˡ⁻ _ (delete k l) p r bal
 
236
  ... | tri≈ _ _ _ = join l r bal
 
237
  ... | tri> _ _ _ = joinʳ⁻ _ l p (delete k r) bal
 
238
 
 
239
  -- Looks up a key in the tree. Logarithmic in the size of the tree
 
240
  -- (assuming constant-time comparisons).
 
241
 
 
242
  lookup : ∀ {h} → (k : Key) → Tree h →
 
243
           Maybe (∃ λ k′ → Value k′ × k ≈ k′)
 
244
  lookup k leaf                  = nothing
 
245
  lookup k (node l (k′ , v) r _) with compare k k′
 
246
  ... | tri< _ _  _ = lookup k l
 
247
  ... | tri≈ _ eq _ = just (k′ , v , eq)
 
248
  ... | tri> _ _  _ = lookup k r
 
249
 
 
250
  -- Converts the tree to an ordered list. Linear in the size of the
 
251
  -- tree.
 
252
 
 
253
  open DiffList
 
254
 
 
255
  toDiffList : ∀ {h} → Tree h → DiffList KV
 
256
  toDiffList leaf           = []
 
257
  toDiffList (node l k r _) = toDiffList l ++ [ k ] ++ toDiffList r
 
258
 
 
259
------------------------------------------------------------------------
 
260
-- Types and functions with hidden indices
 
261
 
 
262
data Tree : Set where
 
263
  tree : ∀ {h} → Indexed.Tree h → Tree
 
264
 
 
265
empty : Tree
 
266
empty = tree Indexed.empty
 
267
 
 
268
singleton : (k : Key) → Value k → Tree
 
269
singleton k v = tree (Indexed.singleton k v)
 
270
 
 
271
insert : (k : Key) → Value k → Tree → Tree
 
272
insert k v (tree t) with Indexed.insert k v t
 
273
... | (_ , t′) = tree t′
 
274
 
 
275
delete : Key → Tree → Tree
 
276
delete k (tree t) with Indexed.delete k t
 
277
... | (_ , t′) = tree t′
 
278
 
 
279
lookup : (k : Key) → Tree → Maybe (∃ λ k′ → Value k′ × k ≈ k′)
 
280
lookup k (tree t) = Indexed.lookup k t
 
281
 
 
282
_∈?_ : Key → Tree → Bool
 
283
k ∈? t = maybeToBool (lookup k t)
 
284
 
 
285
headTail : Tree → Maybe (KV × Tree)
 
286
headTail (tree Indexed.leaf)  = nothing
 
287
headTail (tree {h = suc _} t) with Indexed.headTail t
 
288
... | (k , _ , t′) = just (k , tree t′)
 
289
 
 
290
initLast : Tree → Maybe (Tree × KV)
 
291
initLast (tree Indexed.leaf)  = nothing
 
292
initLast (tree {h = suc _} t) with Indexed.initLast t
 
293
... | ((_ , t′) , k) = just (tree t′ , k)
 
294
 
 
295
-- The input does not need to be ordered.
 
296
 
 
297
fromList : List KV → Tree
 
298
fromList = List.foldr (uncurry insert) empty
 
299
 
 
300
-- Returns an ordered list.
 
301
 
 
302
toList : Tree → List KV
 
303
toList (tree t) = DiffList.toList (Indexed.toDiffList t)