链表
链表也是一种线性表,与数组的区别是链表的内存结构不是连续的内存空间,是将一组零散的内存块串联起来来存储数据的数据结构。
常见的链表有单链表、双向链表、循环链表。
单链表
链表通过指针将一组零散的内存块串联起来,我们将内存块称作“结点”,每一个结点上除了存储数据以外都还记录着下一个结点的地址,把记录下一个结点地址的指针叫作后继指针next
由图可以看出,头结点和尾结点很特殊,因为头结点记录着基地址,有了头结点就能很容易遍历出整条链表。而尾节点的指针最后是指向一个空地址NULL。
插入和删除:链表中插入或者删除一个数据,不会像数组一样为了保证内存的连续性而搬移结点,因为链表的存储空间本身就不是连续的。所以,在链表中插入和删除一个数据是非常快的。
如下图:
由此可以得出,插入和删除的时间复杂度O(1),但是随机访问的效率低,不能像数组一样可以根据首地址和下标来查询,需要一个一个的寻址遍历,所以时间复杂度就是O(n)
循环链表
循环链表的尾节点直接指向了头结点,所以在处理环型数据结构的场景时,循环链表很适合。(如约瑟夫问题)
双向链表
双向链表的结点上除了数据之外,还有两个指针分别指向前一个结点的地址(前驱指针prev)和下一个结点地址(后继指针next)。
首结点的前驱指针prev和尾节点的后继指针next均指向空地址。
双向循环链表
首结点的前驱指针prev指向尾结点data,尾结点的后继指针next指向首结点data
总结
数组的插入和删除时间复杂度O(n)、随机访问O(1)
链表的插入和删除时间复杂度O(1)、随机访问O(n)