LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 5750|回复: 18

讨论一下 链表和数组的区别在哪里 !

[复制链接]
发表于 2004-4-2 18:05:16 | 显示全部楼层 |阅读模式
就着个话题!
 楼主| 发表于 2004-4-2 18:18:19 | 显示全部楼层
希望大家踊跃参与!
 楼主| 发表于 2004-4-2 18:19:01 | 显示全部楼层
这是一位人士的讲解:


III.我们需要链表吗
  相信大家在学习《数据结构》的时候,对链表是相当熟悉了,所以我看有人在编写一些耗时算法的时候,也采用了链表的形式。这样编写当然对内存的占用(似乎)少了,可是速度呢?如果你测试:申请并遍历10000个元素链表的时间与遍历相同元素的数组的时间,你就会发现时间相差了百倍!(以前测试过一个算法,用链表是1分钟,用数组是4秒钟)。所以这里我的建议是:在编写耗时大的代码时,尽可能不要采用链表!
  其实实际上采用链表并不能真正节省内存,在编写很多算法的时候,我们是知道要占用多少内存的(至少也知道个大概),那么与其用链表一点点的消耗内存,不如用数组一步就把内存占用。采用链表的形式一定是在元素比较少,或者该部分基本不耗时的情况下。
  (我估计链表主要慢是慢在它是一步步申请内存的,如果能够象数组一样分配一个大内存块的话,应该也不怎么耗时,这个没有具体测试过。仅仅是猜想 )
发表于 2004-4-2 18:42:59 | 显示全部楼层
我认为链表的时间问题不是因为分配内存,而是因为访问内存。数组可以准确的知道它的每一个单元处于什么位置,而链表必须找到上一个元素,才能通过它找到它的后继元素,它的遍历操作比数组要多做几倍的工作。
链表的意义在于处理大型的,未知大小的数据。如果是小型运算,也不必在乎差的那一点内存了。如果你用一个二进制文件来保存一些资料(比如一个通讯薄),使用时取到内存中,进行查找,删除等相关操作,然后写回文件。用数组肯定是不行的,除了直接操作二进制文件,就只有使用链表了。我想,链表应该还是比文件快吧。
 楼主| 发表于 2004-4-2 20:03:53 | 显示全部楼层
cozo 说得好 !

从概念上来看,表是一种抽象数据类型;数组是一种具体的数据结构

从数学性质上来看,表是一个二元关系R,<x,y>∈R 当且仅当x是y的前驱;如果将该二元关系用关系图(将每一个元素用一个点来表示,若x与y有关系则从x到y连一条有向线段)来表示,则得到的是一条单链a1→a2→…→an ,因此表也可以看成是特殊的图或特殊的树(每个节点有且仅有一个子节点);而数组是从1..n的自然数集合到数组元素集合的一一映射,其中n是数组的长度,1..n中每一个自然数唯一地对应着一个数组元素,反之亦然。所以数组可以用来实现映射。


从物理性质来看,数组中相邻的元素是连续地存储在内存中的,或者对于程序员来说可以认为它们是连续地存储在内存中的(比如动态增长的数组实际上并不存储在连续的内存中,但程序员可以认为它存储在连续的内存中),数组的存取对程序员来说是透明的;表只是一个抽象的数学结构,并不具有具体的物理形式,表需要通过其它有具体物理形式的数据结构来实现。在表的具体实现中,表中相邻的元素不一定存储在连续的内存空间中,除非表是用数组来实现的。对于数组,可以利用其下标在一个操作内随机存取任意位置上的元素;对于表,只能根据当前元素找到其前驱或后继,因此要存取第i个位置上的元素,一般不能在一个操作内实现,除非表是用数组实现的。在实现表时需要提供足够的信息以便能够通过表中元素的位置p来存取表中的元素。表中元素的位置p是指示表中元素位置的信息,通过对p进行处理(可能是从事某种函数运算计算出该元素在内存中的位置,也可能从表头开始,依次寻找当前元素的后继,重复i次找到第i个位置的元素)可以得到表中元素在内存中的物理位置,因此不能简单地将位置p理解为类似数组下标的自然数,实际上p可以是各种类型的变量,在数学上可将p定义为一个偏序集上的变量。在具体实现表及其运算时,应区分p与p所表示的位置,以及该位置上的元素三者之间的不同含义。
发表于 2004-4-3 08:46:39 | 显示全部楼层
咦?!!top小兄弟什么时候变得高深起来了,说的都是一套一套的。
个人意见:数据结构中的长期每一种结构都有各自的优点和缺点,采用那一种结构应该由具体需要决定。
 楼主| 发表于 2004-4-4 13:48:13 | 显示全部楼层
呵呵!

我马上要毕业了。

后天去学校面试,一所职业学院本来是想从事开发的

但是人家让我讲课,所以准备了一些东西

害怕这个问题备提到所以来问问大家。
发表于 2004-4-4 17:48:42 | 显示全部楼层
最初由 top 发表
cozo 说得好 !

从概念上来看,表是一种抽象数据类型;数组是一种具体的数据结构

从数学性质上来看,表是一个二元关系R,<x,y>∈R 当且仅当x是y的前驱;如果将该二元关系用关系图(将每一个元素用一个点来表示,若x与y有关系则从x到y连一条有向线段)来表示,则得到的是一条单链a1→a2→…→an ,因此表也可以看成是特殊的图或特殊的树(每个节点有且仅有一个子节点);而数组是从1..n的自然数集合到数组元素集合的一一映射,其中n是数组的长度,1..n中每一个自然数唯一地对应着一个数组元素,反之亦然。所以数组可以用来实现映射。


从物理性质来看,数组中相邻的元素是连续地存储在内存中的,或者对于程序员来说可以认为它们是连续地存储在内存中的(比如动态增长的数组实际上并不存储在连续的内存中,但程序员可以认为它存储在连续的内存中),数组的存取对程序员来说是透明的;表只是一个抽象的数学结构,并不具有具体的物理形式,表需要通过其它有具体物理形式的数据结构来实现。在表的具体实现中,表中相邻的元素不一定存储在连续的内存空间中,除非表是用数组来实现的。对于数组,可以利用其下标在一个操作内随机存取任意位置上的元素;对于表,只能根据当前元素找到其前驱或后继,因此要存取第i个位置上的元素,一般不能在一个操作内实现,除非表是用数组实现的。在实现表时需要提供足够的信息以便能够通过表中元素的位置p来存取表中的元素。表中元素的位置p是指示表中元素位置的信息,通过对p进行处理(可能是从事某种函数运算计算出该元素在内存中的位置,也可能从表头开始,依次寻找当前元素的后继,重复i次找到第i个位置的元素)可以得到表中元素在内存中的物理位置,因此不能简单地将位置p理解为类似数组下标的自然数,实际上p可以是各种类型的变量,在数学上可将p定义为一个偏序集上的变量。在具体实现表及其运算时,应区分p与p所表示的位置,以及该位置上的元素三者之间的不同含义。

首先,先佩服一下你的离散数学水平,我已经望的差不多了。

但是,你不是要比较数组和链表么?这两个都是具体的数据结构的实现,表是数据抽象,和链表根本不是一个层面上的概念,是不应该混淆的。而所谓的动态增长数组,并不能说他是数组中的一种,他和传统的数组也不是一个层面上的概念,按照我的理解,他实际上代表着“基于数组实现的可变长线性表”。

至于链表和数组,只是对于线性表不同的实现罢了,他们可以实现完全相同的功能,但是算法的复杂度是不同的,我想任何一本讲数据结构的书都会对这一点有一个很详细的论述。至于抽象类型和实现的关系,我觉得看一下C++的<vector> <list> <deque>..会有一个很好的了解,它们的接口是类似的,但是对于某个特定的方法,时间复杂度不同,The C++ Programming Language,3/ed 在17.1.2小节有一张表,把这几个标准容器的接口时间复杂度比较的很清楚。

至于那个所谓“专业人士”讲得话,我觉得也没有什么好继续说的了吧。
发表于 2004-4-5 15:32:21 | 显示全部楼层
最初由 top 发表
呵呵!

我马上要毕业了。

后天去学校面试,一所职业学院本来是想从事开发的

但是人家让我讲课,所以准备了一些东西

害怕这个问题备提到所以来问问大家。

不要担心,这种学校不会要求你讲太高深的理论,只是要你多讲讲实用的东西。
发表于 2004-4-5 18:19:12 | 显示全部楼层

链表的优势在于插入和删除啊

rt
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表