赞
踩
链表也是一种数据结构,相比较于数组,略显复杂。链表和数组都是非常基础、非常常用的数据结构。
从底层的存储结构上看,二者申请的内存空间不一样:
数组需要一块连续的内存空间来存储,对内存要求较高。
链表不需要一块连续的内存空间,它通过"指针"将一组零散的内存块串联起来。
例如,当我们申请一个100MB大小的数组,当内存空间中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于100MB,仍然会申请失败。但如果我们申请的是100MB大小的链表时,就可以申请成功。
对比图如下:
链表结构有很多种,但最常见的主要有如下三种:
单链表
双向链表
循环链表
链表通过指针将一组零散的内存块串联在一起,我们将内存块称为链表的“结点”。为了将所有的结点串联在一起,每个链表的结点除了要存储数据之外,还需要记录链上的下一个结点的地址,如下图所示,将记录一个结点地址的指针叫作“后继指针next”。
从上面单链表的图中可以看到有两个结点比较特殊,分别是第一个结点和最后一个结点。我们习惯性的把第一个结点叫作头结点,最后一个结点叫作尾结点。
头结点用来记录链表中的基地址,可以根据头结点遍历得到整个链表。
尾结点的指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。
在链表中进行数据的插入和删除操作要比数组中高效。因为在数组中进行插入、删除操作时,为了保持内存数据的连续性,需要做大量的数据移动,时间复杂度是O(n)。而在链表中存储空间本身就不是连续的,不需要为了保持内存的连续性而移动大量的数据。
为了方便理解,看一张链表中数据插入和删除操作的图:
从图中可以看出,在链表的插入和删除操作中,我们只需要考虑相邻结点的指针改变,所以对应的时间复杂度是O(1)。
链表中数据的插入和删除比数组高效,但当需要随机访问第k个数据时,就没有数组高效。因为链表中的数据不是连续存储的,无法像数组那样,根据首地址和下标,通过寻址公式直接计算出对应的内存地址,而是需要根据指针一个结点一个结点依次遍历,直到找到对应的结点。
循环链表的本质是一种特殊的单链表,与单链表的区别就是在尾结点。单链表中的尾结点指针指向空地址,表示这就是最后的结点。而循环链表的尾结点指针指向链表的头结点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。