hbase---跳跃表(skiplist)

跳跃表(SkipList)是一种能高效实现插入、删除、查找的内存数据结构,这些操作的期望复杂度都是O(logN)。与红黑树以及其他的二分查找树相比,跳跃表的优势在于实现简单,而且在并发场景下加锁粒度更小,从而可以实现更高的并发性。正因为这些优点,跳跃表广泛使用于KV数据库中,诸如Redis、LevelDB、HBase都把跳跃表作为一种维护有序数据集合的基础数据结构。

众所周知,链表这种数据结构的查询复杂度为O(N),这里N是链表中元素的个数。在已经找到要删除元素的情况下,再执行链表的删除操作其实非常高效,只需把待删除元素前一个元素的next指针指向待删除元素的后一个元素即可,复杂度为O(1),但问题是,链表的查询复杂度太高,因为链表在查询的时候,需要逐个元素地查找。如果链表在查找的时候,能够避免依次查找元素,那么查找复杂度将降低。而跳跃表就是利用这一思想,在链表之上额外存储了一些节点的索引信息,达到避免依次查找元素的目的,从而将查询复杂度优化为O(logN)。将查询复杂度优化之后,自然也优化了插入和删除的复杂度。

1.定义

如图所示,跳跃表的定义如下:

·跳跃表由多条分层的链表组成(设为S0,S1,S2,...,Sn),例如图中有6条链表。

·每条链表中的元素都是有序的。

·每条链表都有两个元素:+∞(正无穷大)和-∞(负无穷大),分别表示链表的头部和尾部。

·从上到下,上层链表元素集合是下层链表元素集合的子集,即S1是S0的子集,S2是S1的子集。

·跳跃表的高度定义为水平链表的层数。

在跳跃表中查找一个指定元素的流程比较简单。上图以左上角元素(设为currentNode)作为起点查询值5:

·如果发现currentNode后继节点的值小于等于待查询值,则沿着这条链表向后查询,否则,切换到当前节点的下一层链表。

·继续查询,直到找到待查询值为止(或者currentNode为空节点)为止。

2.插入

跳跃表的插入算法要复杂一点。如下图所示。首先,需要按照上述查找流程找到待插入元素的前驱和后继;然后,按照如下随机算法生成一个高度值:

// p是一个(0,1)之间的常数,一般取p=1/4或者1/2

public void randomHeight(double p){

    int height = 0 ;

    while(random.nextDouble() < p) height ++ ;

    return height + 1;

}

最后,将待插入节点按照高度值生成一个垂直节点(这个节点的层数正好等于高度值),之后插入到跳跃表的多条链表中去。假设height=randomHeight(p),这里需要分两种情况讨论:

·如果height大于跳跃表的高度,那么跳跃表的高度被提升为height,同时需要更新头部节点和尾部节点的指针指向。

·如果height小于等于跳跃表的高度,那么需要更新待插入元素前驱和后继的指针指向。

4.删除

删除操作和插入操作有点类似,不再细说。

5.复杂度分析

这里,我们一起来评估跳跃表的时间和空间复杂度。

性质1 一个节点落在第k层的概率为P^(k-1)。

这条性质比较简单,如果randomHeight(p)函数返回的高度为k,那么必须要求前面(k-1)个随机数都小于p,(k-1)个概率为p的独立事件概率相乘,因此高度为k的概率为P^(k-1)。性质2 一个最底层链表有n个元素的跳跃表,总共元素个数为:

其中k为跳跃表的高度。

由于性质1,一个元素落在第k层概率为p^(k-1),则第k层插入的元素个数为n×p^(k-1),所有k相加得到上述公式。当p <= 1/2时,上述公式小于O(2n),所以空间复杂度为O(n)。

性质3 跳跃表的高度为O(logn)。

考虑第层,落在这层的期望节点数为

当n较大时,该层节点数为0,所以层数在O(logn)这个数据级上。

 

性质4 跳跃表的查询时间复杂度为O(logN)。

查询时间复杂度关键取决于从最左上角到达最底层走过的横向步数和纵向步数之和。我们反过来考虑这个过程,也就是从最底层达到最左上角s走过的期望步数(包括横向步数)。对第k层第j列节点来说,它只可能从以下两种情况跳过来:

·第k-1层第j列节点往上走,跳到第k层第j列节点。根据randomHeight(p)函数定义,往上走的概率为p。

·第k层第j+1列节点往左走,跳到第k层第j列节点。这种情况,第k层第j+1列节点已经是垂直节点的最高点,也就是说,这个节点已经不能往上走,只能往左走。根据randomHeight(p)函数定义,往左走的概率为(1-p)。

设Ck为往上跳k层的期望步数(包括纵向步数和横向步数),那么有:

由于高度k为O(logN)级别,所以,查询走过的期望步数也为O(logN)。

性质5 跳跃表的插入/删除时间复杂度为O(logN)。

由插入/删除的实现可以看出,插入/删除的时间复杂度和查询时间复杂度相等,故性质5成立。

因此,跳跃表的查找、删除、插入的复杂度都是O(logN)。

 

### 回答1: HBase-Java API 是一种用于管理 HBase 表的编程接口。使用 HBase-Java API,开发人员可以编写 Java 代码来创建、删除、修改和查询 HBase 表。HBase-Java API 提供了一系列类和方法,可以让开发人员轻松地与 HBase 表进行交互。例如,可以使用 HBaseAdmin 类来管理 HBase 表,使用 HTable 类来访问 HBase 表中的数据,使用 Put 类来插入数据,使用 Get 类来获取数据,等等。总之,HBase-Java API 是 HBase 的重要组成部分,它为开发人员提供了强大的工具来管理和操作 HBase 表。 ### 回答2: HBase是一个分布式的列式存储数据库,在很多大数据应用中得到广泛的使用。它采用Hadoop作为其底层基础框架,同时提供了Java API供开发人员使用。HBase的Java API为开发人员提供了一个管理表的接口,使得开发人员可以对HBase数据库中的表进行创建、读取、修改和删除等基本操作。 首先,我们需要用Java API创建一个HBase数据库中的表。使用HBase的Java API创建表的流程如下: 1. 首先需要获取HBase Configuration对象,并设置HBase连接参数以连接HBase数据库。 2. 接下来,需要获取HBase Admin对象,以便在操作HBase数据库表之前检查表是否存在,如果表不存在,需要创建该表。 3. 通过HBase的Java API创建表时,需要指定表的表名、列族的名称以及版本数等属性。 4. 创建表时需要考虑表的region的分配问题,可以对表的region进行手动或自动分片,以此来控制HBase的负载均衡。 创建了HBase数据库中的表之后,我们可以使用Java API对表进行读写操作。在进行读写操作时,需要使用HBase的Java API提供的Get的方法来获取表中的数据、Scan方法来扫描整个表、以及Put方法来向表中插入数据。此外,在进行表操作时还需要设置一些常见的数据操作参数,例如版本数、时间戳等。 在使用HBase的Java API时,还需要注意一些性能优化的问题,例如何时启用缓存、何时触发分区策略以及如何优化HBase表的大小等。这些优化措施能够在HBase的性能以及数据读写时的延迟方面提供很好的支持和帮助。 总的来说,HBase的Java API提供的表管理接口为开发人员提供了非常方便和快捷的方式来操作HBase数据库中的表。通过使用这些API,开发人员可以创建、读取、修改和删除表的数据,并且能够充分应用HBase的分布式特性来优化数据管理和性能提升。 ### 回答3: HBase是一个开源、分布式、非关系型数据库,它可以存储和处理大规模结构化、半结构化和非结构化数据。HBase Java API是HBase的官方API,它提供了对HBase表的管理和操作功能,让开发人员可以通过Java代码轻松地连接到HBase数据库。 在使用HBase Java API管理表时,首先需要创建一个HBaseConfiguration对象,它包含了连接HBase数据库所需的配置信息,如Zookeeper地址、HBase根目录等。然后,可以使用HBaseAdmin类创建、删除、修改表,以及列族等操作。例如,创建一个表可以通过以下代码实现: ``` HBaseAdmin admin = new HBaseAdmin(HBaseConfiguration.create()); HTableDescriptor tableDescriptor = new HTableDescriptor("table_name"); HColumnDescriptor columnDescriptor = new HColumnDescriptor("column_family"); tableDescriptor.addFamily(columnDescriptor); admin.createTable(tableDescriptor); ``` 创建表时,需要先通过HTableDescriptor类定义表名称,然后通过HColumnDescriptor类定义列族名称。可以通过addFamily()方法将列族添加到表描述中,最后通过HBaseAdmin的createTable()方法创建表。 除了创建表之外,HBase Java API还提供了许多其他的操作,如获取表信息、获取所有表的列表、删除表等。同时,HBase Java API还提供了对数据的CRUD操作,包括put、get、scan、delete等方法,让开发人员可以方便地进行数据操作。 总之,HBase Java API是一个非常强大的工具,它可以使开发人员轻松地管理HBase数据库,并实现数据的高效存储和处理。但是,在使用HBase Java API时,需要了解HBase的基本知识和API的用法,才能更好地发挥其功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值