[BAEL-7557] SkipList-implementation-in-Java (#16253)
This commit is contained in:
parent
24a53b3d65
commit
2df107ef2b
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.algorithms.skiplist;
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
int value;
|
||||||
|
Node[] forward; // array to hold references to different levels
|
||||||
|
|
||||||
|
public Node(int value, int level) {
|
||||||
|
this.value = value;
|
||||||
|
this.forward = new Node[level + 1]; // level + 1 because level is 0-based
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package com.baeldung.algorithms.skiplist;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class SkipList {
|
||||||
|
private Node head;
|
||||||
|
private int maxLevel;
|
||||||
|
private int level;
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
public SkipList() {
|
||||||
|
maxLevel = 16; // maximum number of levels
|
||||||
|
level = 0; // current level of SkipList
|
||||||
|
head = new Node(Integer.MIN_VALUE, maxLevel);
|
||||||
|
random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(int value) {
|
||||||
|
Node[] update = new Node[maxLevel + 1];
|
||||||
|
Node current = this.head;
|
||||||
|
|
||||||
|
for (int i = level; i >= 0; i--) {
|
||||||
|
while (current.forward[i] != null && current.forward[i].value < value) {
|
||||||
|
current = current.forward[i];
|
||||||
|
}
|
||||||
|
update[i] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.forward[0];
|
||||||
|
|
||||||
|
if (current == null || current.value != value) {
|
||||||
|
int lvl = randomLevel();
|
||||||
|
|
||||||
|
if (lvl > level) {
|
||||||
|
for (int i = level + 1; i <= lvl; i++) {
|
||||||
|
update[i] = head;
|
||||||
|
}
|
||||||
|
level = lvl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node newNode = new Node(value, lvl);
|
||||||
|
for (int i = 0; i <= lvl; i++) {
|
||||||
|
newNode.forward[i] = update[i].forward[i];
|
||||||
|
update[i].forward[i] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean search(int value) {
|
||||||
|
Node current = this.head;
|
||||||
|
for (int i = level; i >= 0; i--) {
|
||||||
|
while (current.forward[i] != null && current.forward[i].value < value) {
|
||||||
|
current = current.forward[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = current.forward[0];
|
||||||
|
return current != null && current.value == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(int value) {
|
||||||
|
Node[] update = new Node[maxLevel + 1];
|
||||||
|
Node current = this.head;
|
||||||
|
|
||||||
|
for (int i = level; i >= 0; i--) {
|
||||||
|
while (current.forward[i] != null && current.forward[i].value < value) {
|
||||||
|
current = current.forward[i];
|
||||||
|
}
|
||||||
|
update[i] = current;
|
||||||
|
}
|
||||||
|
current = current.forward[0];
|
||||||
|
|
||||||
|
if (current != null && current.value == value) {
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
if (update[i].forward[i] != current) break;
|
||||||
|
update[i].forward[i] = current.forward[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (level > 0 && head.forward[level] == null) {
|
||||||
|
level--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int randomLevel() {
|
||||||
|
int lvl = 0;
|
||||||
|
while (lvl < maxLevel && random.nextDouble() < 0.5) {
|
||||||
|
lvl++;
|
||||||
|
}
|
||||||
|
return lvl;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.baeldung.algorithms.skiplist;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class SkipListUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSkipList_WhenInsert_ThenSearchFound() {
|
||||||
|
SkipList skipList = new SkipList();
|
||||||
|
|
||||||
|
skipList.insert(3);
|
||||||
|
assertTrue(skipList.search(3), "Should find 3");
|
||||||
|
|
||||||
|
assertFalse(skipList.search(99), "Should not find 99");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSkipList_WhenDeleteElement_ThenRemoveFromList() {
|
||||||
|
SkipList skipList = new SkipList();
|
||||||
|
|
||||||
|
skipList.insert(3);
|
||||||
|
skipList.insert(7);
|
||||||
|
|
||||||
|
skipList.delete(3);
|
||||||
|
assertFalse(skipList.search(3), "3 should have been deleted");
|
||||||
|
|
||||||
|
skipList.delete(99);
|
||||||
|
assertTrue(skipList.search(7), "7 should still exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user