Redis跳表

Redis-跳跃表(skip List) 什么是跳跃表(skip list) 跳表全称叫做跳跃表,简称跳表。跳表是一个随机化的数据结构, 跳跃表(skiplist)是一个用于有序元素序列快速搜索的随机化的数据结构,由美国计算机科学家William Pugh发明于1989年,论文《Skip lists: a probabilistic alternative to balanced trees》中提出。 它的效率和红黑树以及 AVL 树不相上下,但实现起来比较容易。是一种可以于平衡树媲美的层次化链表结构——查找、删除、添加等操作都可以在对数期望时间下 阅读详情

一、跳表为什么能在Redis中C位出道?

1.1 设计哲学之争


有序数据结构

平衡树族

跳跃链表族

AVL树

红黑树

B+树

Redis跳表

LevelDB跳表

对比优势:

  • 实现复杂度比红黑树低5倍

  • 天然支持范围查询

  • 便于并发控制(无需全局重平衡)

1.2 Redis的选择之谜

[Sorted Set核心需求]
1. 快速定位排名(O(logN)复杂度)
2. 高效范围查询(ZRANGE命令)
3. 动态数据更新(自动调整位置)


二、跳表底层结构全解析

2.1 节点结构解剖

typedef struct zskiplistNode {
    sds ele;                      // 成员对象
    double score;                 // 排序分数
    struct zskiplistNode *backward; // 后退指针
    struct zskiplistLevel {
        struct zskiplistNode *forward; // 前进指针
        unsigned long span;            // 跨度
    } level[];                   // 柔性数组(层级指针)
} zskiplistNode;

核心参数:

  • 最大层数:32层(可配置)

  • 层数生成算法:幂次定律(P=1/4)

  • 平均查找路径长度:logN + 2级

2.2 跳表示意图


头节点:L32

节点1:L4

节点2:L3

节点3:L5

节点4:L2

节点3:L4

节点3:L3

nil

节点2:L2


三、插入操作的高光时刻

3.1 插入算法五步走

def zslInsert(zsl, score, ele):
    update = []  # 更新路径数组
    rank = [0]*ZSKIPLIST_MAXLEVEL  # 排名数组
  
    # 步骤1:查找插入位置
    x = zsl.header
    for i in range(zsl.level-1, -1, -1):
        rank[i] = 0 if i == zsl.level-1 else rank[i+1]
        while x.level[i].forward and 
             (x.level[i].forward.score < score or 
             (x.level[i].forward.score == score and 
             compareStringObjects(x.level[i].forward.ele,ele) < 0)):
            rank[i] += x.level[i].span
            x = x.level[i].forward
        update.append(x)
  
    # 步骤2:生成随机层数
    level = zslRandomLevel()
  
    # 步骤3:创建新节点
    newNode = createNode(level, score, ele)
  
    # 步骤4:调整指针和跨度
    for i in range(level):
        newNode.level[i].forward = update[i].level[i].forward
        update[i].level[i].forward = newNode
        newNode.level[i].span = update[i].level[i].span - (rank[0] - rank[i])
        update[i].level[i].span = (rank[0] - rank[i]) + 1
  
    # 步骤5:调整后退指针和长度
    newNode.backward = update[0]
    if newNode.level[0].forward:
        newNode.level[0].forward.backward = newNode
    zsl.length += 1

3.2 层数生成规则

int zslRandomLevel(void) {
    int level = 1;
    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
        level += 1;
    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

层数概率分布:

  • L1:100%

  • L2:25%

  • L3:6.25%

  • Ln:(1/4)^(n-1)


四、查找与删除艺术

4.1 查找操作流程图


ClientHeaderNode1Node2Target从最高层开始查找score < target?继续移动找到目标节点返回查找结果ClientHeaderNode1Node2Target

4.2 删除操作三步骤

  1. 查找要删除的节点

  2. 更新前后指针关系

  3. 释放节点内存


五、跳表性能终极PK

特性跳表红黑树B+树
实现复杂度O(N)简单O(N)复杂O(N)复杂
范围查询效率O(logN)优秀O(N)需要中序O(logN)优秀
插入/删除开销O(logN)中等O(logN)中等O(logN)中等
内存使用效率每个节点多指针颜色标记空间节点填充因子高
并发控制难度易于局部锁需要全局锁需要页面锁
典型应用场景Redis ZSETC++ STL Map数据库索引


六、Redis使用跳表的三大精髓

6.1 ZRANGE命令魔法

ZADD leaderboard 98 "PlayerA" 95 "PlayerB"
ZRANGE leaderboard 0 -1 WITHSCORES  # 高效范围查询

6.2 排名统计奥秘

typedef struct zset {
    dict *dict;          // 哈希表: O(1)查找
    zskiplist *zsl;      // 跳表: O(logN)排名
} zset;

6.3 延迟队列实现

def add_delayed_task(task_id, execute_time):
    redis.zadd("delayed_queue", {task_id: execute_time})
​
def check_delayed_tasks():
    now = time.time()
    tasks = redis.zrangebyscore("delayed_queue", 0, now)
    process_tasks(tasks)
    redis.zremrangebyscore("delayed_queue", 0, now)

七、跳表使用六大陷阱

  1. 内存膨胀风险:元素较多时考虑使用ziplist编码 zset-max-ziplist-entries 128

  2. 分数相同排序:当score相同时按成员字典序排列

  3. 大数据量瓶颈:元素超过10万时层级指针占内存30%+

  4. 更新操作误区:先删除旧元素再插入新元素(原子性风险)

  5. 遍历顺序误解:默认从低到高排序,反向遍历用ZREVRANGE

  6. 内存回收隐患:删除大量元素后及时主动释放内存


八、跳表优化的三重境界

8.1 层级优化策略

// 修改ZSKIPLIST_P参数(默认0.25)
#define ZSKIPLIST_P 0.5  // 增加高层节点密度

8.2 内存布局优化

原始内存布局:
┌─────────────┐
│  header     │
├─────────────┤
│  level 0    │ 
├─────────────┤
│  level 1    │
└─────────────┘
​
优化后:
┌─────────────┐
│  header     │
│  level 0-7  │
└─────────────┘

8.3 混合索引方案


快速定位

哈希表

跳表节点

元素内容


九、生产环境常见问题

  1. 为什么ZSCORE时间复杂度是O(1)? (哈希表直接查找)

  2. 如何实现相同score按时间排序? (将时间戳编码到score中)

  3. 为什么有时候跳表比红黑树慢? (CPU缓存不友好导致)

  4. 如何避免跳表内存溢出? (设置maxmemory策略)


十、源码层面的五个灵魂拷问

  1. 为什么要使用柔性数组实现层级指针? (节省内存,连续内存访问加速)

  2. 跨度(span)字段的真正作用是什么? (快速计算排名,而不是遍历统计)

  3. 为什么Redis跳表没有使用锁机制? (内存操作单线程保证原子性)

  4. 如何保证跳表与哈希表数据一致性? (所有操作封装成原子步骤)

  5. 最高32层的设计依据是什么? (log2^32=42亿级别数据量)

Redis内部数据结构--跳表详解 skiplist本质上也是一种查找结构,用于解决算法中的查找问题,跟平衡搜索树和哈希表的价值是一样的,可以作为key或者key/value的查找模型。 阅读详情

相关推荐

Redis-跳表

跳表(skiplist)是一种有序数据结构,它通过在每个节点维持多个指向其他节点的指针来达到快速访问的目的。Redis使用跳表作为有序表的底层实现。

千磨万击还坚韧,任尔东西南北风 2848

Redis数据结构之——跳表skiplist

Redis数据结构之——跳表skiplist

weixin_46935110的博客 7079

Redis Sorted Set 跳表的实现原理与分析

在 Redis 中,Sorted Set(有序集合)是一种非常重要且高效的数据结构。与普通的 Set 不同,Sorted Set 为每个元素关联了一个分数(score),并按照这个分数进行排序。在许多需要快速插入、删除、查找和范围查询的场景下,Sorted Set 提供了理想的解决方案。而其底层的核心数据结构之一便是跳表(Skip List),这种结构有效地支持了有序集合的高效操作。

喵手的博客 1515

Redis-数据结构-跳表详解

Redis跳表详解

喻师傅的学习笔记 3219

跳表:为什么 Redis 一定要用跳表实现有序集合?

在 Redis 中,有序集合(sorted set)是一种非常重要的数据结构,它被广泛应用于各种场景,如排行榜、延时任务队列等。而 Redis 选择使用跳表(skiplist)来实现有序集合,这背后有着深刻的原因。

yonggeit的博客 3624

技能伤害继承英雄属性【War3地图编辑器】

风暴之锤跟随山丘之王的力量增长

ArYe 2303

Redis 跳表

跳表(SkipList,全称跳跃表)是用于有序元素序列快速搜索查找的一个数据结构,跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。它在性能上和红黑树,AVL树不相上下,但是跳表的原理非常简单,实现也比红黑树简单很多。 回顾链表,链表的痛点就是查询很慢很慢!每次查询都是一种O(n)复杂度的操作,下图这是一个带头结点的链表(头结点相当于一个固定的入口,不存储有意义的值)

小楠的博客 2086

锂电池主动均衡理解

锂电池主动均衡方案总结: 来自:http://wenku.baidu.com/link?url=EWiyACZ3aLPhcOjI4FZL3uQ9d0FD6dBhADQSVQiaSmRHHATTdSig1Wy39JY7-ijCzbAEYG1ymz6Lv5zhGdZaStQSHzFt6v3h3_tMrJudz9O 目前车厂采用被动均衡方案的公司:(来自网页) 目前采用主动均衡的...

weixin_34365417的博客 2910

Redis中的跳表

跳表是一种基于多级链表的数据结构,它通过在链表的基础上增加多级索引来加速查找操作。传统链表的查找时间复杂度为 O(n),而跳表通过建立多层索引链表,优化了查找性能,平均查找时间复杂度为 O(log n)。底层链表包含所有的节点,并且按从小到大的顺序排列。上层链表是底层链表的一个“抽样”,每隔一段节点会抽取一个节点放到上层链表中,从而加速查找。每个节点会有一个随机的“高度”,表示该节点存在于多少层链表中。这种随机化策略使得跳表的平均复杂度为 O(log n),且避免了复杂的平衡操作。

小小程序猿 1409

EB Tresos激活失败?3种实用解决方案帮你搞定(含离线激活步骤)

本文针对EB Tresos软件激活失败问题,提供了三种实用的解决方案。详细分析了激活失败的常见根源,并系统阐述了在线环境下的排查步骤、无网环境下的离线激活全流程,以及高级许可证环境修复方法,帮助汽车电子工程师快速恢复开发环境。

milk8的博客 609

前端零代码丨UIOTOS + NodeRed:无代码搭建工控上位机的绝配组合!

用户类型价值硬件产品商软硬一体方案,无代码GUI上位机成新卖点软件服务商售前原型演示利器,交付成本降低至1/3平台开发商融合无代码技术,同质化竞争中脱颖而出🚀 总结UIOTOS的前端零代码设计(页面嵌套、属性继承、节点连线)与NodeRed的后端流程自动化,堪称工控与IoT开发的黄金组合。无论是串口通信、SCADA监控还是业务管理,均能实现“无代码交付”,真正让前端不求人,硬件交互触手可及!探索更多案例:UIOTOS官网在线体验。

2502_91192798的博客 757

Redis中跳表的实现原理

跳表: 主要通过多重链表实现,最底层包含所有元素,上层都是底层元素的跳跃索引,每一层的元素是从下一层中随机选择的,通常使用概率算法来决定一个元素是否出现在上一层。每个节点包含一个值和指向下一层节点的指针插入时,首先从最高层开始查找插入位置,然后随机决定新节点的层数,最后在相应的层中插入节点并更新指针。删除时,同样从最高层开始查找要删除的节点,并在各层中更新指针,以保持跳表的结构。查找时,从最高层开始,逐层向下,直到找到目标元素或确定元素不存在。查找效率高,时间复杂度为 O(logn)

欢迎来到空说的博客 1198

最详细的Cadence OrCAD Capture自带元件库的介绍

最详细的Cadence OrCAD Capture自带元件库的介绍 本章节将介绍Cadence OrCAD Capture 软件自带的各类元件库的分类,方便大家在设计时能够快速的选择元件。 AMPLIFIER.OLB 共182个零件,存放模拟放大器,IC,如LM386,MAX457等。 ARITHMETIC.OLB 共182个零件...

LGCPCB的博客 6万+

Redis 之跳表

跳表,又称跳跃表,在 Redis 中表现为 skiplist,是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。 在正式介绍跳表前,先来看看 Redis 中的有序集合。 zadd class 87.5 alice 87.5 fred 65.5 charles 94.5 emily 向 class 有序集合里插入 4 条数据,查看下底层编码实现。 1...

molaifeng的专栏 1352

Altium Designer 16来自原理图/PCB的各种报错 (持续更新):

NO1.Nets with only one pin: 根本原因: 在BGA的原理图绘制时,我一般习惯拉出该元件的所有IO的网络,这方便利于我开发其他款板卡。同样也会因为不同板卡的需求不同而造成有些IO并没有使用到,也就是整个原理图中only one pin。 解决方案: 鼠标右键工程文件>工程参数>下图圈中的选项将“错误”更改为“警告/不报告” ...

优快云@猿谷攻城狮 1万+

YOLOv8融合HAttention:激活更多像素的注意力机制科研实践指南

HAttention通过层级化像素激活与融合的设计,为YOLOv8的像素级特征利用能力带来了质的飞跃。从原理理解到代码实现,再到集成调优,每一步都是科研中“解决像素信息遗漏难题”的具体实践。如果你在实验中发现某类细节或大尺度目标的检测仍有不足,可以尝试结合数据增强(如随机裁剪、多尺度训练)来强化模型对像素特征的学习能力。科研的价值在于不断挖掘技术的潜力,希望这份指南能真正帮你在目标检测的像素级特征利用领域找到新的突破点,祝你在科研探索中持续收获创新与成长。

FJN110的博客 106

Redis中的跳表是怎么回事

引子 早些年笔者一次真实的美团面试经历。 面试官:请问Redis有哪些数据结构? 我:string、hash、list、set、zset、 bitmaps、hyperloglogs、geospatial、布隆过滤器。 面试官:zset主要用什么应用场景? 我:zset主要是一种有权重的set集合,因为每一个元素都可以有一个“分数”,redis提供了根据这个分数操作的api,比如取分数前几的啊,所以我们可以用作一些类似于排行榜的东西,比如点赞次数前几名的啦,,叭叭叭。 面试官:嗯,,,那它的底层的数据结构

程序员大航子 4757

Python蓝色跳动的爱心(完整代码)

Python语言实现蓝色跳动的爱心的完整代码。 代码分析 这段代码使用了 库来创建一个动态的爱心图案,并在屏幕上显示带有动态效果的“我爱你”字样。以下是对这段代码的详细分析: 用于创建图形用户界面(GUI)。 用于生成随机数,主要用于控制爱心图案的扩散效果。 中的 , , , 用于数学计算,生成爱心形状和扩散效果。 包含了 等常量,用于控制控件的对齐方式。 2. 全局变量定义 , : 定义画布的大小。 , : 爱心的中心坐标。 : 用于定义爱心形状的缩放

AIGC 1919

redis跳表的实现

看了redis的跳表的源码,感觉代码的实现非常短小精悍。 redis中跳表主要实现:增删改查, 除了这几个常规功能之外,还有一个很牛逼且很实用的功能:获取节点的rank排名、或者获取指定范围rank的节点。 redis中跳表的实现 typedef struct zskiplistNode { robj *obj; double score; // ...

spb3732的博客 910

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Redis数据结构总结-跳表

普通链表的时间复杂度很有意思,增删改都是O(1),只有查是O(n).而且无论这个链表元素是否有序,查询时间复杂度都是O(n),这就很让人沮丧了.如果是数据的话,元素有序我们可以去用二分法,那就快很多了.但是链表的查询让人有点绝望.难道一点办法都没有吗?如果链表是有序的,还是有办法的,新的数据结构-跳表!链表在查找元素的时候,因为需要逐一查找,所以查询效率非常低,时间复杂度是O(N),于是就出现了跳表。

左灯右行的爱情 1868

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Redis系列-跳表源码分析

跳表是一种具有$O(logn)$级别的查询时间复杂度的数据结构,redis的有序集合在数据比较多或者单个数据比较大的时候底层使用的数据结构就是跳表。跳表相比于其他查询结构如红黑树、B树、B+树等等,具有易于实现的特点。LeetCode上没有手写红黑树或者B树的题目,但是有题目要求手写跳表,可见其相对易于实现。本文将以redis里的跳表源码来分析跳表这种数据结构,所使用的redis版本为6.0.19

zhuohuashiyi 1552

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

redis的zset结构跳表

跳表:为什么 Redis 一定要用跳表来实现有序集合? 上几篇主要是学习二分查找算法,但是二分查找底层依赖的是数组随机访问的特性,所以只能用数组来实现。如果数据存储在链表中,就没办法使用二分查找了吗? 此时跳表出现了,跳表(Skip list)实际上就是在链表的基础上改造生成的。 跳表是一种各方面性能都比较优秀的动态数据结构,可以支持快速的插入、删除、查找操作,写起来也不复杂,甚至...

适恒 7440

【Redis】求求你,别再问跳表了

目录跳表使用场景结构描述查询算法插入算法删除算法时间复杂度空间复杂度总结Redis使用跳表而不是红黑树? 跳表 使用场景 跳表(Skiplist )是一个特殊的链表,相比一般的链表,有更高的查找效率,可比拟二叉查找树, 平均期望的查找、插入、删除时间复杂度都是O(log n),许多知名的开源软件(库)中的数据 结构均采用了跳表这种数据结构∶ Redis中的有序集合zset LevelDB、RocksDB、HBase中Memtable Apache Lucene中的Term Dictionary、Posti

爱敲代码的小黄 6509

Redis为什么用跳表实现有序集合

近几年针对 Redis 面试时会涉及常见数据结构的底层设计,其中就有这么一道比较有意思的面试题:“Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?本文就以这道大厂常问的面试题为切入点,带大家详细了解一下跳表这个数据结构。本文整体脉络如下图所示,笔者会从有序集合的基本使用到跳表的源码分析和实现,让你会对 Redis 的有序集合底层实现的跳表有着更深刻的理解和掌握。这里我们需要先了解一下 Redis 用到跳表的数据结构有序集合的使用,Redis 有个比较常用的数据结构叫。

2403_87122707的博客 1387
上一篇: Redis九大核心数据类型
下一篇: Spring Cloud微服务架构深度解析
KBkongbaiKB
博客等级 码龄4年 1244粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值