之前一直不太懂,为什么跳表的平均时间复杂度为O(logN)
但是后来看了下
http://blog.xiaoheshang.info/?p=248 算是理解了一些,再结合自己的思考,记录一下
首先,需要理解刚才那篇文章中的 "如果每2^i个节点都指向前面2^i个节点,寻找一个节点的复杂度变成logn(类似于二分查找)", 这个应该没什么问题
那么问题来了,为什么随机的层数也能保证logN的复杂度?
原因就在于,这里说的随机,并不是完全的随机一个层数出来,而是通过随机的算法,算出一个并不随机的层数来
以redis中的随机层数的算法来看
int zslRandomLevel(void) {
int level = 1;
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
这里假设 ZSKIPLIST_P 为2 (实际为4,便于理解设置为2),这段代码我们可以理解为,落到层数为i + 1的概率为0.5^i
而反过来理解,每两个节点出现层数为2的期望就是1,每4个节点出现第三层的期望也为1,每8个节点出现第四层(0.5^3)的期望为1 (期望值 = 单个概率 * 数量)
正是基于此,如果我们的数据量越大,越是可以接近期望的值,所以,我们可以认为,我们实现了 "如果每2^i个节点都指向前面2^i个节点"的效果,也就是说,查找的平均复杂度为O(logN)
分享到:
相关推荐
Redis选择使用跳表而不是红黑树实现有序集合的原因在于跳表的实现相对简单,理解和调试更容易。同时,跳表的查找、插入和删除操作在平均情况下与红黑树相当,但在最坏情况下,红黑树的操作时间复杂度仍为O(log n),...
Redis跳表是一种基于有序链表的数据结构,它通过添加多级索引来加速查找。跳表的每一层都是原始数据的一个子集,级别越高的索引包含的元素越少。查找时,从最高级别开始,逐步向下查找直至找到目标元素。跳表的查找...
- 跳表和红黑树在查找、插入和删除操作上的时间复杂度都是O(log N),但在实际操作中,由于跳表的分层结构,其平均查找效率可能会更高。 - 跳表的实现相对简单,易于理解和调试,而红黑树的平衡过程相对复杂,可能...
4. 哈希表:Redis使用哈希表作为主要的数据结构,用于存储键值对,提供O(1)的时间复杂度进行查找。每个键值对由一个dictEntry结构表示,包含指向键和值的指针。Redis的数据库由多个哈希表组成,支持自动扩展和重哈希...
C++实现跳表的知识点 ...跳表的优点是插入、删除和查找操作的时间复杂度都是O(log n),性能上和红黑树,AVL树不相上下,但跳表的原理非常简单。 跳表的应用 跳表的应用非常广泛,Redis和LevelDB中都有用到。
因此,跳表的查找时间复杂度可以近似为O(3*log N),但由于常数因子可以忽略,最终的时间复杂度仍为O(log N)。 以下是跳表的一些公共API接口,它们通常包括构造函数、析构函数、插入元素、删除元素和查找元素等方法...
3. **跳表**:跳表是一种随机化的数据结构,允许高效地进行查找、插入和删除操作,其平均时间复杂度为O(log n),但空间复杂度较高,为O(n)。跳表适用于需要高效查找,但对内存占用敏感的情况。 4. **时间轮**:时间...
- **跳表的优点**:跳表是一种类似于多层链表的数据结构,其主要优势在于能够提供快速的范围查询功能,单点查找的时间复杂度为 O(log n)。 - **哈希表的作用**:虽然跳表适合范围查询,但在单点查找方面效率略低,...
跳表(Skip List)是一种高效的动态数据结构,常用于实现有序集合,比如Redis中的有序集合ZSet。在Redis中,跳表被用来存储等级代码小于`z_`的数据,这使得快速查找、插入和删除这些元素成为可能。下面将详细阐述...
实际上,Redis的SortedSet是通过跳表(Skip List)实现的,跳表是一种可以在平均O(logN)时间复杂度内进行查找、插入和删除操作的数据结构。它通过多级索引,加快了查找速度,同时构造相对简单,比红黑树更容易理解和...
1. **跳表支持近似“折半查找”算法:**Redis采用跳表结构,通过在有序链表的基础上增加多级索引来支持类似二分查找的功能,从而实现了快速的查找、插入与删除操作。 2. **纯内存操作:**所有数据均存储于内存中,...
例如,哈希表用于键值对的存储,提供O(1)的查找和修改时间复杂度;压缩表用于存储较短的字符串,节省内存空间;跳表则用于有序集合的快速查找和遍历。 5. **自定义事件分离器**: Redis 自带了一个事件分离器,...
在构建跳表时,新插入的节点会随机决定其拥有的层数,这使得在不同层级间形成了概率上的平衡,从而保证了平均查找时间复杂度为O(log n)。 在C++中实现跳表,通常包括以下几个关键部分: 1. **节点定义**:每个节点...
跳表的期望空间复杂度为 $O(n)$,跳表的查询,插入和删除操作的期望时间复杂度都为 $O(\log n)$。获取节点的最大层数模拟以 $p$ 的概率往上加一层,最后和上限值取最小。```cppint randomLevel() { int lv = 1; // ...
散列表,又称哈希表,通过散列函数将键映射到特定位置,实现快速的查找、插入和删除操作,时间复杂度通常接近O(1)。而链表则是一种线性数据结构,通过节点间的链接关系来存储数据,便于在任意位置进行插入和删除,但...
跳表是一种高效的数据结构,常用于数据库和搜索引擎中,它以链表为基础并结合了随机化算法,使得在平均情况下查找、插入和删除操作的时间复杂度达到O(logn)。跳表在Redis和LevelDB等数据库系统中被广泛应用,替代了...
它通过多级索引,使得查找时间复杂度达到O(logn)。在Redis的Zset集合中,跳表用于支持有序集合的各种操作,如增删查元素和按范围查找,其性能优于红黑树在区间查找上的表现。 这些数据结构的理解和熟练应用是成为一...
散列表用于根据ID快速查找、删除和更新信息,时间复杂度通常为O(1)。而跳表则用于按积分查询,通过索引层提供近似于O(logn)的时间复杂度。为了支持排名查询,我们可以在跳表的索引节点中添加span字段,记录连续积分...