1 | {single instance priority queue
|
---|
2 | main parts contributed by Rassim Eminli}
|
---|
3 |
|
---|
4 | {$INCLUDE Switches.inc}
|
---|
5 |
|
---|
6 | unit Pile;
|
---|
7 |
|
---|
8 | interface
|
---|
9 |
|
---|
10 | procedure Create(Size: integer);
|
---|
11 | procedure Free;
|
---|
12 | procedure Empty;
|
---|
13 | function Put(Item, Value: integer): boolean;
|
---|
14 | function TestPut(Item, Value: integer): boolean;
|
---|
15 | function Get(var Item, Value: integer): boolean;
|
---|
16 |
|
---|
17 |
|
---|
18 | implementation
|
---|
19 |
|
---|
20 | const
|
---|
21 | MaxSize=9600;
|
---|
22 |
|
---|
23 | type
|
---|
24 | TheapItem = record
|
---|
25 | Item: integer;
|
---|
26 | Value: integer;
|
---|
27 | end;
|
---|
28 |
|
---|
29 | var
|
---|
30 | bh: array[0..MaxSize-1] of TheapItem;
|
---|
31 | Ix: array[0..MaxSize-1] of integer;
|
---|
32 | n, CurrentSize: integer;
|
---|
33 | {$IFDEF DEBUG}InUse: boolean;{$ENDIF}
|
---|
34 |
|
---|
35 |
|
---|
36 | procedure Create(Size: integer);
|
---|
37 | begin
|
---|
38 | {$IFDEF DEBUG}assert(not InUse, 'Pile is a single instance class, '
|
---|
39 | +'no multiple usage possible. Always call Pile.Free after use.');{$ENDIF}
|
---|
40 | assert(Size<=MaxSize);
|
---|
41 | if (n <> 0) or (Size > CurrentSize) then
|
---|
42 | begin
|
---|
43 | FillChar(Ix, Size*sizeOf(integer), 255);
|
---|
44 | n := 0;
|
---|
45 | end;
|
---|
46 | CurrentSize := Size;
|
---|
47 | {$IFDEF DEBUG}InUse:=true;{$ENDIF}
|
---|
48 | end;
|
---|
49 |
|
---|
50 | procedure Free;
|
---|
51 | begin
|
---|
52 | {$IFDEF DEBUG}assert(InUse);InUse:=false;{$ENDIF}
|
---|
53 | end;
|
---|
54 |
|
---|
55 | procedure Empty;
|
---|
56 | begin
|
---|
57 | if n <> 0 then
|
---|
58 | begin
|
---|
59 | FillChar(Ix, CurrentSize*sizeOf(integer), 255);
|
---|
60 | n := 0;
|
---|
61 | end;
|
---|
62 | end;
|
---|
63 |
|
---|
64 | //Parent(i) = (i-1)/2.
|
---|
65 | function Put(Item, Value: integer): boolean; //O(lg(n))
|
---|
66 | var
|
---|
67 | i, j: integer;
|
---|
68 | begin
|
---|
69 | assert(Item<CurrentSize);
|
---|
70 | i := Ix[Item];
|
---|
71 | if i >= 0 then
|
---|
72 | begin
|
---|
73 | if bh[i].Value <= Value then
|
---|
74 | begin
|
---|
75 | result := False;
|
---|
76 | exit;
|
---|
77 | end;
|
---|
78 | end
|
---|
79 | else
|
---|
80 | begin
|
---|
81 | i := n;
|
---|
82 | Inc(n);
|
---|
83 | end;
|
---|
84 |
|
---|
85 | while i > 0 do
|
---|
86 | begin
|
---|
87 | j := (i-1) shr 1; //Parent(i) = (i-1)/2
|
---|
88 | if Value >= bh[j].Value then break;
|
---|
89 | bh[i] := bh[j];
|
---|
90 | Ix[bh[i].Item] := i;
|
---|
91 | i := j;
|
---|
92 | end;
|
---|
93 | // Insert the new Item at the insertion point found.
|
---|
94 | bh[i].Value := Value;
|
---|
95 | bh[i].Item := Item;
|
---|
96 | Ix[bh[i].Item] := i;
|
---|
97 | result := True;
|
---|
98 | end;
|
---|
99 |
|
---|
100 | function TestPut(Item, Value: integer): boolean;
|
---|
101 | var
|
---|
102 | i: integer;
|
---|
103 | begin
|
---|
104 | assert(Item<CurrentSize);
|
---|
105 | i := Ix[Item];
|
---|
106 | result := (i < 0) or (bh[i].Value > Value);
|
---|
107 | end;
|
---|
108 |
|
---|
109 | //Left(i) = 2*i+1.
|
---|
110 | //Right(i) = 2*i+2 => Left(i)+1
|
---|
111 | function Get(var Item, Value: integer): boolean; //O(lg(n))
|
---|
112 | var
|
---|
113 | i, j: integer;
|
---|
114 | last: TheapItem;
|
---|
115 | begin
|
---|
116 | if n = 0 then
|
---|
117 | begin
|
---|
118 | result := False;
|
---|
119 | exit;
|
---|
120 | end;
|
---|
121 |
|
---|
122 | Item := bh[0].Item;
|
---|
123 | Value := bh[0].Value;
|
---|
124 |
|
---|
125 | Ix[Item] := -1;
|
---|
126 |
|
---|
127 | dec(n);
|
---|
128 | if n > 0 then
|
---|
129 | begin
|
---|
130 | last := bh[n];
|
---|
131 | i := 0; j := 1;
|
---|
132 | while j < n do
|
---|
133 | begin
|
---|
134 | // Right(i) = Left(i)+1
|
---|
135 | if(j < n-1) and (bh[j].Value > bh[j + 1].Value)then
|
---|
136 | inc(j);
|
---|
137 | if last.Value <= bh[j].Value then break;
|
---|
138 |
|
---|
139 | bh[i] := bh[j];
|
---|
140 | Ix[bh[i].Item] := i;
|
---|
141 | i := j;
|
---|
142 | j := j shl 1+1; //Left(j) = 2*j+1
|
---|
143 | end;
|
---|
144 |
|
---|
145 | // Insert the root in the correct place in the heap.
|
---|
146 | bh[i] := last;
|
---|
147 | Ix[last.Item] := i;
|
---|
148 | end;
|
---|
149 | result := True
|
---|
150 | end;
|
---|
151 |
|
---|
152 | initialization
|
---|
153 | n:=0;
|
---|
154 | CurrentSize:=0;
|
---|
155 | {$IFDEF DEBUG}InUse:=false;{$ENDIF}
|
---|
156 | end.
|
---|
157 |
|
---|