偶然机会接触到这家公司的,具体信息就不说了。
看了他们前台发的面试题,关于三个方向的:
链表,skip list,是一个1-2-3确定性链表。
字符串匹配 Edit distance
文档摘要提取。
1-2-3skip list是一种特殊的skip list。其中两个节点之间的间隙容量应该是1、2、3,除了头和尾之间可能有零间隙外。
在数值结构和算法分析 C语言版本中,有关于此的介绍。其中给出了find 和insert的程序,但是没有给出remove的程序。
其实,关于find 和insert还是很好实现的。只要了解其结构,再加上具有链表的一些知识,因为一直在用链表,所以对这部分还是很容易理解的。只是,remove部分需要注意很多地方是很难实现的。
首先,注意到,需要添加一个前端链表指针,其次,需要注意在删除节点的过程中,注意结构的变化。这里有详细的实现程序,转过来学习学习。http://www.cnblogs.com/rocketfan/archive/2010/02/28/1556797.html
/123 skip list 的实现文件
1
/*
*
2
* /file determin_skip_list.h
3
* /author pku_goldenlock
4
* /date 2009-8-7
5
*/
6
7
#ifndef _DETERMIN_SKIP_LIST_H
8
#define
_DETERMIN_SKIP_LIST_H
9
10
#define
DISALLOW_COPY_AND_ASSIGN(TypeName) /
11
TypeName(
const
TypeName
&
); /
12
void
operator
=
(
const
TypeName
&
)
13
14
#include
<
iostream
>
15//
#include
"
skip_list.h
"
16
namespace
skip_list {
17
18
/*
*
19
* class SkipNode.
20
* the node type for DeterminSkipList to operate.
21
*/
22
template
<
typename ElemType
>
23
class
SkipNode {
24
public
:
25
template
<
typename T
>
friend
class
DeterminSkipList;
26
SkipNode();
27
SkipNode(
const
ElemType
&
key_input, SkipNode
*
right_input
=
NULL,
28
SkipNode
*
down_input
=
NULL);
29
private
:
30
DISALLOW_COPY_AND_ASSIGN(SkipNode);
/*
* Do not all copy and assign
*/
31
ElemType key;
/*
*< The key is what we use for comparing during Search,Insert,Remove.
*/
32
SkipNode
*
right;
/*
*< Point to the right skip node ont the same level
*/
33
SkipNode
*
down;
/*
*< Point to the lower level skip node where we will go down from current node
*/
34
};
35
36
template
<
typename ElemType
>
37
SkipNode
<
ElemType
>
::SkipNode() : right(NULL), down(NULL) {}
38
39
template
<
typename ElemType
>
40
SkipNode
<
ElemType
>
::SkipNode(
const
ElemType
&
key_input, SkipNode
*
right_input,
41
SkipNode
*
down_input)
42
: key(key_input), right(right_input), down(down_input) {}
43
44
/*
*
45
* DeterminSkipList
46
* An implementaion of skip list using 1-2-3 skip list
47
*/
48
template
<
typename ElemType
>
49
class
DeterminSkipList {
50
public
:
51
/*
* Client should determin Max and Max + 1 value
*/
52
DeterminSkipList(
const
ElemType
&
max,
const
ElemType
&
max_1);
53
~
DeterminSkipList();
54
/*
* Clear the whoe skip list free all allocated resouces on heap
*/
55
void
Clear();
56
bool
Search(
const
ElemType
&
value)
const
;
57
/*
*
58
* If the list already has one node whose key == value
59
* return false and do not do insert otherwise insert a new node with
60
* its key == value and return true
61
*/
62
bool
Insert(
const
ElemType
&
value);
63
/*
*
64
* If the list already has one node whose key == value
65
* remove it and return true otherwise return false
66
*/
67
bool
Remove(
const
ElemType
&
value);
68
/*
* For debug
*/
69
/*
* Show the internal structure of the skip list
*/
70
void
Print()
const
;
71
/*
* Return false if current structure of the skip list is wrong
*/
72
bool
IsValid()
const
;
73
74
private
:
75
/*
* For simplicty here do not allow copy and assign
*/
76
DISALLOW_COPY_AND_ASSIGN(DeterminSkipList);
77
void
Init();
78
void
ClearHelp(SkipNode
<
ElemType
>
*
current);
79
/*
*
80
* Helper function for Search
81
* If could not find one node with key value == item return bottom
82
* otherwise return postion of node containing the key
83
*
*/
84
SkipNode
<
ElemType
>
*
SearchHelp(
const
ElemType
&
value)
const
;
85
/*
* Helper function for Remove, find all the nodes with key == value and modify it to other_value
*/
86
void
FindAndModifyRemoveHelp(
const
ElemType
&
value,
const
ElemType
&
other_value);
87
/*
* lower the head if possible during Remove help to keep skip list structure consistent
*/
88
void
LowerHeadRemoveHelp();
89
90
private
:
91
//
actual data skip list store
92
SkipNode
<
ElemType
>
*
head;
/*
*< where we start
*/
93
SkipNode
<
ElemType
>
*
bottom;
/*
*< mark if we have down to the lowerest level
*/
94
SkipNode
<
ElemType
>
*
tail;
/*
*< mark the end of each level
*/
95
96
const
ElemType Max;
/*
*< Max > any client input key value
*/
97
const
ElemType Max_1;
/*
*< Max_1 > Max
*/
98
};
99
100
template
<
typename ElemType
>
101
DeterminSkipList
<
ElemType
>
::DeterminSkipList(
const
ElemType
&
max,
const
ElemType
&
max_1)
102
: head(NULL), bottom(NULL), tail(NULL), Max(max), Max_1(max_1)
103
{
104
Init();
105
}
106
107
template
<
typename ElemType
>
108
DeterminSkipList
<
ElemType
>
::
~
DeterminSkipList()
109
{
110
if
(head) {
111
Clear();
112
}
113
}
114
115
template
<
typename ElemType
>
116
void
DeterminSkipList
<
ElemType
>
::Init()
117
{
118
//
init head bottom and tail see paper p372 figure 6
119
bottom
=
new
SkipNode
<
ElemType
>
;
120
bottom
->
right
=
bottom
->
down
=
bottom;
121
122
tail
=
new
SkipNode
<
ElemType
>
(Max_1);
123
tail
->
right
=
tail;
124
125
head
=
new
SkipNode
<
ElemType
>
(Max, tail, bottom);
126
}
127
128
template
<
typename ElemType
>
129
void
DeterminSkipList
<
ElemType
>
::Clear()
130
{
131
ClearHelp(head
->
down);
132
delete head;
133
delete bottom;
134
delete tail;
135
head
=
NULL;
136
bottom
=
NULL;
137
tail
=
NULL;
138
}
139
140
template
<
typename ElemType
>
141
void
DeterminSkipList
<
ElemType
>
::ClearHelp(SkipNode
<
ElemType
>
*
current)
142
{
143
SkipNode
<
ElemType
>
*
temp;
144
if
(current
==
bottom)
145
return
;
146
ClearHelp(current
->
down);
147
while
(current
!=
tail) {
148
temp
=
current;
149
current
=
current
->
right;
150
delete temp;
151
}
152
}
153
154
template
<
typename ElemType
>
155
inline
bool
DeterminSkipList
<
ElemType
>
::Search(
const
ElemType
&
value)
const
156
{
157
return
((SearchHelp(value)
==
bottom)
?
false
:
true
);
158
}
159
160
template
<
typename ElemType
>
161
SkipNode
<
ElemType
>
*
DeterminSkipList
<
ElemType
>
::
162
SearchHelp(
const
ElemType
&
value)
const
163
{
164
SkipNode
<
ElemType
>
*
current;
165
166
current
=
head;
167
while
(current
!=
bottom) {
168
while
(value
>
current
->
key)
169
current
=
current
->
right;
170
if
(current
->
down
==
bottom)
171
return
((value
==
current
->
key)
?
current : bottom);
172
current
=
current
->
down;
173
}
174
return
NULL;
175
}
176
177
/*
*
178
* Insert a key value to the skip list.
179
* if that the key value has already existed.
180
* return false and will not insert.
181
* else insert and return true.
182
*/
183
template
<
typename ElemType
>
184
bool
DeterminSkipList
<
ElemType
>
::Insert(
const
ElemType
&
value)
185
{
186
SkipNode
<
ElemType
>
*
current,
*
new_node;
187
188
current
=
head;
189
bottom
->
key
=
value;
190
bool
can_insert
=
true
;
191
while
(current
!=
bottom) {
192
while
(value
>
current
->
key)
193
current
=
current
->
right;
194
//
if exists one elem whose key == value return false do not need insert
195
if
((current
->
down
==
bottom)
&&
(value
==
current
->
key)) {
196
can_insert
=
false
;
//
can not insert but should check if need to adjust head before return
197
break
;
198
}
199
//
if gap size is 3 or at bottom level and must insert
200
//
then promote the middle element
201
if
((current
->
down
==
bottom)
202
||
(current
->
key
>
current
->
down
->
right
->
right
->
key)) {
203
new_node
=
new
SkipNode
<
ElemType
>
;
204
new_node
->
right
=
current
->
right;
205
new_node
->
down
=
current
->
down
->
right
->
right;
206
current
->
right
=
new_node;
207
new_node
->
key
=
current
->
key;
208
current
->
key
=
current
->
down
->
right
->
key;
209
}
210
current
=
current
->
down;
211
}
212
//
if need to raise the height of the skip list,raise it
213
if
(head
->
right
!=
tail) {
214
new_node
=
new
SkipNode
<
ElemType
>
;
215
new_node
->
down
=
head;
216
new_node
->
right
=
tail;
217
new_node
->
key
=
Max;
218
head
=
new_node;
219
}
220
221
return
can_insert;
222
}
223
template
<
typename ElemType
>
224
void
DeterminSkipList
<
ElemType
>
::FindAndModifyRemoveHelp(
const
ElemType
&
value,
const
ElemType
&
other_value)
225
{
226
SkipNode
<
ElemType
>
*
current;
227
228
current
=
head;
229
while
(current
!=
bottom) {
230
while
(value
>
current
->
key)
231
current
=
current
->
right;
232
if
(value
==
current
->
key)
233
current
->
key
=
other_value;
234
current
=
current
->
down;
235
}
236
237
}
238
template
<
typename ElemType
>
239
void
DeterminSkipList
<
ElemType
>
::LowerHeadRemoveHelp()
240
{
241
SkipNode
<
ElemType
>
*
temp;
242
if
(head
->
down
->
right
==
tail) {
243
temp
=
head
->
down;
244
head
->
down
=
temp
->
down;
245
delete temp;
246
}
247
}
248
template
<
typename ElemType
>
249
bool
DeterminSkipList
<
ElemType
>
::Remove(
const
ElemType
&
value)
250
{
251
//
empty list can not remove
252
if
(head
->
down
==
bottom)
253
return
false
;
254
//
current node, previous node of current, start mark the begining of each level when the node goes down
255
//
if previous finally equal to start means have not advanced toward right on this level
256
//
next save the start position of the next level for current node
257
SkipNode
<
ElemType
>
*
current,
*
previous,
*
temp,
*
next;
258
259
current
=
head
->
down;
260
int
visit_num
=
0
;
261
bool
can_remove
=
true
;
262
for
(;;) {
//
loop and will return when curent->down == bottom
263
previous
=
NULL;
264
while
(value
>
current
->
key) {
//
try advance toward right as far as possible
265
previous
=
current;
266
current
=
current
->
right;
267
}
268
//
visit num will mark if a node is a height 1 node
269
if
(value
==
current
->
key)
270
visit_num
++
;
271
272
//
if on level 1 try to remove if possible and return
273
if
(current
->
down
==
bottom) {
274
if
(visit_num
==
0
) {
//
can not find do not need to remove
275
LowerHeadRemoveHelp();
///
might need to lower the head
276
can_remove
=
false
;
277
return
false
;
278
}
279
else
{
//
need to remove
280
if
(visit_num
==
1
) {
//
if node height == 1 just remove it
281
//
delete need to consider down fild of the upper level
282
//
so swap current and current->right
283
temp
=
current
->
right;
//
to be deleted
284
current
->
key
=
current
->
right
->
key;
285
current
->
right
=
temp
->
right;
286
delete temp;
287
LowerHeadRemoveHelp();
///
might need to lower the head
288
}
else
{
289
//
if current node height > 1, swap the key with neighbour than delete the neighbour
290
//
here swap with left neigbour,notice we must have advaced right on
291
//
this level otherwise it must be a height 1 node.
292
//
we will find all the node with key value current->key and modify it
293
//
to previous->key
294
LowerHeadRemoveHelp();
//
need to make sure the sturcture correct first
295
FindAndModifyRemoveHelp(current
->
key, previous
->
key);
296
previous
->
right
=
current
->
right;
297
delete current;
298
}
299
return
true
;
300
}
301
}
302
//
on other levels ,not level 1
303
//
save the postion to go down on the lower level
304
next
=
current
->
down;
//
the next level will be unchaged when dealing the current level
305
//
current->key == current->down->right->key means the gap we want to down
306
//
is of size only 1
307
if
(current
->
key
==
current
->
down
->
right
->
key) {
308
//
the first gap case, consider current gap and the next
309
if
(previous
==
NULL) {
//
have not advanced on this level
310
//
if the next gap has 2 or more one level lower element
311
//
one element need to lower down,the other one need to raise one level,
312
//
just swap do not need to delte space
313
if
(current
->
right
->
key
>
current
->
right
->
down
->
right
->
key) {
314
current
->
key
=
current
->
right
->
down
->
key;
315
current
->
right
->
down
=
current
->
right
->
down
->
right;
316
}
else
{
317
//
one element need to lower down,need to delete space
318
temp
=
current
->
right;
319
current
->
key
=
temp
->
key;
320
current
->
right
=
temp
->
right;
321
delete temp;
322
}
323
}
else
{
//
not the first so consider the privious gap and the current
324
if
(previous
->
key
>
previous
->
down
->
right
->
key) {
325
temp
=
previous
->
down
->
right;
326
if
(temp
->
right
->
key
!=
previous
->
key)
327
temp
=
temp
->
right;
328
previous
->
key
=
temp
->
key;
329
current
->
down
=
temp
->
right;
330
}
else
{
331
previous
->
key
=
current
->
key;
332
previous
->
right
=
current
->
right;
333
delete current;
334
}
335
}
336
}
337
current
=
next;
//
go to the next level (one level lower)
338
}
339
}
340
341
template
<
typename ElemType
>
342
bool
DeterminSkipList
<
ElemType
>
::IsValid()
const
343
{
344
SkipNode
<
ElemType
>
*
current,
*
temp,
*
temp2;
345
int
gap_size;
346
347
current
=
head;
348
while
(current
->
down
!=
bottom) {
349
temp
=
current;
350
while
(temp
!=
tail) {
351
temp2
=
temp
->
down;
352
gap_size
=
0
;
353
while
(temp2
->
key
!=
temp
->
key) {
354
gap_size
++
;
355
temp2
=
temp2
->
right;
356
}
357
if
(gap_size
<
1
||
gap_size
>
3
)
358
return
false
;
359
temp
=
temp
->
right;
360
}
361
current
=
current
->
down;
362
}
363
return
true
;
364
}
365
366
367
template
<
typename ElemType
>
368
void
DeterminSkipList
<
ElemType
>
::Print()
const
369
{
370
using
namespace
std;
371
SkipNode
<
ElemType
>
*
current,
*
temp;
372
373
current
=
head;
374
while
(current
!=
bottom) {
375
temp
=
current;
376
while
(temp
!=
NULL) {
377
if
(temp
!=
tail) {
378
cout
<<
temp
->
key
<<
"
(
"
379
<<
temp
->
down
->
key
<<
"
)
"
;
380
temp
=
temp
->
right;
381
}
else
{
382
cout
<<
temp
->
key
<<
"
[
"
383
<<
"
tail
"
<<
"
]
"
;
384
temp
=
NULL;
385
}
386
}
387
cout
<<
endl;
388
current
=
current
->
down;
389
}
390
cout
<<
endl;
391
}
392
393
394
}
//
end fo namespace skip_list
395
396
#endif
//
end of _DETERMIN_SKIP_LIST_H
//123 skip list 的测试文件
1
#include
<
iostream
>
2
#include
<
string
>
3
#include
<
fstream
>
4
5
#include
"
determin_skip_list.h
"
6
7
using
namespace
std;
8
using
namespace
skip_list;
9
10
/*
*
11
* TestSkipList is the kernal test fuction of Insert,Search and Remove of a
12
* determinstic skip list.
13
* @param skip_list is the user created empty skip list for test
14
* @param in is the ifstream relating to the opened file
15
* @param out is the ofstream relating to the file to write result
16
*/
17
template
<
typename T
>
18
void
TestSkipList(DeterminSkipList
<
T
>
&
skip_list, ifstream
&
in
, ofstream
&
out
)
19
{
20
string
op;
21
string
value;
22
///
loop to get input and to corresponding operation on skip_list
23
///
and write the result to the out put file
24
while
(
in
>>
op
>>
value) {
25
if
(op
==
"
INS
"
) {
26
if
(skip_list.Insert(value))
27
out
<<
op
<<
"
"
<<
value
<<
endl;
28
else
29
out
<<
"
DUP
"
<<
"
"
<<
value
<<
endl;
30
}
else
if
(op
==
"
FIND
"
) {
31
if
(skip_list.Search(value))
32
out
<<
op
<<
"
"
<<
value
<<
endl;
33
else
34
out
<<
"
NONE
"
<<
"
"
<<
value
<<
endl;
35
}
else
if
(op
==
"
REM
"
) {
36
if
(skip_list.Remove(value))
37
out
<<
op
<<
"
"
<<
value
<<
endl;
38
else
39
out
<<
"
NONE
"
<<
"
"
<<
value
<<
endl;
40
}
41
if
(
!
skip_list.IsValid())
42
cout
<<
"
not valid for
"
<<
op
<<
"
"
<<
value
<<
endl;
43
}
44
}
45
46
int
main(
int
argc,
char
*
argv[])
47
{
48
if
(argc
!=
3
) {
49
cout
<<
"
Usage is :
"
50
<<
"
test_determin_skip_list <input_file> <output_file>
"
51
<<
endl;
52
return
-
1
;
53
}
54
///
argv[1] the name of the file to open
55
///
argv[2] the name of the file to wirte
56
ifstream
in
(argv[
1
]);
57
if
(
!
in
) {
58
cout
<<
"
Could not find the file named
"
59
<<
argv[
1
]
<<
"
to open!
"
<<
endl;
60
return
-
1
;
61
}
62
ofstream
out
(argv[
2
]);
63
///
create a empty skip list key type is string,
64
///
assumming for any input key value
65
///
key value
< Max < Max_1
66
char a[2];
67
a[
0
]
=
char
(
254
); a[
1
]
=
'
/0
'
;
68
const
string
Max(a);
69
a[
0
]
=
char
(
255
);
70
const
string
Max_1(a);
71
DeterminSkipList
<
string
>
skip_list(Max, Max_1);
72
73
try
{
74
TestSkipList(skip_list,
in
,
out
);
///
The main test process
75
}
catch
(std::bad_alloc
&
) {
///
will exit if can not allocate more space
76
cout
<<
"
no more available memory
"
<<
endl;
77
in
.close();
78
out
.close();
79
return
-
1
;
80
}
81
82
in
.close();
83
out
.close();
84
return
0
;
85
}