Skip to content

Commit b2ddb52

Browse files
author
phishman3579
committed
Removed the need for a "previous" pointer in the Skip List's node.
git-svn-id: https://java-algorithms-implementation.googlecode.com/svn/trunk@425 032fbc0f-8cab-eb90-e552-f08422b9a96a
1 parent 4464deb commit b2ddb52

File tree

1 file changed

+77
-46
lines changed

1 file changed

+77
-46
lines changed

src/com/jwetherell/algorithms/data_structures/SkipList.java

+77-46
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class SkipList<T extends Comparable<T>> implements ISet<T> {
1717

1818
private static final Random seedGenerator = new Random();
1919

20-
// Defaults
20+
// If you change this number, you also need to change the random function.
2121
private static final int MAX = 31;
2222

2323
private int randomSeed = -1;
@@ -60,21 +60,23 @@ private Node<T> insertValue(T value) {
6060
// handle case where head is greater than new node, just swap values
6161
T oldHeadValue = head.value;
6262
head.value = value;
63+
// Swap the old head value into the new node
6364
node.value = oldHeadValue;
6465
}
66+
// Start from the top and work down to update the pointers
6567
for (int i=MAX; i>=0; i--) {
6668
Node<T> next = prev.getNext(i);
6769
while (next!=null) {
6870
if (next.value.compareTo(value)==1) break;
6971
prev = next;
72+
// It's important to set next since the node we are looking for
73+
// on the next level cannot be behind this "prev" node.
7074
next = prev.getNext(i);
7175
}
7276
if (i <= level) {
77+
// If we are on a level where the new node exists, update the linked list
7378
node.setNext(i, next);
74-
if (next!=null) next.setPrev(i, node);
75-
7679
prev.setNext(i, node);
77-
node.setPrev(i, prev);
7880
}
7981
}
8082
}
@@ -91,13 +93,13 @@ public boolean add(T value) {
9193
return (node!=null);
9294
}
9395

94-
private Node<T> findValue(T value) {
96+
private NodeLevelPair<T> findPredecessor(T value) {
9597
Node<T> node = head;
9698
if (node==null) return null;
97-
else if (node.value.equals(value)) return node;
99+
if (node.value.equals(value)) return null;
98100

99-
// Current node is not the node we are looking for. Keep moving down
100-
// until you find a node with a "next" node.
101+
// Current node is not the node we are looking for; Keep moving down
102+
// until you find a node with a non-null "next" pointer.
101103
int level = node.getLevel();
102104
Node<T> next = node.getNext(level);
103105
while (next==null) {
@@ -110,8 +112,9 @@ private Node<T> findValue(T value) {
110112
while (next!=null) {
111113
int comp = next.value.compareTo(value);
112114
if (comp==0) {
113-
// Found the node!
114-
return next;
115+
// Found the node who's next node is the node we are looking for!
116+
NodeLevelPair<T> pair = new NodeLevelPair<T>(level,node);
117+
return pair;
115118
} else if (comp==1) {
116119
// Found a node that's greater, move down a level
117120
if (level>0) level--;
@@ -120,7 +123,7 @@ private Node<T> findValue(T value) {
120123
// Update the next pointer
121124
next = node.getNext(level);
122125
} else {
123-
// Next is less then the value we are looking for, keep moving right.
126+
// Next is less then the value we are looking for, keep moving to next.
124127
node = next;
125128
next = node.getNext(level);
126129
while (next==null && level>0) {
@@ -131,30 +134,73 @@ private Node<T> findValue(T value) {
131134
return null;
132135
}
133136

137+
private Node<T> findValue(T value) {
138+
if (head==null) return null;
139+
if (head.value.compareTo(value)==0) return head;
140+
141+
NodeLevelPair<T> pair = findPredecessor(value);
142+
if (pair==null) return null;
143+
return pair.node.getNext(pair.level);
144+
}
145+
134146
private Node<T> removeValue(T value) {
135-
Node<T> node = findValue(value);
136-
if (node==null) return null;
137-
138-
Node<T> prev = node.getPrev(0);
139-
Node<T> next = node.getNext(0);
147+
Node<T> node = null;
148+
Node<T> prev = null;
149+
int lvl = 0;
150+
// Find the predecessor of the node we are looking for and
151+
// which level it is found on.
152+
NodeLevelPair<T> pair = findPredecessor(value);
153+
if (pair!=null) {
154+
prev = pair.node;
155+
lvl = pair.level;
156+
}
157+
158+
// Head node has no predecessor
159+
if (prev==null)
160+
node = head;
161+
else
162+
node = prev.getNext(lvl);
163+
164+
// Either head is null or node doesn't exist
165+
if (node == null)
166+
return null;
167+
168+
Node<T> next = null;
169+
// Head node is the only node without a prev node
140170
if (prev == null) {
171+
next = node.getNext(0);
141172
// Removing head
142173
if (next != null) {
174+
// Switch the value of the next into the head node
143175
node.value = next.value;
144176
next.value = value;
177+
// Update the prev and node pointer
178+
prev = node;
145179
node = next;
146180
} else {
181+
// If head doesn't have a new node then list is empty
147182
head = null;
148183
}
184+
} else {
185+
// Set the next node pointer
186+
next = node.getNext(lvl);
149187
}
188+
189+
// Start from the top level and move down removing the node
150190
int level = node.getLevel();
151191
for (int i=level; i>=0; i--) {
152-
prev = node.getPrev(i);
153192
next = node.getNext(i);
154-
if (prev != null)
193+
if (prev!=null) {
155194
prev.setNext(i, next);
156-
if (next != null)
157-
next.setPrev(i, prev);
195+
if (i > 0) {
196+
// Move down a level and look for the 'next' previous node
197+
Node<T> temp = prev.getNext(i - 1);
198+
while (temp != null && temp.value.compareTo(value) != 0) {
199+
prev = temp;
200+
temp = temp.getNext(i - 1);
201+
}
202+
}
203+
}
158204
}
159205
size--;
160206
return node;
@@ -204,10 +250,6 @@ public boolean validate() {
204250
}
205251
prev = node;
206252
node = node.getNext(i);
207-
if (node != null && !node.getPrev(i).value.equals(prev.value)) {
208-
System.err.println("prev!=next");
209-
return false;
210-
}
211253
}
212254
}
213255
return true;
@@ -267,18 +309,16 @@ public String toString() {
267309

268310
private static final class Node<T extends Comparable<T>> {
269311

270-
private Node<T>[] prev = null;
271312
private Node<T>[] next = null;
272313
private T value = null;
273314

274315
private Node(int level, T data) {
275-
this.prev = new Node[level+1];
276316
this.next = new Node[level+1];
277317
this.value = data;
278318
}
279319

280320
private int getLevel() {
281-
return prev.length-1;
321+
return next.length-1;
282322
}
283323

284324
private void setNext(int idx, Node<T> node) {
@@ -289,32 +329,14 @@ private Node<T> getNext(int idx) {
289329
return this.next[idx];
290330
}
291331

292-
private void setPrev(int idx, Node<T> node) {
293-
this.prev[idx] = node;
294-
}
295-
private Node<T> getPrev(int idx) {
296-
if (idx>=this.prev.length) return null;
297-
return this.prev[idx];
298-
}
299-
300332
/**
301333
* {@inheritDoc}
302334
*/
303335
@Override
304336
public String toString() {
305337
StringBuilder builder = new StringBuilder();
306338
builder.append("data=").append(value);
307-
int size = prev.length;
308-
if (prev!=null) {
309-
builder.append("\n").append("prev=[");
310-
for (int i=0; i<size; i++) {
311-
Node<T> n = prev[i];
312-
if (n!=null) builder.append(n.value);
313-
else builder.append("none");
314-
if (i!=size-1) builder.append("<-");
315-
}
316-
builder.append("]");
317-
}
339+
int size = next.length;
318340
if (next!=null) {
319341
builder.append("\n").append("next=[");
320342
for (int i=0; i<size; i++) {
@@ -329,6 +351,15 @@ public String toString() {
329351
}
330352
}
331353

354+
private static final class NodeLevelPair<T extends Comparable<T>> {
355+
private int level = -1;
356+
private Node<T> node = null;
357+
private NodeLevelPair(int level, Node<T> node) {
358+
this.level = level;
359+
this.node = node;
360+
}
361+
}
362+
332363
public static class JavaCompatibleSkipList<T extends Comparable<T>> extends java.util.AbstractSet<T> {
333364

334365
private SkipList<T> list = null;

0 commit comments

Comments
 (0)