数据结构-跳表(基于JAVA的实现)

跳表是一种可进行二分查找的有序链表,通过多级索引加速查询,常用于并发环境。在Java中,ConcurrentSkipListMap和ConcurrentSkipListSet实现了跳表,提供线程安全的高效操作。相比红黑树,跳表在并发更新时锁的代价较小,Redis等场景中也有应用。
摘要由CSDN通过智能技术生成

跳表的原理与特点

跳表实质就是一种可以进行二分查找的有序链表,跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。解决了链表查询慢的问题,但会占有更多的内存,是一种以空间换内存的数据结构。

查询任意数据的时间复杂度O(logn)
插入数据的时间复杂度O(logn)
空间复杂度:O(n)

跳表的数据结构

跳跃表应用场景分析

在Server端,对并发和性能有要求的情况下,如何选择合适的数据结构(跳表和红黑树)?
如果单纯比较性能,跳跃表和红黑树可以说相差不大,但是加上并发的环境就不一样了,如果要更新数据,跳表需要更新的部分就比较少,锁的东西也就比较少,所以不同线程争锁的代价就相对少了。而红黑树有个平衡的过程,牵涉到大量的节点,争锁的代价也就相对较高了。性能也就不如前者了。

在并发环境下Skip List有另外一个优势,红黑树在插入和删除的时候可能需要做一些rebalance的操作,这样的操作可能会涉及到整个树的其他部分,而Skip List的操作显然更加局部性一些,锁需要盯住的节点更少,因此在这样的情况下性能好一些。

在Redis中,有序集数据类型(Sorted Set)也是用跳表实现的。
Redis作者描述的使用跳表的原因:

1、跳表的一个缺点是耗内存(因为要重复分层存节点),但是作者也说了,可以调参数来降低内存消耗,和那些平衡树结构达到差不多。
2、redis经查有范围操作,这样利用跳表里面的双向链表,可以方便地操作。另外还有缓存区域化(cache locality)不会比平衡树差。
3、实现简单。zrank操作能够到O(log(N))。

跳跃表的JAVA应用

在Java的API中已经有了实现:

  1. ConcurrentSkipListMap. 在功能上对应HashTable、HashMap、TreeMap。
  2. ConcurrentSkipListSet . 在功能上对应HashSet.
    确切来说,Skip List更像Java中的TreeMap。TreeMap基于红黑树(一种自平衡二叉查找树)实现的,时间复杂度平均能达到O(log n),TreeMap输出是有序的,ConcurrentSkipListMap和ConcurrentSkipListSet 输出也是有序的(本博测试过)。下例的输出是从小到大,有序的。

使用样例

import java.util.*;
import java.util.concurrent.*;
/*
 * 跳表(SkipList)这种数据结构算是以前比较少听说过,它所实现的功能与红黑树,AVL树都差不太多,说白了就是一种基于排序的索引结构,
 * 它的统计效率与红黑树差不多,但是它的原理,实现难度以及编程难度要比红黑树简单。 
 * 另外它还有一个平衡的树形索引机构没有的好处,这也是引导自己了解跳表这种数据结构的原因,就是在并发环境下其表现很好. 
 * 这里可以想象,在没有了解SkipList这种数据结构之前,如果要在并发环境下构造基于排序的索引结构,那么也就红黑树是一种比较好的选择了,
 * 但是它的平衡操作要求对整个树形结构的锁定,因此在并发环境下性能和伸缩性并不好.
 * 在Java中,skiplist提供了两种:
 * ConcurrentSkipListMap 和 ConcurrentSkipListSet 
 * 两者都是按自然排序输出。
 */
public class SkipListDemo {
   	
	public static void skipListMapShow(){
   
	Map<Integer,String> map= new ConcurrentSkipListMap<>();
	map.put(1, "1");
	map.put(23, "23");
	map.put(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值