数组实现的有序double link list头尾间插入元素搜索迭代优化咨询
已知数值范围的优化价值
已知数值范围可以极大降低遍历次数,最直接的方案是建立区间索引(桶索引):
- 基于数值范围划分固定大小的区间,比如数值范围为
[0, 100000]时,可以每100个数值划分为一个桶,创建一个桶数组,每个位置存储对应区间内的链表节点指针 - 插入新值时直接计算新值所属的桶下标,从桶存储的节点开始遍历,最多仅需遍历一个区间内的节点,遍历次数直接从O(n)降到O(区间大小),如果数值范围足够小,甚至可以建立数值到节点的一对一索引,实现O(1)定位插入位置
其他通用优化方案
维护动态索引数组
你本身用数组实现双向链表,可以额外维护一个有序的索引数组,存储各节点在数组中的下标,值和链表节点值一一对应。插入新节点时先对索引数组做二分查找,O(logn)就能找到插入位置对应的前驱节点下标,之后直接操作双向链表的前后指针即可,改造成本极低,对长链表的优化效果非常明显。改造为跳表结构
在现有双向链表的基础上新增多层索引层,高层索引的节点步长更大,低层索引步长依次缩小。插入时从最高层索引开始检索,逐步向下层收敛到合适的插入位置,时间复杂度可以稳定在O(logn),远优于现有两端遍历、固定mid检索的O(n)级复杂度,链表越长优化效果越突出。链表分块管理
将整个有序链表拆分为多个固定大小的块(块大小可选32/64,可根据实际场景调整),每个块记录块内最大值、最小值和块首节点指针。插入时先遍历块列表找到符合值范围的目标块,再在块内遍历查找插入位置,整体遍历次数会降低到O(块数量 + 块大小),实现难度比跳表更低。动态维护多阶锚点
不要只维护单个mid节点,可以维护多个均匀分布的锚点(比如1/4、1/2、3/4位置的节点),并且每次插入/删除操作后更新锚点位置。插入新值时先判断新值落在哪个锚点区间,从对应锚点开始遍历,也能直接降低一半以上的遍历次数。热点节点缓存
将最近频繁插入的区间对应的节点缓存下来,插入新值时先判断是否落在缓存的热点区间内,是的话直接从缓存节点开始遍历,适合插入值分布不均匀的场景。
内容的提问来源于stack exchange,提问作者Aval Sarri
相关产品推荐
相关产品推荐

