锯齿数组也是随机存储结构吗?

2019-10-01 14:24:40 +08:00
 asiufasd

我知道因为数组的内存中连续和等分的特点,所以对于任意一个二维数组int[][]
LOC(i,j)=LOC(0,0) + (b*i + j)L
LOC(0,0)是该二维数组的起始存储位置,b 是每行的长度,L 是每个数据元素的宽度
所以 get 和 set 的时间复杂度是一个常数时间 O(1)

但是对于锯齿数组

int[][] ja = new int[4][];  
ja[0] = new int[6];
ja[1] = new int[4];
ja[2] = new int[4];
ja[3] = new int[5];

第二维度的长度并不固定,如果要计算出 LOC(i,j)是不是需要通过 sum 确定偏移量
这样对于锯齿数组的 get 和 set 是不是 O(i-1)?

1868 次点击
所在节点    问与答
8 条回复
xenme
2019-10-01 14:29:22 +08:00
数组里面存不定长数组的地址
等于取两次地址

或者长度变化不大的,按最大长度指定。变成普通数组
xupefei
2019-10-01 14:37:22 +08:00
get 在最坏情况下需要 sum 所有的行,所以是 O(i)。
set 在给定坐标的情况下还是 O(1)。
xupefei
2019-10-01 14:46:49 +08:00
@xupefei 哦不,set 也是 O(i)
asiufasd
2019-10-01 14:49:47 +08:00
@xupefei 如果是这样的话,是不是可以说对于锯齿数组,使用链表更加合适
xupefei
2019-10-01 15:04:03 +08:00
@asiufasd 你指的是把第一层指针换成链表还是把所有数组都换成链表?
无论怎样都不行,因为链表比数组慢很多且不支持随机访问。

最好的办法是像一楼说的那样,变成普通数组。
还有个办法是按长度排序,每 n 行分出一个组,一个组里所有的数组长度等于此组内最长数组的长度。
asiufasd
2019-10-01 15:15:25 +08:00
@xupefei 我是想说既然对于锯齿数组 get 和 set 已经不是 O(1)了,那就失去了数组的随机访问的特性了,相比之下链表还有插入和删除的速度优势。
其实仔细想想可能更想表达的是,对于锯齿数组在内存中的存储结构是怎么样子的,可能确实如一楼所言是数组里面存不定长数组的地址,并不是普通数组那样内存中连续的结构吧。
xupefei
2019-10-01 15:24:51 +08:00
@asiufasd 数组的数组在内存里不连续。在内存里是一个连续的指针数组,其中每个指针指向另一个连续数组。

锯齿数组(数组的数组):访问行是 O(i),访问列是 O(1)。
链表的链表:访问行是 O(i),访问列是 O(i)。
链表的数组:访问行是 O(1),访问列是 O(i)。

如果你有插入需求的话就没得选了,只能链表。
reus
2019-10-01 18:23:36 +08:00
可以加 skiplist 维护偏移量

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/605874

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX