Skip to content

Commit e2cf889

Browse files
committed
Update skip_list implementation with linked list approach
1 parent cb2e0ac commit e2cf889

1 file changed

Lines changed: 82 additions & 20 deletions

File tree

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
import math
22

33

4+
class Node:
5+
def __init__(self, value, next=None):
6+
self.value = value
7+
self.next = next
8+
9+
410
class SkipList:
511
def __init__(self):
6-
self.data = [] # sorted list
12+
self.head = None
13+
self.length = 0
714
self.skips = [] # list of skip pointers, each is a tuple (index, value)
815

16+
def _get_node(self, index):
17+
"""Get the node at the given index."""
18+
current = self.head
19+
for _ in range(index):
20+
if current is None:
21+
return None
22+
current = current.next
23+
return current
24+
925
def rebuild_skips(self):
1026
"""Rebuild the skip pointer so we can jump over sqrt(n) elements."""
11-
n = len(self.data)
27+
n = self.length
1228
if n == 0:
1329
self.skips = []
1430
return
@@ -18,49 +34,95 @@ def rebuild_skips(self):
1834

1935
def _find_position(self, value):
2036
"""Find the position to insert value using skip pointers."""
21-
if not self.data:
37+
if self.length == 0:
2238
return 0
2339

2440
# Use skip pointers to find the range where value should be
2541
for i in range(len(self.skips) - 1):
2642
a = self.skips[i]
2743
b = self.skips[i + 1]
28-
if self.data[a] <= value < self.data[b]:
44+
45+
node_a = self._get_node(a)
46+
node_b = self._get_node(b)
47+
48+
if node_a.value <= value < node_b.value:
2949
# linear search between a and b
30-
for j in range(a, b):
31-
if self.data[j] >= value:
32-
return j
50+
idx = a
51+
current = node_a
52+
while idx < b and current:
53+
if current.value >= value:
54+
return idx
55+
current = current.next
56+
idx += 1
3357
return b
34-
3558
# Check the last skip pointer
3659
start = self.skips[-1]
37-
for j in range(start, len(self.data)):
38-
if self.data[j] >= value:
39-
return j
40-
return len(self.data)
60+
idx = start
61+
current = self._get_node(start)
62+
while current:
63+
if current.value >= value:
64+
return idx
65+
current = current.next
66+
idx += 1
67+
return self.length
4168

4269
def insert(self, value):
4370
"""Insert value into the skip list, maintaining sorted order."""
4471
pos = self._find_position(value)
4572

46-
if pos < len(self.data) and self.data[pos] == value:
47-
return # value already exists, do not insert duplicates
48-
self.data.insert(pos, value)
73+
if pos < self.length:
74+
node_at_pos = self._get_node(pos)
75+
if node_at_pos and node_at_pos.value == value:
76+
return # value already exists, do not insert duplicates
77+
# Insert the new node
78+
new_node = Node(value)
79+
if pos == 0:
80+
new_node.next = self.head
81+
self.head = new_node
82+
else:
83+
prev_node = self._get_node(pos - 1)
84+
new_node.next = prev_node.next
85+
prev_node.next = new_node
86+
self.length += 1
4987
self.rebuild_skips()
5088

5189
def __contains__(self, value):
52-
if not self.data:
90+
if self.length == 0:
5391
return False
5492

5593
for i in range(len(self.skips) - 1):
5694
a = self.skips[i]
5795
b = self.skips[i + 1]
58-
if self.data[a] <= value < self.data[b]:
59-
return value in self.data[a:b]
6096

97+
node_a = self._get_node(a)
98+
node_b = self._get_node(b)
99+
100+
if node_a.value <= value < node_b.value:
101+
idx = a
102+
current = node_a
103+
while idx < b and current:
104+
if current.value == value:
105+
return True
106+
current = current.next
107+
idx += 1
108+
return False
61109
start = self.skips[-1]
62-
return value in self.data[start::]
110+
idx = start
111+
current = self._get_node(start)
112+
113+
while current:
114+
if current.value == value:
115+
return True
116+
current = current.next
117+
idx += 1
118+
119+
return False
63120

64121
def to_list(self):
65122
"""Return the skip list as a regular sorted list."""
66-
return self.data
123+
result = []
124+
current = self.head
125+
while current:
126+
result.append(current.value)
127+
current = current.next
128+
return result

0 commit comments

Comments
 (0)