牛骨文教育服务平台(让学习变的简单)
博文笔记

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

创建时间:2013-06-13 投稿人: 浏览次数:2194

绝对不是。这确实让人很不理解,毕竟为了将某元素插入到数组合适的地方,需要将此地方及以后的元素都要向后平移,而对链表来说,简单地新申请一个节点和改变两个指针变量的值即可,甚至,我们还可以预先一次性申请一堆节点。但是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的整数,但是如果我们将要存储的数据换成一个结构体的时候,上面的测试数据可能就不存在有效性了。一切取决于实际应用。在选择数组或链表的时候,根据实际情况合理选择,最好预先做相应的测试,根据实际结果选择。

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。