发布时间:2022-08-18 18:57
是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度。
链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。
一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。
单向链表是一种线性表,实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。其数据在内存中存储是不连续的,它存储的数据分散在内存中,每个结点只能也只有它能知道下一个结点的存储位置。由N各节点(Node)组成单向链表,每一个Node记录本Node的数据及下一个Node。向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的。
一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个连接:一个指向前一个节点,(当此“连接”为第一个“连接”时,指向空值或者空列表);而另一个指向下一个节点,(当此“连接”为最后一个“连接”时,指向空值或者空列表)
一个双向链表有三个整数值: 数值, 向后的节点链接, 向前的节点链接
在一个 循环链表中, 首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,你开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。再来看另一种方法,循环链表可以被视为“无头无尾”。这种列表很利于节约数据存储缓存, 假定你在一个列表中有一个对象并且希望所有其他对象迭代在一个非特殊的排列下。
指向整个列表的指针可以被称作访问指针。
Java中的链表都是双向链表,相关的实现类有LinkedList:
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
由于LinkedList实现了Deque和Queue接口,可以按照队列、栈和双端队列的方式进行操作:
LinkedList作为队列:
1、在尾部添加元素 (add, offer):
add()会在长度不够时抛出异常:IllegalStateException; offer()则不会,只返回false
2、查看头部元素 (element, peek),返回头部元素,但不改变队列
element()会在没元素时抛出异常:NoSuchElementException; peek()返回null;
3、删除头部元素 (remove, poll),返回头部元素,并且从队列中删除
remove()会在没元素时抛出异常:NoSuchElementException; poll()返回null;
LinkedList作为双端队列:
LinkedList作为栈:
操作一个链表只需要知道它的头指针就可以做任何操作了。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
1、链表的反转:(迭代法)
public ListNode reverseList(ListNode head) {
if(head==null || head.next==null) return head;
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
复杂度分析