-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSkpLstClass.pas
171 lines (143 loc) · 3.37 KB
/
SkpLstClass.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
unit SkpLstClass;
interface
uses System.SysUtils;
const
MaxLevel=20; // ìàêñèìàëüíûé óðîâåíü ñïèñêà
inf=200000;
type
Valuetype = longint; // òèï èíôî÷àñòè
Snode=^Skiptype;
Skiptype=record
key:longint;
value:Valuetype;
next:array[1..MaxLevel] of Snode;
end;
Listtype=record
level:integer;
header,tail:Snode;
end;
type
SkipList = class
private
List : Listtype; // îáúåêò ñïèñêà
emptyNode : Skiptype; // ïóñòîé óçåë
update : array[1..MaxLevel] of Snode; // áóôåðíûé óçåë
function RandomLevel() : integer; // ãåíåðàöèÿ ñëó÷àéíîãî óðîâíÿ
public
property GetList : Listtype read List write List; // äëÿ ïåðåäà÷è ñïèñêà âîâíå
function Search(key : longint; var res : Valuetype) : boolean; // ïîèñê
procedure Insert(key : longint; value : Valuetype); // âñòàâêà
procedure Remove(key : longint); // óäàëåíèå
constructor Create();
end;
implementation
constructor SkipList.Create();
var
i:integer;
begin
// Çàïîëíÿåò ðàçäåë ïàìÿòè çíà÷åíèåì áàéòà èëè ñèìâîëà-çàïîëíèòåëÿ
fillchar(Emptynode,sizeof(Emptynode),0);
List.level:=1;
// Ñîçäàíèå íîâîãî ñïèñêà
new(List.header);
List.header^:=Emptynode;
List.header^.key:=-inf;
new(List.tail);
List.tail^:=Emptynode;
List.tail^.key:=inf;
for i:=1 to MaxLevel do
List.header^.next[i]:=List.tail;
for i:=1 to MaxLevel do
update[i]:=List.header;
end;
function SkipList.RandomLevel : integer;
var
lev : integer;
begin
lev := 1;
while random < 0.5 do lev := lev + 1; // âåðîÿòíîñòü ð = 0.5
RandomLevel := lev;
end;
function SkipList.Search(key : longint; var res : Valuetype) : boolean;
var
x:Snode;
i:integer;
begin
x:=List.header;
// ïîèñê ýëåìåíòà
for i:=List.level downto 1 do
begin
while x^.next[i]^.key < key do
x:=x^.next[i];
end;
// ïðîâåðêà íà ðåçóëüòàò
x:=x^.next[1];
if x^.key=key then
begin
res := x^.value;
Search := true
end
else
Search := false;
end;
Procedure SkipList.Insert(key : longint; value : Valuetype);
var
x:Snode;
lvl, i : integer;
update : array[1..MaxLevel] of Snode;
begin
x:=List.header;
// ðàññ÷åò ïîçèöèè
for i := List.level downto 1 do
begin
while x^.next[i]^.key < key do
x := x^.next[i];
update[i] := x;
end;
if x^.next[1]^.key = key then
begin
x:=x^.next[1];
x^.value:= value;
end else
begin
// îïðåäåëåíèå óðîâíÿ
lvl := RandomLevel;
if lvl > List.level then begin
for i := List.level + 1 to lvl do
update[i] := List.header;
List.level := lvl;
end;
new(x);
x^ := Emptynode;
x^.key := key;
x^.value := value;
// âñòàâêà íà òðåáóåìûå óðîâíè
for i:=1 to lvl do begin
x^.next[i] := update[i]^.next[i];
update[i]^.next[i] := x;
end;
end;
end;
Procedure SkipList.Remove(key : longint);
var
x:Snode;
i:integer;
update:array[1..MaxLevel] of Snode;
begin
x:=List.header;
for i:=List.level downto 1 do begin
while x^.next[i]^.key<key do x:=x^.next[i];
update[i]:=x;
end;
if x^.next[1]^.key = key then begin
x:=x^.next[1];
for i:=1 to List.level do begin
if update[i]^.next[i]^.key <> key then break;
update[i]^.next[i]:=x^.next[i];
end;
dispose(x);
while (List.level > 1) and (List.header^.next[List.level] = List.tail) do
dec(List.level);
end;
end;
end.