import java.util.Random; public class SkipList> { //表示跳表的高度,包括原始链表这一层 private static final int MAX_LEVEL = 16;//跳表的高度是16 //内部类Node private class Node >{ E data;//结点数据 Node[] nextNodes; //记录当前节点维护的索引节点的最大高度 int maxIndexLevel = 0; Node(E data) { this.data = data; nextNodes = new Node[MAX_LEVEL];//跳表的高度是16 } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("{ data: "); builder.append(data); builder.append("; levels: "); builder.append(maxIndexLevel); builder.append(" }"); return builder.toString(); } } // 表示当前跳表最大的高度 (包含了原始链表层,所以默认初始值是 1) private int levelCount; // 虚拟头结点 private Node dummyHead; private Random random = new Random(); //跳表初始化 public SkipList() { this.levelCount = 1; this.dummyHead = new Node(-1); } public boolean contains(E e){ return get(e) != null; } //查询操作 //log(n) public Node get(E e){ Node curr = dummyHead; //从最高一层 往下 一层一层 的寻找元素所在的区间 for(int i = levelCount - 1 ; i >= 0 ; i--){ //同层比较(i 层) //只要下一个结点值 比 待查找的元素小,一直往右前进 while(curr.nextNodes[i] != null && curr.nextNodes[i].data.compareTo(e) < 0){ curr = curr.nextNodes[i]; } } //到最底层了:比较e结点 和 下一个结点大小关系 if(curr.nextNodes[0] != null && curr.nextNodes[0].data.compareTo(e) == 0){ return curr.nextNodes[0]; } //没找到结点 return null; } //插入操作 public void add(E e){ //维护一层索引 int level = dummyHead.nextNodes[0] == null ? 1 : randomLevel(); Node[] prevNodes = new Node[level]; for(int i = 0 ; i < level ; i++){ prevNodes[i] = dummyHead; } //1.找到要插入节点的前面一个节点 Node prev = dummyHead; for(int i = levelCount - 1 ; i >= 0 ; i--){ while(prev.nextNodes[i] != null && prev.nextNodes[i].data.compareTo(e) < 0){ prev = prev.nextNodes[i]; } if(i < level) prevNodes[i] = prev; } Node newNode = new Node(e); //2.将节点插入到节点prev的后面 for(int i = 0 ; i < level ; i++){ newNode.nextNodes[i] = prevNodes[i].nextNodes[i]; prevNodes[i].nextNodes[i] = newNode; } //维护最大高度 if(levelCount < level){ levelCount = level; } } //随机给出维护高度 private int randomLevel() { int level = 1; for (int i = 1; i < MAX_LEVEL; i++) { if (random.nextInt() % 2 == 1) { level++; } } return level; } public void remove(E e) { // 1. 找到需要删除节点的前一个节点,以及删除节点对应的索引节点的前一个索引节点 Node [] prevNodes = new Node[levelCount]; Node prev = dummyHead; for (int i = levelCount - 1; i >= 0; i--) { while (prev.nextNodes[i] != null && prev.nextNodes[i].data.compareTo(e) < 0) { prev = prev.nextNodes[i]; } prevNodes[i] = prev; } // 2. 对每一层进行删除节点 // 先判断节点是否存在,存在的话才执行删除 if (prev.nextNodes[0] != null && prev.nextNodes[0].data.compareTo(e) == 0) { // 对每一层进行删除节点 for (int i = levelCount - 1; i > 0; i--) { Node delNode = prevNodes[i].nextNodes[i]; if (delNode != null && delNode.data.compareTo(e) == 0) { prevNodes[i].nextNodes[i] = delNode.nextNodes[i]; delNode.nextNodes[i] = null; } } } } }



