有序插入时,数组与链表效率比较

绝对不是。这确实让人很不理解,毕竟为了将某元素插入到数组合适的地方,需要将此地方及以后的元素都要向后平移,而对链表来说,简单地新申请一个节点和改变两个指针变量的值即可,甚至,我们还可以预先一次性申请一堆节点。但是Programming Pearls(英文版第2版)第137页列出一张表,证实情况不那么简单

表列出数据表明了向相应数据结构中插入m个0~n(n = 1,000,000)之间的随机数的耗时情况。表中的简单链表指插入元素时采用递归,并且每次只申请一个节点空间;无递归链表去掉递归,采用循环;组空间申请指一次性申请m个节点空间

 

数组结构

问题规模(m)

10,000

20,000

40,000

数组

0.6

2.6

11.1

简单链表

5.7

31.2

170.0

无递归链表

1.8

12.6

73.8

组空间申请链表

1.2

5.7

25.4

 

    由图可以看出,即使是链表采用了组空间申请这样精巧的技术,速度仍然比数组慢一倍!这与我们“当有频繁的插入操作时最好采用链表结构”的常识完全相反。用John Bentley的话说,“something was wrong”。下面是他的分析。

 

    “我首先认为(链表比数组慢)是因为递归太耗时,...,改为循环之后时间下降了将近三倍。然后我的反应是将内存申请策略改为一次申请m个节点。这样有两个显著的改进:a)内存申请操作耗时比最简单内存操作多出大约二个数量级,b)当一次性为若干节点申请一块内存时,每个节点只有8字节(4个字节存储整数,4字节存储指向下一节点的指针),于是40,000个节点消耗320k内存,这完全可放入二级缓存;而一次申请一块时每个节点占用48字节,总共消耗1.9M(比他的二级缓存大)。... 对于数组和链表,要插入一个元素,首先要找到该元素应该插入的位置,这必然是一个线性过程;不同的是接下来,数组需要将该位置及以后的元素向后移动,而链接不会,那为什么链表反而更耗时?部分原因是链表占用至少2倍的内存空间:它需要将8字节读入缓存以获取4字节的整数。另一个原因是数组的内存是连续的,访问其元素有很好的可预测性,而链表需要满内存地跳来跳去。”


我觉得,上面的分析任然有很大的局限性,因为上面的例子,默认存储的是一个4byte的整数,但是如果我们将要存储的数据换成一个结构体的时候,上面的测试数据可能就不存在有效性了。一切取决于实际应用。在选择数组或链表的时候,根据实际情况合理选择,最好预先做相应的测试,根据实际结果选择。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值