什么是链表 Linked list
链表是一种与数组类似的数据结构,数组的每个元素是存储在特定的位置或索引中,链表的每个元素都是独立的对象,但是的每一个数据都有一个指向下一个对象的指针。所以链表有两个重要的点,一个是数据,一个是指针。
可能不好理解,给大家举个例子吧。数组就是一个固定大小的车厢/教室(arr
),里面每一个元素(item
座位)是固定的,每个座位上有固定的位置( 索引 ),链表类似于火车;有一个火车头(head
),火车头的钩子会连接(指针next
)下一个车厢(节点),每个车厢都有一个钩子会连接下一个车厢,每个车厢的位置是任意的,谁先谁后无所谓,以此类推....
链表的结构可以有很多种,比方说单向链表或双向链表,也可以是已排序、未排序、环形的、或非环形等。
链表和数组的区别
链表的特点
就如我刚刚举的例子
- 链表中各节点在内存中的存放位置是任意的,不要求连续
- 每一个节点都保存了下一个节点的内存地址
- 查找数据时效率低
==>
由于第一点,就决定了他不能通过数组一样arr[index]
来查找元素,也就是不具有随机访问性。但是他每个节点都有一个指向下一个节点的链接(next
),所以查找元素需要一个个挨次挨次去找 - 增加数据和删除数据很容易
==>
还是由于第一点,增加数据和删除数据它就很容易,来一节车厢可以随便加,比如加到第三个位置,那他只需要把自己的头挂到第二个车厢的钩子上(第二元素的next指向自己
),然后尾巴的钩子挂住原来第三车厢就行了(自己的next指向原来的第三元素
),其他人都不用操作。删除也是同理可证 - 不指定大小,扩展方便,链表大小不用定义,数据随意增删。就像火车,货物多你可以临时多挂几节车厢,货物少你可以少挂几节。
数组的特点
- 在内存中,数组是一块连续的区域
==>
固定大小的教室 - 数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间。
==>
教室在制造时就预计要搞多少座位,也就是使用前需要提前申请所占内存的大小,这样不知道需要多大的空间,就预先申请可能会浪费内存空间,所以数组空间利用率低 - 增加数据和删除数据效率低
==>
教室的每个座位位置是固定的,座位还有编号,插入/删除数据时,这个位置前后面的数据在内存中都要向前/后移。 - 查找数据时效率高
==>
可以直接根据编号来找位置,就像arr[index]
,随机读取效率很高 - 不利于扩展
==>
教室座位不够坐不下就麻烦,需要走出去重新找一个大教室,数组开辟的空间,在不够使用的时候需要扩容,扩容的话,就会涉及到需要把旧数组中的所有元素向新数组中迁移
所以呀,总结一下就是
数组中的元素顺序关系由元素由索引体现,链表中的结点顺序关系由指针来体现; 数组大小固定,不能动态扩展;但是链表可以进行动态增删。
- 数组:查找快,增删慢
- 链表:增删快,查找慢
- 数组的内存在数组定义时分配,因此元素个数是固定的
- 链表节点的内存在程序执行时动态向系统申请,因此链表节点个数可按照需要动态增减
- 数组中的元素顺序关系由元素索引体现
- 链表中的节点顺序关系由指针来体现