source: tags/1.3.4/IPQ.pas

Last change on this file was 468, checked in by chronos, 12 months ago
  • Added: High DPI support integrated into trunk branch. It can be enabled by adding DPI define to compiler parameters for main project and packages.
File size: 3.1 KB
Line 
1{ binary heap priority queue
2 Code contributed by Rassim Eminli }
3
4{$INCLUDE Switches.inc}
5unit IPQ;
6
7interface
8
9type
10 TIntegerArray = array [0 .. $40000000 div SizeOf(Integer)] of Integer;
11 PIntegerArray = ^TIntegerArray;
12
13 THeapItem = record
14 Item: Integer;
15 Value: Integer;
16 end;
17
18 TItemArray = array [0 .. $40000000 div SizeOf(THeapItem)] of THeapItem;
19 PItemArray = ^TItemArray;
20
21 TIPQ = class
22 constructor Create(Max: Integer);
23 destructor Destroy; override;
24 procedure Empty;
25 function Put(Item, Value: Integer): Boolean;
26 function TestPut(Item, Value: Integer): Boolean;
27 function Get(var Item, Value: Integer): Boolean;
28 private
29 // n - is the size of the heap.
30 // fmax - is the max size of the heap.
31 N, fmax: Integer;
32
33 // bh - stores (Value, Item) pairs of the heap.
34 // Ix - stores the positions of pairs in the heap bh.
35 bh: PItemArray;
36 Ix: PIntegerArray;
37 end;
38
39
40implementation
41
42constructor TIPQ.Create(Max: Integer);
43begin
44 inherited Create;
45 fmax := Max;
46 GetMem(bh, fmax * SizeOf(THeapItem));
47 GetMem(Ix, fmax * SizeOf(Integer));
48 N := -1;
49 Empty;
50end;
51
52destructor TIPQ.Destroy;
53begin
54 FreeMem(bh);
55 FreeMem(Ix);
56 inherited;
57end;
58
59procedure TIPQ.Empty;
60begin
61 if N <> 0 then
62 begin
63 FillChar(Ix^, fmax * SizeOf(Integer), 255);
64 N := 0;
65 end;
66end;
67
68// Parent(i) = (i-1)/2.
69function TIPQ.Put(Item, Value: Integer): Boolean; // O(lg(n))
70var
71 I, J: Integer;
72 lbh: PItemArray;
73 lIx: PIntegerArray;
74begin
75 lIx := Ix;
76 lbh := bh;
77 I := lIx[Item];
78 if I >= 0 then
79 begin
80 if lbh[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 >= lbh[J].Value then
96 Break;
97 lbh[I] := lbh[J];
98 lIx[lbh[I].Item] := I;
99 I := J;
100 end;
101 // Insert the new Item at the insertion point found.
102 lbh[I].Value := Value;
103 lbh[I].Item := Item;
104 lIx[lbh[I].Item] := I;
105 Result := True;
106end;
107
108function TIPQ.TestPut(Item, Value: Integer): Boolean;
109var
110 I: Integer;
111begin
112 I := Ix[Item];
113 Result := (I < 0) or (bh[I].Value > Value);
114end;
115
116// Left(i) = 2*i+1.
117// Right(i) = 2*i+2 => Left(i)+1
118function TIPQ.Get(var Item, Value: Integer): Boolean; // O(lg(n))
119var
120 I, J: Integer;
121 Last: THeapItem;
122 lbh: PItemArray;
123begin
124 if N = 0 then
125 begin
126 Result := False;
127 Exit;
128 end;
129
130 lbh := bh;
131 Item := lbh[0].Item;
132 Value := lbh[0].Value;
133
134 Ix[Item] := -1;
135
136 Dec(N);
137 if N > 0 then
138 begin
139 Last := lbh[N];
140 I := 0;
141 J := 1;
142 while J < N do
143 begin
144 // Right(i) = Left(i)+1
145 if (J < N - 1) and (lbh[J].Value > lbh[J + 1].Value) then
146 Inc(J);
147 if Last.Value <= lbh[J].Value then
148 Break;
149
150 lbh[I] := lbh[J];
151 Ix[lbh[I].Item] := I;
152 I := J;
153 J := J shl 1 + 1; // Left(j) = 2*j+1
154 end;
155
156 // Insert the root in the correct place in the heap.
157 lbh[I] := Last;
158 Ix[Last.Item] := I;
159 end;
160 Result := True;
161end;
162
163end.
Note: See TracBrowser for help on using the repository browser.