太刺激了,面试官让我手写跳表,而我用两种实现方式吊打了TA!
然后,继续往下,走到了绿色的6这里,再往后按链表的方式删除元素,这个大家都会了: OK,给出删除元素的代码(查看完整代码,关注公众号彤哥读源码回复skiplist领取): /** * 删除元素 * @param value */ public void delete(T value) { System.out.println("删除元素:u6b22u8fceu5173u6ce8u516cu4f17u53f7u5f64u54e5u8bfbu6e90u7801uff0cu83b7u53d6u66f4u591au67b6u6784u3001u57fau7840u3001u6e90u7801u597du6587uff01"); if (value == null) { throw new NullPointerException(); } Index q = this.head; Index r, d; Comparator cmp = this.comparator; Node preIndexNode; // 第一步:寻找元素 for(;;) { r = q.right; if (r != null) { // 包含value的索引,正好有 if (cmp.compare(r.node.value, value) == 0) { // 纠正:顺便修正向右的索引 q.right = r.right; } // 如果右边的节点比value小,则右移 if (cmp.compare(r.node.value, value) < 0) { q = r; continue; } } d = q.down; // 如果下面的索引为空了,则返回该节点 if (d == null) { preIndexNode = q.node; break; } // 否则,下移 q = d; } // 第二步:从链表中删除 Node p = preIndexNode; Node n; int c; for (;;) { n = p.next; if (n == null) { return; } c = cmp.compare(n.value, value); if (c == 0) { // 找到了 p.next = n.next; return; } if (c > 0) { // 没找到 return; } // 后移 p = n; } } OK,到这里,跳表的通用实现就完事了,其实,你也可以发现,这里还是有一些可以优化的点的,比如right和next指针为什么不能合二为一呢?向下的指针能不能跟指向Node的指针合并呢? 关注公众号彤哥读源码,回复“skiplist”领取本节完整源码,包含测试代码。 为了尝试解决这些问题,彤哥又自己研究了一种实现,这种实现不再区分头索引节点、索引节点、普通节点,把它们全部合并成一个,大家都是一样的,并且,我将它运用到了HashMap的改造中,来看看吧。 彤哥独家实现 (编辑:应用网_阳江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |