blob: 76e4b1d6190afafc524b908d3893770034dc9f34 (
plain)
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
|
class PriorityQueue {
var N: int; // capacity
var n: int; // current size
ghost var Repr: set<object>; // set of objects that make up the representation of a PriorityQueue
var a: array<int>; // private implementation of PriorityQueu
function Valid(): bool
reads this, Repr;
{
MostlyValid() &&
(forall j :: 2 <= j && j <= n ==> a[j/2] <= a[j])
}
function MostlyValid(): bool
reads this, Repr;
{
this in Repr && a in Repr &&
a != null && a.Length == N+1 &&
0 <= n && n <= N
}
method Init(capacity: int)
requires 0 <= capacity;
modifies this;
ensures Valid() && fresh(Repr - {this});
ensures N == capacity;
{
N := capacity;
var arr := new int[N+1];
a := arr;
n := 0;
Repr := {this};
Repr := Repr + {a};
}
method Insert(x: int)
requires Valid() && n < N;
modifies this, a;
ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) + 1 && N == old(N);
{
n := n + 1;
a[n] := x;
call SiftUp(n);
}
method SiftUp(k: int)
requires 1 <= k && k <= n;
requires MostlyValid();
requires (forall j :: 2 <= j && j <= n && j != k ==> a[j/2] <= a[j]);
requires (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j != k ==> a[j/2/2] <= a[j]);
modifies a;
ensures Valid();
{
var i := k;
assert MostlyValid();
while (1 < i)
invariant i <= k && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
invariant (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j != i ==> a[j/2/2] <= a[j]);
{
if (a[i/2] <= a[i]) {
return;
}
var tmp := a[i]; a[i] := a[i/2]; a[i/2] := tmp;
i := i / 2;
}
}
method RemoveMin() returns (x: int)
requires Valid() && 1 <= n;
modifies this, a;
ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) - 1;
{
x := a[1];
a[1] := a[n];
n := n - 1;
call SiftDown(1);
}
method SiftDown(k: int)
requires 1 <= k;
requires MostlyValid();
requires (forall j :: 2 <= j && j <= n && j/2 != k ==> a[j/2] <= a[j]);
requires (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != k ==> a[j/2/2] <= a[j]);
modifies a;
ensures Valid();
{
var i := k;
while (2*i <= n) // while i is not a leaf
invariant 1 <= i && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
invariant (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != i ==> a[j/2/2] <= a[j]);
{
var smallestChild;
if (2*i + 1 <= n && a[2*i + 1] < a[2*i]) {
smallestChild := 2*i + 1;
} else {
smallestChild := 2*i;
}
if (a[i] <= a[smallestChild]) {
return;
}
var tmp := a[i]; a[i] := a[smallestChild]; a[smallestChild] := tmp;
i := smallestChild;
assert 1 <= i/2/2 ==> a[i/2/2] <= a[i];
}
}
}
|