登录社区云,与社区用户共同成长
邀请您加入社区
基础数据结构是机器学习的底层基石。机器学习的模型算法是上层“表象”,而数组、链表、哈希表则是支撑表象落地的底层“根基”。数组以连续内存与高效数值运算,撑起了机器学习所有核心计算场景;链表以动态灵活的特性,适配了各类可变数据与动态迭代场景;哈希表以高效键值映射,实现了全流程的检索加速与冗余优化。从数据预处理到模型训练,从迭代优化到线上部署,三类基础数据结构贯穿机器学习全过程,其内存特性与时间复杂度的
本文深入解析鸿蒙内核中的核心数据结构LOS_DL_LIST双向链表,它是系统运行的关键基础。文章通过生动的比喻(将指针比作"触手")和清晰的图示,展示了双向链表在鸿蒙系统中的广泛运用和精妙设计。作者详细讲解了双向链表的基本概念、功能接口(包括初始化、插入、删除等操作)以及强大的宏支持,强调理解这一数据结构对掌握鸿蒙内核至关重要。文中还提供了实用的工具建议(如Source Ins
数组与链表作为计算机科学中最基础的数据结构,在Java中有着广泛应用。它们的设计差异直接影响着程序的性能特性,理解其底层原理与适用场景,是资深资深工程师er必备的核心能力。本文将从内存布局、操作特性到实际工程实践,全面剖析这两种数据结构的本质区别。
结合红黑树优化,性能和稳定性都显著提升。在 JDK 1.8 及以后,而在 JDK 1.8。
座位一排共 N 个座位,编号分别为[0,N-1],动态维护一个已占用座位的列表,并在每次有员工进入时计算最佳座位,以及在有员工离开时更新座位状态。seat -> 0,空在任何位置都行,但是要给他安排索引最小的位置,也就是座位 0。:在处理完所有操作后,输出最后一个进入的员工的座位编号。如果会议室已满,则输出。seat -> 4,要和旁边的人距离最远,应该坐到中间,也就是座位 4。例如 -4 表示坐
输入一串方波信号,求取最长的完全连续交替方波信号,并将其输出,如果有相同长度的交替方波信号,输出任一即可。方波信号高位用1标识,低位用0标识 。说明:输入信号字符串(长度 >= 3 且 <= 1024):例如:0010101010110000101000010注:输入总是合法的,不用考虑异常情况输出最长的完全连续交替方波信号串例如:01010若不存在完全连续交替方波信号串,输出 -1。输入输出说明
反射可以在运行时获取到一个类的所有信息,包括(成员变量,成员方法,构造器等)反射可以直接操作类的私有属性反射就是把Java类中的各种成分映射成一个个的Java对象双亲委派模型,就是加载类的时候,先请求其父类加载器去加载,如果父类加载器无法加载类,再尝试自己去加载类。如果都没加载到,就抛出异常。使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。
对于顺序表而言,内存利用率很高,按位置查找效率高。但插入删除需要搬移大量元素,时间效率低。并且堆区必须出现连续的空间,空间不满足。因此可以考虑链表链表的定义:单向链表只能往一个方向访问,一旦访问了下一个节点,那么再也不能回到之前的状态了需要申明节点和表头,每个节点的next域指向下一个节点,而表头则存储头节点和节点的总个数等,在头节点(head)中的无任何意义,则是指向第一个节点 。 C实现:Ja
本文深入解析了JDK1.8中HashMap的红黑树优化机制。当链表长度超过8且数组容量≥64时,HashMap会将链表转换为红黑树(O(logn)查询),退化阈值为6以避免频繁转换。这种设计基于泊松分布原理,平衡了性能与空间成本。文章通过源码分析揭示了树化的双重条件,并探讨了背后的数学原理和工程考量,为开发者提供了HashMap优化的完整理解框架。
摘要:AQS(抽象队列同步器)采用双向链表实现同步队列,主要基于三个核心原因:1)处理线程取消时能O(1)高效删除任意节点,单向链表需O(n)遍历;2)释放锁时可反向回溯清理无效节点,避免锁死;3)完美契合AQS无锁设计,所有操作通过CAS原子完成。双向链表的prev/next指针支持高效删除和双向遍历,解决了并发场景下线程动态取消和可靠唤醒的核心痛点,是AQS高性能的关键设计。相比之下,单向链表
HashMap 是 Java 非线程安全键值对容器,JDK8 底层为数组 + 双向链表 + 红黑树,通过哈希扰动、位运算定位桶下标。默认负载因子 0.75 平衡时空,链表≥8 且数组≥64 时转红黑树。需注意线程不安全(换 ConcurrentHashMap)、Key 重写 hashCode/equals,合理设置初始容量可减少扩容。
LVGL(Light and Versatile Graphics Library)作为嵌入式领域主流的开源 GUI 库,凭借轻量化、跨平台、易扩展的特性,广泛应用于单片机(STM32/ESP32 等)和 Linux(ARM/x86)平台。页面切换是 LVGL 开发中的高频操作,但如果管理不当,极易引发内存泄漏—— 单片机资源有限(KB 级 RAM),泄漏会直接导致系统死机;Linux 平台虽内存
Java中的基础类型和引用类型,以及变量创建和传值/传址机制
state 是一个无语义的整型变量,AQS 仅提供原子操作方法,具体语义由子类(如state = 0:锁处于空闲状态,当前无线程持有锁,新线程可尝试获取;state > 0:锁处于被持有状态,若为(可重入锁),state的值等于「当前线程重入锁的次数」(如重入 2 次则state=2释放锁时,线程需原子性减少 state 值,直到state=0,表示锁完全释放。队列关系:AQS 双向链表队列是原始
该篇主要讲解了双向链表,双向循环链表之间与单向链表的区别,以及需要注意的事项,也带有详细的代码,最后就归纳总结了数组和链表的区别不同。
摘要: Java的LinkedList是基于双向链表实现的线性表结构,支持高效的头尾增删操作(O(1)),但随机访问较慢(O(n))。它实现了List和Deque接口,可用作列表、队列或栈。相比ArrayList,LinkedList在频繁头尾操作的大数据量场景中略有优势,但在大多数情况下ArrayList性能更优。现代推荐使用ArrayDeque替代LinkedList作为队列/栈的实现。Lin
以Java的LinkedList为例,虽然提供了get(index)方法,但其底层实现是通过遍历链表节点(逐个访问next属性)来定位目标元素,这意味着每次索引访问都需要O(n)的时间复杂度。虽然本题给出了节点数量,但这些节点可能属于不同的链表结构,因此实际链表长度仍是未知的。在Java中,LinkedList的get(index)方法时间复杂度为O(n)而非O(1),这种情况下更推荐使用Arra
本文介绍了链表操作的两种核心方法:反转链表和虚拟头节点技巧。链表不支持随机访问,操作时需注意保存节点引用。反转链表可通过迭代或递归实现,迭代法空间更优。虚拟头节点(dummy node)能统一处理头节点和中间节点的操作,避免边界判断。以删除倒数第N个节点为例,演示了如何结合双指针和dummy node简化逻辑。这些技巧是解决复杂链表问题的基础,如回文链表、分组反转等。
LinkedList是 Java 集合框架中List和Deque接口的双重实现者。与ArrayList那种“紧凑型”的连续存储不同,LinkedList采用了“分布式”的存储结构。这种结构赋予了它极强的灵活性,但也带来了不少性能上的折中。在现代 Java 开发中,LinkedList的地位其实比较尴尬。缓存友好性:数组在内存中是连续的,对 CPU 缓存(Cache Line)非常友好;链表节点是散
让我们来实现一个为数据库内核服务的 cache。本次 project 我们要实现 3 个 Task:一般来说适用于 cache 的策略有两种: 和 ,前者淘汰最久未被访问的,后者淘汰访问频次最低的;但是这两种淘汰指标在不同场景下各有优势,而且的实现难度比会更高一些(因为要维护频次信息),因此 IBM 提出了兼顾“最近访问”以及“访问频次”的算法,即自适应(Adaptive)置换(Replaceme
在 Java 集合框架中,可能是最容易被轻视,但设计得极其巧妙的一个类。它是HashMap的直接子类,源码量非常少,因为它直接复用了 HashMap 的 90% 以上的代码。在数组+链表/红黑树的基础上,额外增加了一根穿过所有节点的“红线”——双向链表。作为资深开发,你应该在以下场景优先考虑需要保持顺序:比如做 JSON 序列化输出,希望字段顺序和存入顺序一致。缓存失效策略:实现简单的 LRU 缓
摘要: 数据局部性(Data Locality)是影响程序性能的关键因素。CPU 缓存命中率高时(如连续访问 int[]),性能极佳;而频繁指针跳转(如 LinkedList)会导致缓存失效,显著降低效率。优化建议:优先使用原始类型数组(如 int[]),避免装箱类型和链表结构,确保数据连续存储以减少缓存未命中(Cache Miss)。核心原则:减少指针追踪(Pointer Chasing),提升
如果你想找第 100 个元素,Java 会先看一共多少人。这意味着它既能当队列用(先进先出),也能当栈用(先进后出)。:手里有两张纸条,一张写着“下一站”,一张写着“上一站”。造一个新节点,让它的 next 指向 oldFirst。每个盒子要装三样东西:数据、前面的地址、后面的地址。把公司的“门牌号”(first)挂在新人头上。遍历链表,找到第一个匹配的元素并解除链接。:最后一个人手里拿着指向第一
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstIn First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front):是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。栈结构简单、操作高效,入栈和出栈都只在栈顶进行,时间复杂度为 O(1),存取速度
/ 添加元素articles.add("Java入门");articles.add("ArrayList实战");articles.add("LinkedList深入解析");// 遍历// 在开头/结尾添加articles.addFirst("面向对象基础");articles.addLast("集合实战");System.out.println("添加首尾元素后:" + articles);/
分阶段处理:将复杂问题拆分为“构建结构”和“处理随机指针”两个阶段,降低思考难度。哈希表的作用:通过map2建立原节点到新节点的快速查找,解决了random指向“未知节点”的问题。虚拟头节点的使用:简化了新链表next指针的构建,避免了单独处理第一个节点的特殊逻辑。空指针处理:注意random可能为null,代码中需要显式判断,避免空指针异常。
Redis快速链表(QuickList)是一种结合双向链表和压缩列表优点的列表实现结构。它通过分块存储(将大列表分割为多个小压缩列表节点)和可配置的压缩机制,在内存效率和操作性能间取得平衡。相比纯双向链表可减少50%-80%内存使用,同时避免压缩列表的连锁更新问题。支持O(1)复杂度的头尾操作,并通过节点元素计数优化索引查找。通过list-max-ziplist-size和list-compres
JDK 7:分段锁 (Segment)。问题:如果哈希函数设计不佳,或者攻击者构造大量哈希冲突的 SKU ID(例如利用 String.hashCode() 的碰撞特性),导致某个 Bucket 下的链表长度达到几千。未优化前 (JDK 7):每次 get() 商品都要遍历几千个节点,O(n) 复杂度导致 CPU 飙升,接口响应从 2ms 变 2s,甚至线程阻塞,引发雪崩。在无法完全避免哈希冲突(
之所以选择 8 而不是更小的数字,是因为红黑树虽然查询效率高(O(log n)),但它的节点占用内存是普通链表节点的两倍,而且维护树结构(旋转、变色)也有额外开销。这就是链表的基础结构。两个线程同时执行 put 操作,如果它们的 key 映射到同一个桶,且桶为空,两个线程都判断桶为空并各自创建节点,最终只有一个节点会被保留,另一个被覆盖,导致数据丢失。JDK 8 在这里做了一个巧妙的优化:由于容量
ConcurrentHashMap 不一开始就用红黑树,而是采用链表长度超过阈值才转换的策略。
本文将深入解析Netty框架的核心组件——ChannelPipeline。ChannelPipeline通过拦截过滤器模式,为网络事件处理构建了一条可插拔的双向处理链,如同数据流动的“高速公路”。文章详细剖析了其基于双向链表的底层结构、入站与出站处理器的分工、事件传播机制以及线程安全的动态管理。同时,提供了从异常处理、性能优化到调试监控的完整实战指南,并总结了保持处理器轻量、正确传播事件、合理排序
选择ArrayList的情况需要频繁随机访问元素数据量相对稳定,或可预估主要在尾部进行插入删除操作内存空间有限选择LinkedList的情况需要频繁在任意位置插入删除元素不需要频繁随机访问数据量变化较大,无法预估需要实现队列、双端队列等数据结构LinkedList作为Java集合框架中与ArrayList互补的数据结构,通过链式存储解决了ArrayList在频繁插入删除时的性能问题。理解其双向链表
底层自带HashMap + 双向链表构造器第三个参数 accessOrder=true开启 LRU 访问排序重写,判断容量超限自动删最久未使用所以代码极简,是 Java 最快写出来的标准 LRU。
摘要: 本文深入剖析Linux内核中复杂数据结构的设计哲学,重点解析链表、红黑树和XArray的实现策略。内核拒绝传统抽象数据类型(ADT),强调细节可见性以优化性能,如链表采用嵌入式锚点设计,红黑树仅提供核心算法而将搜索逻辑开放给开发者。XArray作为革新性结构,以数组接口简化树形操作,集成RCU锁和自动内存管理。文章总结出五大内核设计模式,包括嵌入式锚点、宽接口和工具箱等,并探讨了XArra
面试官:“手写一个LRU缓存。你心里一喜,LeetCode 146刚刷过,一行搞定。面试官:“如果让你手撕双向链表呢?你开始冒汗。面试官:“那你知道Caffeine的W-TinyLFU吗?和LRU有什么不同?你沉默了。这篇文章,就是帮你把这中间的坑填上。从面试题到工业实现,咱们一层层扒开看。场景推荐方案单机应用、通用场景Caffeine(命中率、性能都是天花板)需要持久化、集群RedisAndro
1. 哈希表每个桶数据相互独立,修改单个桶无需锁住其他位置2. 一条链表全部节点都挂载在头节点,锁首节点 = 锁住整条链表3. 锁粒度压缩到最小,大幅度减少多线程锁竞争4. 多桶可以并行操作,整体并发吞吐量大幅提升5. 配合 CAS 无锁机制,尽量少加锁;同时依托 synchronized 锁升级机制,锁性能更好。
摘要:LeetCode 23题要求合并K个升序链表。最优解法是使用小顶堆(优先队列),时间复杂度O(N log k)。具体步骤:1) 将所有链表头节点入堆;2) 每次取出最小节点拼接到结果链表;3) 若该节点有后继节点则将其入堆。相比暴力两两合并(O(kN))更高效。关键点在于动态维护堆中始终保存各链表当前最小候选节点。Java实现使用PriorityQueue,按节点值排序,空间复杂度O(k)。
add(index, element)方法的源码addFirst()方法的源码addLast()方法的源码LinkedList可以作为一个队列来使用offer() == add(),就是在队列尾部入队,将一个元素插入队列尾部,offerFirst(),offerLast()poll(),从队列头部出队peek(),获取队列头部的元素,但是头部的元素不出队
可惜这一点在ListDictionary中并没有体现,每次添加数据,ListDictionary都要遍历整个链表,来确保没有重复节点,导致每次添加都要循环一次,添加数据的时间复杂度和查询数据的时间复杂度都为O(n),比线性表和哈希表要慢的多。除了节省内存空间外,链表的另一个优点--插入数据的灵活性,在LinkedList<T>中完全体现出来,共有4个不同位置的添加数据的方法,分别为链头插入,链尾插
从一名初学者的视角 带你了解我在学习链表过程中的困惑与思考有问题希望大家可以多多指出~
链表
——链表
联系我们(工作时间:8:30-22:00)
400-660-0108 kefu@csdn.net