diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SkipList.java b/src/main/java/com/thealgorithms/datastructures/lists/SkipList.java new file mode 100644 index 000000000..5cd14f9dd --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/lists/SkipList.java @@ -0,0 +1,324 @@ +package com.thealgorithms.datastructures.lists; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Skip list is a data structure that allows {@code O(log n)} search complexity + * as well as {@code O(log n)} insertion complexity within an ordered sequence + * of {@code n} elements. Thus it can get the best features of a sorted array + * (for searching) while maintaining a linked list-like structure that allows + * insertion, which is not possible with a static array. + *
+ * A skip list is built in layers. The bottom layer is an ordinary ordered + * linked list. Each higher layer acts as an "express lane" for the lists + * below. + *
+ * [ ] ------> [ ] --> [ ] + * [ ] --> [ ] [ ] --> [ ] + * [ ] [ ] [ ] [ ] [ ] [ ] + * H 0 1 2 3 4 + *+ * + * @param
+ * [ ] --- --- [ ] --- [ ] + * [ ] --- [ ] [ ] --- [ ] + * [ ] [ ] [ ] [ ] [ ] [ ] + * H 0 1 2 3 4 + *+ * Values of nodes is not presented. + * + * @return string representation + */ + @Override + public String toString() { + List
P = pi(1 - p)
+ *
+ * Maximum height that would give the best search complexity
+ * calculated by log1/pn
+ * where {@code n} is an expected count of elements in list.
+ */
+ public static class BernoulliHeightStrategy implements HeightStrategy {
+
+ private final double probability;
+
+ private static final double DEFAULT_PROBABILITY = 0.5;
+ private static final Random RANDOM = new Random();
+
+ public BernoulliHeightStrategy() {
+ this.probability = DEFAULT_PROBABILITY;
+ }
+
+ public BernoulliHeightStrategy(double probability) {
+ if (probability <= 0 || probability >= 1) {
+ throw new IllegalArgumentException("Probability should be from 0 to 1. But was: " + probability);
+ }
+ this.probability = probability;
+ }
+
+ @Override
+ public int height(int expectedSize) {
+ long height = Math.round(Math.log10(expectedSize) / Math.log10(1 / probability));
+ if (height > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+ return (int) height;
+ }
+
+ @Override
+ public int nodeHeight(int heightCap) {
+ int level = 0;
+ double border = 100 * (1 - probability);
+ while (((RANDOM.nextInt(Integer.MAX_VALUE) % 100) + 1) > border) {
+ if (level + 1 >= heightCap) {
+ return level;
+ }
+ level++;
+ }
+ return level;
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java
new file mode 100644
index 000000000..b26de0c55
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java
@@ -0,0 +1,85 @@
+package com.thealgorithms.datastructures.lists;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SkipListTest {
+
+ @Test
+ void add() {
+ SkipList