source: branches/AlphaChannel/IPQ.pas

Last change on this file was 38, checked in by chronos, 7 years ago
  • Modified: Switches.pas renamed to Switches.inc.
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
11 TIntegerArray = array [0 .. $40000000 div sizeof(integer)] of integer;
12 PIntegerArray = ^TIntegerArray;
13
14 TheapItem = record
15 Item: integer;
16 Value: integer;
17 end;
18
19 TItemArray = array [0 .. $40000000 div sizeof(TheapItem)] of TheapItem;
20 PItemArray = ^TItemArray;
21
22 TIPQ = class
23 constructor Create(max: integer);
24 destructor Destroy; override;
25 procedure Empty;
26 function Put(Item, Value: integer): boolean;
27 function TestPut(Item, Value: integer): boolean;
28 function Get(var Item, Value: integer): boolean;
29 private
30 // n - is the size of the heap.
31 // fmax - is the max size of the heap.
32 n, fmax: integer;
33
34 // bh - stores (Value, Item) pairs of the heap.
35 // Ix - stores the positions of pairs in the heap bh.
36 bh: PItemArray;
37 Ix: PIntegerArray;
38 end;
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 Destroy;
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.