算法与数据结构【Java】:跳跃链表

Java实现跳跃表(skiplist)的简单实例 主要介绍了Java编程中跳跃表的概念和实现原理,并简要叙述了它的结构,具有一定参考价值,需要的朋友可以了解下。 立即下载

普通链表有一个严重的缺陷:查找某对象时需要遍历整个链表,直到找到了该元素或者遍历完了整个链表也没有找到,时间复杂度很高。

         为了解决该问题,可以使用跳跃链表。

跳跃链表的特点:

跳跃链表中的元素按照从小到达或从大到小的规则排列,该顺序在向链表加入元素时维护,所以,只能指定向链表插入某个值,不能指定插入位置
跳跃链表使用了二分查找的思想, 查找某个元素的复杂度是O(logn)

跳跃链表最底层(对应代码中的0层)包含了所有元素
跳跃链表第1层(对应代码中的1层)包含了从0层中随机抽取的一半的元素(理论上)
跳跃链表第2层(对应代码中的2层)包含了从1层中随机抽取的一半的元素(理论上)

以此类推

为什么使用随机数?

因为跳跃表在何处插入和删除值未知,很难使用预定算法使得这个链表“平衡”(即上层索引较为平均的分隔下层索引)。所以使用随机数决定,要将新加入的结点存入哪些层

算法中的缺陷:

加入元素时采用随机值决定要插入多少层;但是删除时,必须一律从最高层开始删除,多次添加和删除之后,较高层的插入是根据随机数,删除是必须删除,所以会发生较高层结点较少的情况,降低查找效率。

另外,算法根据随机数进行层数分配,有一定的不可控因素。

下方是Java代码:

package skiplist;

import java.util.Random;

//结点类
class Node{
	int value;		//该结点的值
	Node next;		//该结点的下一个结点
	Node down;		//该结点对应的下一层结点
	
	Node(int aValue){
		value = aValue;
		next = null;
		down = null;
	}
	
	Node(int aValue, Node aNext){
		value = aValue;
		next = aNext;
		down = null;
	}
	
	
	Node(int aValue, Node aNext, Node aDown){
		value = aValue;
		next = aNext;
		down = aDown;
	}
}; 

//顺序表,链表中的元素按升序排列
class SortedList{
	Node head;		//表头结点
	Node tail;		//表尾结点
	int length;		//链表长度
	
	SortedList(){
		head = tail = null;
		length = 0;
	}
	
	
	//插入结点
	//参数:要插入新节点的值;要插入的结点的前一个结点的引用
	Node insertNode(int value, Node aheadOfInsert){

		//被插入的结点
		Node InsertedNode = null;

		//如果链表为空,调用向头部插入方法
		if (aheadOfInsert==null){
			InsertedNode = insertToHead(value);
		}
		//要在链表尾部插入,直接更新tail
		else if (aheadOfInsert == tail){
			InsertedNode = tail = aheadOfInsert.next = new Node(value, null);
		}
		//在链表中间插入
		else {
			InsertedNode = aheadOfInsert.next = new Node(value, aheadOfInsert.next);
		}
		length++;
				
		return InsertedNode;
	}


	//删除结点
	//参数:要删除的结点的前一个结点的引用
	//如果要删除第一个结点,则该参数为空
	int deleteNode(Node aheadOfRemove){
		//链表为空,直接返回-1
		if (head == null){
			return -1;
		}


		Node removedNode = null;
		//链表只有一个结点,删除该结点
		if (head == tail){
			removedNode = head;
			head = tail = null;
		}

		//参数为空,代表要删除第一个结点。同时更新head
		else if (aheadOfRemove == null){
			removedNode = head;
			head = head.next;
		}
		//正常删除结点
		else{
			removedNode = aheadOfRemove.next;
			aheadOfRemove.next = aheadOfRemove.next.next;
		}
		length--;
		return 0;
	}

	//判断链表是否为空
	int isEmpty(){
		return head == null?1:0;
	}
	//打印链表内容及相关参数
	void printSelf(){
		System.out.print("SortedList: [");
		for (Node now=head; now!=null; now=now.next)
		if (now.down == null)
			System.out.print(String.format("%d, ", now.value));
		else
			System.out.print(String.format("%d( %d), ", now.value, now.down.value));
		System.out.print(String.format("]\t\t%d\n", length));
		
	}
	private Node insertToHead(int value){
		if (head == null){
			head = tail = new Node(value, null, null);
		}	
		else {
			head = new Node(value, head);
		}
		return head;
	}
	
};



//跳跃表类
public class SkipList {
	int length;		//跳跃表最底层长度
	int layerNum;	//跳跃表最大层数
	SortedList[] layers;	//跳跃表层数的引用
	//为什么这里使用了数组?
	//因为跳跃表的层数是log(n),100层能够容纳2^100个数据,使用数组占用的空间可以忽略
	
	SkipList(){
		length = 0;
		layerNum = 0;
		layers = new SortedList[100];
		for (int i=0; i<100; i++) {
			layers[i] = new SortedList();
		}
	}
	
	
	//向跳跃表插入值
		void insert(int value){
			//get the necessary layerNum by number of nodes

			//先获得增加结点之后,该结点需要加入到哪些层
			int newLayerNum = getLayerNumRandomly(length+1);
			//更新最大层数量
			if (layerNum < newLayerNum){
				layerNum++;
			}

			//因为先要从上向下查找到要将新结点插入到哪里,并且需要将查找的路径记录下来
			//这样才能在每一层都插入该结点
			//该数组用于记录从上向下寻找的过程中,经过了哪些层的哪个结点(下标为层数,数组内容为经过的结点)
			Node[] aheadOfInsert = new Node[100];
			//数组初始化为NULL
			for (int i=0; i<100; i++)
				aheadOfInsert[i] = null;
			
			//获取每一层需要插入结点的位置
			getInsertIndex(value, aheadOfInsert);
			
			Node[] InsertedNode = new Node[100];
			for (int i=0; i<100; i++)
				InsertedNode[i] = null;
			
			//遍历每一层,插入结点
			for (int i=layerNum;i>=0;i--){
				InsertedNode[i] = layers[i].insertNode(value, aheadOfInsert[i]);
			}
			
			//更新层与层之间的指针
			for (int i=layerNum; i>=1; i--){
				InsertedNode[i].down = InsertedNode[i-1];
			}
			length++;
			//打印各个层
			System.out.println("================================");
			layers[0].printSelf();
			layers[1].printSelf();
			layers[2].printSelf();
			layers[3].printSelf();
			layers[4].printSelf();
			System.out.println("================================");
		}
	
		//因为先要从上向下查找到要将新结点插入到哪里,并且需要将查找的路径记录下来
		//这样才能在每一层都插入该结点
		//这个函用于查找该路径,该路径用要插入的结点位置的前一个结点表示,存入aheadOfInsert数组
		void getInsertIndex(int value, Node[] aheadOfInsert){
			int i;
			Node currentNode = null;
			
			//最高的层可能为空,需要在链表头插入结点,所以前一个结点为空
			for (i=layerNum; i>=0 && (layers[i].head==null || layers[i].head.value>value); i--){
				aheadOfInsert[i] = null;
			}
			//如果所有层都为空,直接返回
			if (i==-1)
				return ;
			currentNode = layers[i].head;
			
			//从上层到下层遍历,寻找该路径
			for (; i>=0; i--){
				Node now;
			
				//该循环从一层的链表前方向后方遍历,循环停止的条件有两个:
				//当遇到链表尾:说明该值只可能在下一层找到
				//当遇到比当前值还小的结点,说明要找的值,在当前结点和下一和结点之间,转向下一层寻找
				for (now=currentNode; now.next!=null && now.next.value<value; now=now.next);
				aheadOfInsert[i] = now;
				currentNode = now.down;
			}
			
		}
		
		
		//因为先要从上向下查找到要删除哪个结点,并且需要将查找的路径记录下来
		//这样才能在每一层都删除该结点
		//这个函用于查找该路径,该路径用要删除的结点位置的前一个结点表示,存入aheadOfRemove数组
		//然而,在删除结点时,有如下三种情况:
			//1、该结点不存在这一层,不需要删除,指针为NULL
			//2、该结点是该层的第一个结点,该结点的前一个结点为NULL,指针也为NULL
			//3、找到了该结点,指针正常
		//所以,需要另一个数组表示该结点是否应该被删除,这里使用数组deleteOrNot
		void getRemoveIndex(int value, Node[] aheadOfRemove, boolean[] deleteOrNot){
			int i;
			Node currentNode = null;

			//从上层向下层遍历,如果该层为空,或该层第一个值已经大于要删除的值,说明这一层不需要删除结点
			for (i=layerNum; i>=0 && (layers[i].head==null || layers[i].head.value>value); i--){
				aheadOfRemove[i] = null;
				deleteOrNot[i] = false;
			}
			//循环退出之后,i指向需要有结点有可能被删除的第一个层
			if (i==-1)
				return ;
			
			//遍历可能需要删除结点的层
			//如果要删除的结点是底层链表的第一个元素,那么向上找,把所有头元素是该元素的链表首元素全部删除
			if (layers[0].head.value == value){
				i=0;
				while(layers[i].head!=null && layers[i].head.value == value){
					deleteOrNot[i] = true;
					aheadOfRemove[i] = null;
					i++;
				}
				return ;
			}
			currentNode = layers[i].head;
			
			//否则向下沿路径查找,寻找应该删除的结点
			for (; i>=0; i--){
				Node now;
			
				for (now=currentNode; now.next!=null && now.next.value<value; now=now.next);
				if (now.next!=null && now.next.value == value){
					deleteOrNot[i] = true;
				}
				aheadOfRemove[i] = now;
				currentNode = now.down;
			}
		}
		
		//删除某个元素的函数
		void remove(int value){
			//每一层需要被删除的结点的前一个结点
			Node[] aheadOfRemove = new Node[100];
			//该层的这个结点是否有效,或者说,如果aheadOfRemove【i】==null,是代表不需要删除任何结点,还是删除第一个结点
			boolean[] removeOrNot = new boolean[100];
			for (int i=0; i<100; i++) {
				aheadOfRemove[i] = null;
				removeOrNot[i] = false;
			}
			
			//获取每一层需要被删除的结点的前一个结点
			getRemoveIndex(value, aheadOfRemove, removeOrNot);
	
			//删除结点
			for (int i=layerNum; i>=0; i--)
				if (removeOrNot[i] == true){
					layers[i].deleteNode(aheadOfRemove[i]);
				}
			length--;

			//打印结果
			System.out.println("================================");
			layers[0].printSelf();
			layers[1].printSelf();
			layers[2].printSelf();
			layers[3].printSelf();
			layers[4].printSelf();
			System.out.println("================================");
		}

		//在跳跃表中搜索某个元素
		Node search(int value){
			int i;
			Node currentNode = null;
			
			//从上层向下层遍历,如果该层为空,或该层第一个值已经大于要查找的值,说明这一层不需要查找
			for (i=layerNum; i>=0 && (layers[i].head==null || layers[i].head.value>value); i--);
			if (i==-1)
				return null;
			currentNode = layers[i].head;
			
			Node now = null;
			//从上层向下层遍历查找
			for (; i>=0; i--){
				for (now=currentNode; now.next!=null && now.next.value<=value; now=now.next);
				currentNode = now.down;
			}
			return now;
		}
		
		//随机获取某个结点应该被插入到0-k层
		int getLayerNumRandomly(int supposeLength){
			int k = 0;
			Random rand = new Random();
			//随机数
			int a = rand.nextInt(2);
			while(a==0){
				k++;
				a = rand.nextInt(2);
			}

			//根据二分的思想,查找n个结点,需要log(n)次
			//跳跃表里也就需要log(n)层,所以这里对随机产生的层数有最大值限制
			int maxLayer = getMaxLayer(supposeLength);
			if (k > maxLayer)
				k = maxLayer;
				
			return k;
		}
		
		int getMaxLayer(int supposeLength){
			return (int)Math.ceil(Math.log10(supposeLength)/Math.log10(2));
		}
		
		
		
	static public void main(String[] argv) {

		SkipList list = new SkipList();
		list.insert(33);
		list.insert(1);
		list.insert(11);
		list.insert(21);
		list.insert(-1);
		list.insert(45);
		list.insert(37);
		
		Node result = list.search(11);
		System.out.println(result.value);
		System.out.println("next Search result: " + result.next.value);
		
		list.remove(11);
		list.remove(-1);
		list.remove(45);
	}
}

 

麒麟和UOS系统编写桌面点击可执行文件 在桌面上创建一个快捷方式(.desktop 文件)来运行脚本。打开文本编辑器,创建一个新文件,如。这可以通过文本编辑器来完成。首先,确保您的脚本具有执行权限。现在,您应该可以双击桌面上的。保存此文件到桌面目录,例如,在桌面上创建一个快捷方式(文件来运行您的脚本了。使用图形界面或命令行给。现在您可以双击桌面上的。为您脚本的实际路径。是您脚本的实际路径。文件来运行您的脚本了。 阅读详情

相关推荐

从数据校准到论文呈现:fsQCA与NCA方法融合的完整实证研究指南

本文详细介绍了fsQCA(模糊集定性比较分析)与NCA(必要条件分析)方法融合的完整实证研究流程,从数据校准到论文呈现。通过软件操作技巧、R语言NCA包高效使用及论文写作规范,帮助研究者避免常见误区,提升研究质量与可靠性。特别适合需要进行组态分析的研究生和学者参考。

weixin_29215391的博客 414

跳跃表的原理和实现(Java)

/ data// links可以看到节点模型主要分为2个部分。data 部分包含具体的存储数据,这里为了不引入其他杂乱的问题,使用 Integer 作为 key 的类型,Object 作为value 的类型。links 部分包含4个指针,分别是 up、down、left、right,单从名字上就能够明白它们的作用。

chuixue24的博客 426

华三R4900 G5服务器实战:用PMC P460-B4阵列卡配置RAID1+RAID6,并搞定CentOS 7.9安装(含热备盘设置)

本文详细解析了在华三R4900 G5服务器上使用PMC P460-B4阵列卡配置RAID1+RAID6混合阵列的全过程,包括热备盘设置和CentOS 7.9系统安装。通过实战步骤和性能优化建议,帮助企业IT人员高效部署高可用存储方案,特别适合需要数据冗余和系统稳定性的企业级应用场景。

weixin_29248653的博客 357

289-跳跃表SkipList

1、跳跃表SkipList介绍 跳跃表性质: 由很多层链表组成 每一层都是一个有序的链表 最底层(level 1)的链表包含所有元素 如果一个元素出现在level i层的链表中,则它在level i之下的链表也都会出现 每个节点都包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素 跳跃表的增加、删除、查询操作时间复杂度和红黑树一样,也是O(logn)。 相比于红黑树,它的优势是: 实现起来更加简单 跳跃表的增加、删除操作只会改动局部,不像红黑树的增加、删除操作,因为需要节点重新着色和

Edward_LF的博客 300

从零到一:STM32CubeMX虚拟串口开发中的常见陷阱与优化策略

本文深入探讨了STM32CubeMX在USB虚拟串口开发中的常见问题与优化策略,涵盖数据流吞吐量瓶颈、实时性约束等核心挑战。通过实战案例和代码示例,详细解析了波特率同步异常、数据丢失等问题的解决方案,并提供了DMA配置和中断优先级调优的高级技巧,帮助开发者提升STM32虚拟串口的性能和可靠性。

weixin_29164185的博客 370

Rk3128投影仪救砖操作和固件分享思路

大家搞一条比较硬的东西,插入耳机口,就可以进入刷机模式了的,我的机器是这样的,大家也可以试试。(看不懂可以往下看)

MMX7088的博客 1万+

数据结构:跳跃表java实现详解

【代码】数据结构:跳跃表java实现详解。

工匠精神coding,终生学习 409

深度学习——VGG16模型详解

1、网络结构 VGG16模型很好的适用于分类和定位任务,其名称来自牛津大学几何组(Visual Geometry Group)的缩写。 根据卷积核的大小核卷积层数,VGG共有6种配置,分别为A、A-LRN、B、C、D、E,其中D和E两种是最为常用的VGG16和VGG19。 介绍结构图: conv3-64 :是指第三层卷积后维度变成64,同样地,conv3-128指的是第三层卷积后维度变成128; input(224x224 RGB image) :指的是输入图片大小为224244的彩色图像,通道为

橙子的博客 12万+

Java数据结构:跳跃链表

1、跳跃链表 用某种数据结构来维护一组有序的数据的列表,尽可能在插入、删除、查找等操作上能够尽可能的快速。 数组:使用数组存储的话,采用二分法可以在 O(logn) 的时间里找到指定的元素,在进行插入和删除则时间复杂度为 O(n) 链表:使用链表存储的话,就插入、删除动作而言,所需的时间复杂度为 O(1) ,加上查找所需的时间复杂度为O(n),故插入、删除所需的总的时间复杂度为O(n)。 ...

baidu_30130783的博客 390

【OpenClaw从入门到精通】第11篇:OpenClaw 2026多模态实战全攻略:OCR/语音/图像自动化(附完整代码+双部署方案)

本文聚焦OpenClaw 2026版核心升级的多模态能力,从底层架构原理到实操落地全流程拆解。先解析“统一指令解析+多工具适配器”的核心设计逻辑,再提供阿里云规模化部署(适合批量任务)与本地汉化版部署(适合隐私数据调试)的详细步骤,含依赖安装、配置验证完整操作;随后落地三大高频实战场景——OCR合同信息结构化提取、会议录音自动转写纪要、电商商品图片智能打标,每个场景均提供可直接运行的完整代码、执行结果演示及流程说明;最后补充多模态任务避坑指南、性能优化技巧与成本控制方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2611

vLLM显存逆向计算:如何得到最优gpu-memory-utilization参数

本文提出了一种**逆向工程**的思路:基于vLLM显存占用的底层机制,通过精确计算模型权重、KV缓存、激活内存等各组件的显存需求,**倒推出最优的gpu-memory-utilization参数**。这种方法让我们能够在部署前就准确预估资源需求,实现一次配置、稳定运行。本文我们将从vLLM显存计算的核心原理出发,构建完整的倒推计算框架和源码,并通过大量实验验证其准确性(会有误差,但基本可以直接使用)。

羊城迷鹿的博客 1947

算法与数据结构【C++与Java实现】:链表篇

对于大多数应用而言,存储数据最好的方式就是使用表。 表有两种最常用的实现:数组和链表 数组是在内存中连续存在的结构,且编译器就需要直到其大小。对于无法提前预估数据规模的程序,如果初始的数组太小,则需要扩展数组大小,这常常伴随着大量的内存复制,时间复杂度很高;如果初始的数组太大,则会造成很大的内存资源浪费。 链表也是一种连续的数据结构,与数组的不同是,每一个元素在内存中不一定连续存储,元素与元...

WilliamCode的博客 1766

OV9734 DATASHEET,完整规格书

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

数据结构与算法——跳表

1. 概述 前面说到了二分查找,并且它是基于顺序表结构的,即数组,如果直接用于链表,时间复杂度会比较的高,是 O(logn),一般我们不会这样做。那么有没有基于链表的二分查找呢?答案就是今天说到的跳跃链表。 2. 跳表长什么样子? 对于一般的链表,我们进行查找的话,需要遍历整个链表,就像下面这样:如果我们要找节点 9 ,需要遍历 9 个节点。 如果我们在原始链表之上建立一级链表,会是什么...

roseduan 的个人博客 779

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

底层:跳跃链表skiplist

底层:跳跃链表skiplist 跳表 每个node的结构:含键和值,还有一个由多个node组成的list,就是本node在不同层指向下一个node的指针。 每次初始化时初始化最初的节点,也就是最左边的节点,它的高度就是跳表最大高度,初始每个位置指针指向null。 插入元素时首先判断该元素在集合中是否存在,从最初节点的最高位置开始寻找,向前的指针键值比要找的值大就向下移动,小就向前移动。...

dig73817的博客 215

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

数据结构之跳跃表

文章目录引入性质实现原理代码实现 跳跃链表又称“跳表”,是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间),并且对并发算法友好。 引入 在单链表中查询一个元素的时间复杂度为O(n),即使该单链表是有序的,我们也不能通过二分的方式缩减时间复杂度。 如下图: 但是如果我们在有序的单链表上加入多层索引,如下图,此时它的查找效率就类似于二分查找 ...

码农先锋的博客 340

Redis使用及数据结构

redis的五种基础数据结构,string,list,set,hash,zset。详情参见redis 字符串(动态,类似于Java的Array List,扩容加倍)结构应用非常广泛,一个常见的用途就是缓存用户信息。我们将用户信息结构体使用JSON序列化成字符串,然后将序列化的字符串塞进redis来缓存。那么取出用户信息就需要反序列化。 Redis的列表结构(list)常用作异步队列使用,将需要延后处理的任务结构体序列化成字符串塞进redis的列表,另一个线程从这个列表中轮询数据进行处理 Redis底层

MOWRONG的博客 189

3w字深度好文|Redis面试全攻略,读完这个就可以和面试官大战几个回合了

不过本文不是要讲述数据结构和算法的,而是另外一个面试重点Redis,因为Redis也是跨语言的共同技术点,无论是Java还是C++都会问到,所以是个高频面试点。笔者是2017年才开始接触Redis的,期间自己搭过单机版和集群版,不过现在公司大一些都完全是运维来实现的,我们使用者只需要在web页面进行相关申请即可,很多细节都被屏蔽了,这样当然很方便啦,不过我们还是要深入理解一下的。在工作几年中笔者接...

583

看完这篇再也不怕 Redis 面试了

0x00.前言Redis是跨语言的共同技术点,无论是Java还是C++都会问到,所以是个高频面试点。笔者是2017年才开始接触Redis的,期间自己搭过单机版和集群版,不过现在大一些的公...

过往记忆大数据 2434

Java之集合(二十六)ConcurrentSkipListMap

  转载请注明源出处:http://www.cnblogs.com/lighten/p/7542578.html 1.前言   一个可伸缩的并发实现,这个map实现了排序功能,默认使用的是对象自身的compareTo方法,如果提供了比较器,使用比较器的比较方法。简单来说ConcurrentSkipListMap是TreeMap的并发实现,但是为什么没有称之为ConcurrentTr...

decvo6179的博客 225

来来来,告诉你啥是跳跃链表【含代码】

点击上方蓝字设为星标下面开始今天的学习~ 作者 |梁唐 来源 |TechFlow前文:啥是布隆过滤器算法?今天要介绍的数据结构非常了不起,和之前介绍的布隆过滤器一样,是一...

程序员吴师兄的博客 402

深度好文| Redis面试全攻略

0x00.前言Redis是跨语言的共同技术点,无论是Java还是C++都会问到,所以是个高频面试点。笔者是2017年才开始接触Redis的,期间自己搭过单机版和集群版,不过现在大一些的公...

过往记忆大数据 2672

数据结构和算法总结

数据结构和算法总结 数据+数据元之间的关系+数据上的操作(增删改查排) 线性表 按照存储方式分类 1.顺序存储:顺序表、栈、队列。随机访问效率高,随机插入效率低。 2.链式存储:链表。随机访问效率低,随机插入效率高。(只需要定位+修改指针) 按照访问方式分类 1.可以随机访问:一般的线性表。链表、顺序表 2.受限访问:受限线性表。栈、队列   各结构细节 1.链表 数据结构

可乐薯片编程小课堂 411

Redis复习

文章目录Redis复习一,Redis底层数据结构1.String类型2.list类型3.hash字典类型4.跳跃链表5.整数集合6.压缩列表二,redis事务2.1redis中的事务三,缓存雪崩,穿透,击穿1.缓存雪崩场景解决方法2.缓存穿透场景解决方法布隆过滤器原理应用3.缓存击穿场景解决方法四,数据一致性问题为什么是删除缓存,而不是更新缓存?五,redis持久化1.何为持久化?2.redis中...

kevin的博客 1253

Redis 面试全攻略、面试题大集合

目录0.前言1.Redis往事2.Redis的江湖地位3.聊聊实战4.底层实现热点题目Q1: Redis常用五种数据类型是如何实现的?Q2: Redis的SDS和C中字符串相比有什么优势?Q3:Redis的字典是如何实现的?简述渐进式rehash的过程。Q4:跳跃链表了解吗?Redis的Zset如何使用跳表实现的?Q5:Redis为什么使用单线程?讲讲Redis网络模型以及单线程如何协调各种事件运行起来的?Q6:了解Redis的内存回收吗?讲讲你的理解1.1 为什么要回收内存?1.2 内存从哪里回收?1.3

ifknow 4912
上一篇: 算法与数据结构【C++】:跳跃链表
下一篇: 算法与数据结构【Java】:稀疏表
WilliamCode
博客等级 码龄11年 118粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值