source: branches/delphi/IPQ.pas

Last change on this file was 2, checked in by chronos, 7 years ago
File size: 2.9 KB
Line 
1{binary heap priority queue
2code contributed by Rassim Eminli}
3
4{$INCLUDE switches.pas}
5
6unit IPQ;
7
8interface
9
10type
11
12TIntegerArray = array[0..$40000000 div sizeof(integer)] of integer;
13PIntegerArray = ^TIntegerArray;
14
15TheapItem = record
16 Item: integer;
17 Value: integer;
18end;
19
20TItemArray = array[0..$40000000 div sizeof(TheapItem)] of TheapItem;
21PItemArray = ^TItemArray;
22
23TIPQ = class
24 constructor Create(max: integer);
25 destructor Destroy; override;
26 procedure Empty;
27 function Put(Item, Value: integer): boolean;
28 function TestPut(Item, Value: integer): boolean;
29 function Get(var Item, Value: integer): boolean;
30private
31// n - is the size of the heap.
32// fmax - is the max size of the heap.
33 n, fmax: integer;
34
35// bh - stores (Value, Item) pairs of the heap.
36// Ix - stores the positions of pairs in the heap bh.
37 bh: PItemArray;
38 Ix: PIntegerArray;
39 end;
40
41
42implementation
43
44constructor TIPQ.Create(max: integer);
45begin
46 inherited Create;
47 fmax := max;
48 GetMem(bh, fmax*SizeOf(TheapItem));
49 GetMem(Ix, fmax*SizeOf(integer));
50 n:=-1;
51 Empty
52end;
53
54destructor TIPQ.Destroy;
55begin
56 FreeMem(bh);
57 FreeMem(Ix);
58 inherited Destroy;
59end;
60
61procedure TIPQ.Empty;
62begin
63 if n <> 0 then
64 begin
65 FillChar(Ix^, fmax*sizeOf(integer), 255);
66 n := 0;
67 end;
68end;
69
70//Parent(i) = (i-1)/2.
71function TIPQ.Put(Item, Value: integer): boolean; //O(lg(n))
72var
73 i, j: integer;
74 lbh: PItemArray;
75 lIx: PIntegerArray;
76begin
77 lIx := Ix;
78 lbh := bh;
79 i := lIx[Item];
80 if i >= 0 then
81 begin
82 if lbh[i].Value <= Value then
83 begin
84 result := False;
85 exit;
86 end;
87 end
88 else
89 begin
90 i := n;
91 Inc(n);
92 end;
93
94 while i > 0 do
95 begin
96 j := (i-1) shr 1; //Parent(i) = (i-1)/2
97 if Value >= lbh[j].Value then break;
98 lbh[i] := lbh[j];
99 lIx[lbh[i].Item] := i;
100 i := j;
101 end;
102 // Insert the new Item at the insertion point found.
103 lbh[i].Value := Value;
104 lbh[i].Item := Item;
105 lIx[lbh[i].Item] := i;
106 result := True;
107end;
108
109function TIPQ.TestPut(Item, Value: integer): boolean;
110var
111 i: integer;
112begin
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 TIPQ.Get(var Item, Value: integer): boolean; //O(lg(n))
120var
121 i, j: integer;
122 last: TheapItem;
123 lbh: PItemArray;
124begin
125 if n = 0 then
126 begin
127 result := False;
128 exit;
129 end;
130
131 lbh := bh;
132 Item := lbh[0].Item;
133 Value := lbh[0].Value;
134
135 Ix[Item] := -1;
136
137 dec(n);
138 if n > 0 then
139 begin
140 last := lbh[n];
141 i := 0; 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 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.
163
Note: See TracBrowser for help on using the repository browser.