source: tags/1.3.1/IPQ.pas

Last change on this file was 442, checked in by chronos, 2 years ago
  • Modified: Code cleanup.
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
39implementation
40
41constructor TIPQ.Create(max: integer);
42begin
43 inherited Create;
44 fmax := max;
45 GetMem(bh, fmax * sizeof(TheapItem));
46 GetMem(Ix, fmax * sizeof(integer));
47 n := -1;
48 Empty;
49end;
50
51destructor TIPQ.Destroy;
52begin
53 FreeMem(bh);
54 FreeMem(Ix);
55 inherited;
56end;
57
58procedure TIPQ.Empty;
59begin
60 if n <> 0 then
61 begin
62 FillChar(Ix^, fmax * sizeof(integer), 255);
63 n := 0;
64 end;
65end;
66
67// Parent(i) = (i-1)/2.
68function TIPQ.Put(Item, Value: integer): boolean; // O(lg(n))
69var
70 i, j: integer;
71 lbh: PItemArray;
72 lIx: PIntegerArray;
73begin
74 lIx := Ix;
75 lbh := bh;
76 i := lIx[Item];
77 if i >= 0 then
78 begin
79 if lbh[i].Value <= Value then
80 begin
81 result := False;
82 exit;
83 end;
84 end
85 else
86 begin
87 i := n;
88 Inc(n);
89 end;
90
91 while i > 0 do
92 begin
93 j := (i - 1) shr 1; // Parent(i) = (i-1)/2
94 if Value >= lbh[j].Value then
95 break;
96 lbh[i] := lbh[j];
97 lIx[lbh[i].Item] := i;
98 i := j;
99 end;
100 // Insert the new Item at the insertion point found.
101 lbh[i].Value := Value;
102 lbh[i].Item := Item;
103 lIx[lbh[i].Item] := i;
104 result := True;
105end;
106
107function TIPQ.TestPut(Item, Value: integer): boolean;
108var
109 i: integer;
110begin
111 i := Ix[Item];
112 result := (i < 0) or (bh[i].Value > Value);
113end;
114
115// Left(i) = 2*i+1.
116// Right(i) = 2*i+2 => Left(i)+1
117function TIPQ.Get(var Item, Value: integer): boolean; // O(lg(n))
118var
119 i, j: integer;
120 last: TheapItem;
121 lbh: PItemArray;
122begin
123 if n = 0 then
124 begin
125 result := False;
126 exit;
127 end;
128
129 lbh := bh;
130 Item := lbh[0].Item;
131 Value := lbh[0].Value;
132
133 Ix[Item] := -1;
134
135 dec(n);
136 if n > 0 then
137 begin
138 last := lbh[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 (lbh[j].Value > lbh[j + 1].Value) then
145 Inc(j);
146 if last.Value <= lbh[j].Value then
147 break;
148
149 lbh[i] := lbh[j];
150 Ix[lbh[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 lbh[i] := last;
157 Ix[last.Item] := i;
158 end;
159 result := True;
160end;
161
162end.
Note: See TracBrowser for help on using the repository browser.