source: trunk/AI Template/Pile.pas

Last change on this file was 583, checked in by chronos, 6 months ago
  • Modified: Code cleanup.
File size: 3.0 KB
Line 
1{single instance priority queue
2main parts contributed by Rassim Eminli}
3
4{$INCLUDE Switches.inc}
5
6unit Pile;
7
8interface
9
10procedure Create(Size: Integer);
11procedure Free;
12procedure Empty;
13function Put(Item, Value: Integer): Boolean;
14function TestPut(Item, Value: Integer): Boolean;
15function Get(var Item, Value: Integer): Boolean;
16
17
18implementation
19
20const
21 MaxSize = 9600;
22
23type
24 TheapItem = record
25 Item: Integer;
26 Value: Integer;
27 end;
28
29var
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
36procedure Create(Size: Integer);
37begin
38 {$IFDEF DEBUG}
39 Assert(not InUse, 'Pile is a single instance class, ' +
40 'no multiple usage possible. Always call Pile.Free after use.');
41{$ENDIF}
42 Assert(Size <= MaxSize);
43 if (N <> 0) or (Size > CurrentSize) then
44 begin
45 FillChar(Ix, Size * SizeOf(Integer), 255);
46 N := 0;
47 end;
48 CurrentSize := Size;
49{$IFDEF DEBUG}
50 InUse := True;
51{$ENDIF}
52end;
53
54procedure Free;
55begin
56{$IFDEF DEBUG}
57 Assert(InUse);
58 InUse := False;
59{$ENDIF}
60end;
61
62procedure Empty;
63begin
64 if N <> 0 then
65 begin
66 FillChar(Ix, CurrentSize * SizeOf(Integer), 255);
67 N := 0;
68 end;
69end;
70
71// Parent(i) = (i-1)/2.
72function Put(Item, Value: Integer): Boolean; // O(lg(n))
73var
74 I, J: Integer;
75begin
76 Assert(Item < CurrentSize);
77 I := Ix[Item];
78 if I >= 0 then
79 begin
80 if bh[I].Value <= Value then
81 begin
82 Result := False;
83 Exit;
84 end;
85 end
86 else
87 begin
88 I := N;
89 Inc(N);
90 end;
91
92 while I > 0 do
93 begin
94 J := (I - 1) shr 1; // Parent(i) = (i-1)/2
95 if Value >= bh[J].Value then
96 Break;
97 bh[I] := bh[J];
98 Ix[bh[I].Item] := I;
99 I := J;
100 end;
101 // Insert the new Item at the insertion point found.
102 bh[I].Value := Value;
103 bh[I].Item := Item;
104 Ix[bh[I].Item] := I;
105 Result := True;
106end;
107
108function TestPut(Item, Value: Integer): Boolean;
109var
110 I: Integer;
111begin
112 Assert(Item < CurrentSize);
113 I := Ix[Item];
114 Result := (I < 0) or (bh[I].Value > Value);
115end;
116
117//Left(i) = 2*i+1.
118//Right(i) = 2*i+2 => Left(i)+1
119function Get(var Item, Value: Integer): Boolean; //O(lg(n))
120var
121 I, J: Integer;
122 Last: TheapItem;
123begin
124 if N = 0 then
125 begin
126 Result := False;
127 Exit;
128 end;
129
130 Item := bh[0].Item;
131 Value := bh[0].Value;
132
133 Ix[Item] := -1;
134
135 Dec(N);
136 if N > 0 then
137 begin
138 Last := bh[N];
139 I := 0;
140 J := 1;
141 while J < N do
142 begin
143 // Right(i) = Left(i)+1
144 if (J < N - 1) and (bh[J].Value > bh[J + 1].Value) then
145 Inc(J);
146 if Last.Value <= bh[J].Value then
147 Break;
148
149 bh[I] := bh[J];
150 Ix[bh[I].Item] := I;
151 I := J;
152 J := J shl 1 + 1; //Left(j) = 2*j+1
153 end;
154
155 // Insert the root in the correct place in the heap.
156 bh[I] := Last;
157 Ix[Last.Item] := I;
158 end;
159 Result := True;
160end;
161
162initialization
163 N := 0;
164 CurrentSize := 0;
165{$IFDEF DEBUG}
166 InUse := False;
167{$ENDIF}
168end.
Note: See TracBrowser for help on using the repository browser.