source: branches/delphi/AI/Pile.pas

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