3
public static final int MAX_LEVEL = 4;5
private final int levels;7
private SkipListEntry head;9
private SkipListEntry tail;15
public Skiplist(int levels) {18
// init new SkipList with defined level19
// Firstly, create the root level (level = 0) entry for left (min) and right (max)21
// LEFT <------------------------------------------------> RIGHT22
SkipListEntry left = new SkipListEntry(Integer.MIN_VALUE, Integer.MIN_VALUE);23
SkipListEntry right = new SkipListEntry(Integer.MAX_VALUE, Integer.MAX_VALUE);27
// After, we can define left and right as the head and tail nodes28
// HEAD = LEFT <------------------------------------------------> RIGHT = TAIL32
// Next, we can define left and right nodes for other levels and linked it33
// 0 HEAD = LEFT <------------------------------------------------> RIGHT = TAIL37
// 1 HEAD = LEFT <------------------------------------------------> RIGHT = TAIL41
// 2 HEAD = LEFT <------------------------------------------------> RIGHT = TAIL45
// 3 HEAD = LEFT <------------------------------------------------> RIGHT = TAIL49
// N HEAD = LEFT <------------------------------------------------> RIGHT = TAIL50
for (int i = 1; i < this.levels; i++) {51
left.down = new SkipListEntry(Integer.MIN_VALUE, Integer.MIN_VALUE, null, null, left, null);54
right.down = new SkipListEntry(Integer.MAX_VALUE, Integer.MAX_VALUE, null, null, right, null);62
public boolean search(int target) {63
return this.find(target).key == target;66
public void add(int num) {67
// We have to always start from head68
SkipListEntry current = this.head;70
// For the searching newNode we have to:71
// 1 - start from the head72
// 2 - go down the bottom level73
while (current.hasDown()) {74
current = current.down;77
// 3 - try to find newNode78
while (current.hasRight() && num > current.right.key) {79
current = current.right;82
// 4 - if we found newNode on the step 3, we have to do nothing (return;)83
if (num == current.key) {87
// 5 - otherwise, we have to a put new newNode on the right88
SkipListEntry newNode = new SkipListEntry(num, num, current, current.right);89
current.right.left = newNode;90
current.right = newNode;92
// 6 - have to go up one level94
// 8 - if on the step 8 true - repeat step 595
for (int level = this.levels - 2; level >= 0; level--) {96
if (!this.coinFlip(level)) {100
// go up one level and find left node for new level101
while (!current.hasUp() && current.hasLeft()) {102
current = current.left;104
current = current.up;106
newNode.up = new SkipListEntry(num, num, current, current.right, null, newNode);107
newNode = newNode.up;109
current.right.left = newNode;110
current.right = newNode;114
public boolean erase(int num) {115
SkipListEntry entry = this.find(num);116
if (entry.key != num) {120
entry.left.right = entry.right;121
entry.right.left = entry.left;123
while ((entry = entry.up) != null) {124
entry.left.right = entry.right;125
entry.right.left = entry.left;131
private SkipListEntry find(int key) {132
// We have to always start from head133
SkipListEntry current = this.head;135
// while node has right or down we can go down a level or right136
// 1 - we have to go right and try to find element137
// 2 - if element is not presented at this level, we have to go down a level139
// 3 - if we found element we have to go down to the bottom140
// if we found element we have to return it, otherwise - return last visited141
while (current != null && current.hasRight()) {142
while (current.hasRight() && key > current.right.key) {143
current = current.right;146
if (key == current.right.key) {147
current = current.right;148
while (current.hasDown()) {149
current = current.down;155
current = current.down;161
private boolean coinFlip(int level) {162
return ThreadLocalRandom.current().nextInt(this.levels - level) == 0;165
public static class SkipListEntry {167
private final int key;169
private final int value;171
private SkipListEntry up;173
private SkipListEntry down;175
private SkipListEntry left;177
private SkipListEntry right;179
public SkipListEntry(int key, int value) {180
this(key, value, null, null, null, null);183
public SkipListEntry(int key, int value, SkipListEntry left, SkipListEntry right) {184
this(key, value, left, right, null, null);187
public SkipListEntry(193
SkipListEntry down) {202
public int getKey() {206
public int getValue() {210
public SkipListEntry left() {211
if (!this.hasLeft()) {218
public void setLeft(SkipListEntry entry) {219
this.left = Objects.requireNonNull(entry);222
public SkipListEntry right() {223
if (!this.hasRight()) {230
public void setRight(SkipListEntry entry) {231
this.right = Objects.requireNonNull(entry);234
public SkipListEntry up() {242
public void setUp(SkipListEntry entry) {243
this.up = Objects.requireNonNull(entry);246
public SkipListEntry getDown() {250
public SkipListEntry down() {251
if (!this.hasDown()) {258
public void setDown(SkipListEntry entry) {259
this.down = Objects.requireNonNull(entry);262
public boolean hasLeft() {263
return this.left != null;266
public boolean hasRight() {267
return this.right != null;270
public boolean hasUp() {271
return this.up != null;274
public boolean hasDown() {275
return this.down != null;