什么是链表
链表图示
使用链表增删改查
图示
代码实现
public class LinkedList<E> {private class Node{public E e;public Node next;public Node(E e,Node next){this.e = e;this.next = next;}public Node(E e){this(e,null);}public Node(){this(null,null);}@Overridepublic String toString() {return e.toString();}}private Node dummyHead;private int size;public LinkedList(){dummyHead = new Node(null,null);size = 0;}public boolean isEmpty(){return size == 0;}//在链表的index位置添加新的元素e//在链表中不是一个常用的操作,仅用于学习使用public void add(int index,E e){if (index < 0 || index>size){throw new IllegalArgumentException("Add Failed. Illegal index");}//使用dummyHead头节点之后就不用再就行判断是否插入位置是0的顾虑了Node prev = dummyHead;for (int i = 0; i < index; i++) {prev = prev.next;}//Node node = new Node(e);//node.next = prev.next;//prev.next = node;prev.next = new Node(e,prev.next);size++;}//在链表头添加新的元素public void addFirst(E e){//Node node = new Node(e);//node.next = head;//head = node;add(0,e);}//在链表末尾添加新的元素public void addLast(E e){add(size,e);}//获得链表的第index个位置的元素//在链表中不是一个常用的操作,仅是练习使用public E get(int index){if (index < 0 || index >= size){throw new IllegalArgumentException("Get Failed . Illegal index");}Node cur = dummyHead.next; //这次得到的是头节点for (int i = 0; i < index; i++) {cur = cur.next;}return cur.e;}//获得链表的第一个元素public E getFirst(){return get(0);}//获得链表的最后一个元素public E getLast(){return get(size);}//修改链表中的第index个元素public void set(int index,E e){if (index < 0 || index >= size){throw new IllegalArgumentException("Set Failed. Illegal index");}Node cur = dummyHead.next;for (int i = 0; i < index; i++) {cur = cur.next;}cur.e = e;}//查找链表是否含有元素epublic boolean contains(E e){Node cur = dummyHead.next;while (cur != null){if (cur.e.equals(e)){return true;}cur = cur.next;}return false;}//从列表中删除index位置的元素,返回删除的元素public E remove(int index){if (index < 0 || index >= size){throw new IllegalArgumentException("Remove Failed . Illegal index");}Node prev = dummyHead;for (int i = 0; i < index; i++) {prev = prev.next;}Node retNode = prev.next;prev.next = retNode.next;retNode.next = null;size--;return retNode.e;}//从链表中删除第一个元素,返回删除第一个元素public E removeFirst(){return remove(0);}//从链表中删除最后一个元素public E removeLast(){return remove(size-1);}public int getSize(){return size;}@Overridepublic String toString() {StringBuffer res = new StringBuffer();Node cur = dummyHead.next;while (cur!=null){res.append(cur+"->");cur = cur.next;}res.append("NULL");return res.toString();}}
使用链表的虚拟头节点(dummyHead)

为什么要设立dummyHead?
- 当实行插入操作时,使用dummyHead头节点就不需要再判断插入位置是0的顾虑了
- 遍历操作index次时,就遍历index次,而不需要遍历index-1

链表实现栈
链表头作为栈顶
public class LinkedListForStack<E> implements Stack<E> {LinkedList<E> stack;public LinkedListForStack() {stack = new LinkedList<>();}@Overridepublic int getSize() {return stack.getSize();}@Overridepublic boolean isEmpty() {return stack.isEmpty();}@Overridepublic void push(E e) {stack.addFirst(e);}@Overridepublic E pop() {return stack.removeFirst();}@Overridepublic E peek() {return stack.getFirst();}@Overridepublic String toString() {final StringBuffer sb = new StringBuffer("stack top");sb.append(stack);return sb.toString();}}
带有尾指针的链表
- 可以用来实现链表队列
```java
public class LinkedListForQueue
implements Queue {
private class Node{public E e;public Node next;public Node(E e, Node next){this.e = e;this.next = next;}public Node(E e){this(e,null);}public Node(){this(null,null);}@Overridepublic String toString() {return e.toString();}}private Node head,tail;private int size;@Overridepublic int getSize() {return size;}@Overridepublic boolean isEmpty() {return size==0;}@Overridepublic void enqueue(E e) {if (tail == null){tail = new Node(e);head =tail;}else {tail.next = new Node(e);tail = tail.next;}size++;}@Overridepublic E dequeue(E e) {if (isEmpty()){throw new IllegalArgumentException("Cannot dequeue from an empty queue");}Node retNode = head;head = head.next;retNode.next = null;if (head == null){tail = null;}size--;return retNode.e;}@Overridepublic E getFront() {if (isEmpty()){throw new IllegalArgumentException("Cannot getFront from an empty queue");}return head.e;}@Overridepublic String toString() {final StringBuffer sb = new StringBuffer("Queue front{");Node cur = head;while (cur != null){sb.append(cur+"->");cur = cur.next;}sb.append("null} tail" );return sb.toString();}
}
<a name="TlfkY"></a># 链表的复杂度分析- 增 : O(n) , 如果是在表头添加,则是O(1)- 删 : O(n) , 如果是表头也是O(1)- 改 : O(n)- 查 : O(n)<a name="HEaRL"></a># 链表相关问题<a name="Y6tMN"></a>## 第一个很好的用到了dummyHead好处的例子:移除链表元素- LeetCode203<a name="AwIof"></a>## 反转链表- 图示:- 当使用递归时:<a name="hIbfB"></a># 递归问题<a name="pqIxu"></a>## 使用递归实现了链表```javapublic class RecursionForLinkedList<E> {private class Node{public E e;public Node next;public Node(E e, Node next){this.e = e;this.next = next;}public Node(E e){this(e,null);}public Node(){this(null,null);}@Overridepublic String toString() {return e.toString();}}private Node head;private int size;public RecursionForLinkedList() {head = null;size = 0;}public boolean isEmpty(){return size == 0;}public int getSize(){return size;}public void add(int index , E e){if (index < 0 || index>size){throw new IllegalArgumentException("Add Failed. Illegal index");}head = add(head,index,e);size++;}private Node add(Node node,int index,E e){if (index == 0){return new Node(e,node);}node.next = add(node.next,index-1,e);return node;}/*** 在链表头添加新的元素*/private void addFirst(E e){add(0,e);}/*** 在链表末尾添加新的元素*/private void addLast(E e){add(size,e);}/*** 获得链表第index个位置的值*/public E get(int index){if (index < 0 || index >= size){throw new IllegalArgumentException("Get Failed . Illegal index");}return get(head,index);}private E get(Node node,int index){if (index < 0 || index >= size){throw new IllegalArgumentException("Get Failed . Illegal index");}if (index == 0){return node.e;}return get(node.next,index-1);}/*** 获得链表的第一个元素*/private E getFirst(){return get(0);}/*** 获得最后一个元素*/private E getLast(){return get(size);}/*** 修改第index个位置的元素*/public void set(int index,E e){set(head,index,e);}private void set(Node node,int index,E e){if (index < 0 || index >= size){throw new IllegalArgumentException("Set Failed. Illegal index");}if (index == 0){node.e = e;}set(node.next,index-1,e);}/*** 查找链表是否存在某个元素*/public boolean contains(E e){return contains(head,e);}private boolean contains(Node node,E e){if (node == null){return false;}if (node.e.equals(e)){return true;}return contains(node.next,e);}/*** 在链表中删除某个元素,并返回删除的元素*/public E remove(int index){if (index < 0 || index >= size){throw new IllegalArgumentException("Remove Failed. Illegal index");}Pair<Node,E> res = remove(head,index);size--;head = res.getKey();return res.getValue();}private Pair<Node,E> remove(Node node, int index){if (index == 0){return new Pair<>(node.next,node.e);}Pair<Node, E> res = remove(node.next, index - 1);node.next = res.getKey();return new Pair<>(node,res.getValue());}// 从链表中删除第一个元素, 返回删除的元素public E removeFirst(){ return remove(0); }// 从链表中删除最后一个元素, 返回删除的元素public E removeLast(){ return remove(size - 1); }//从链表中删除元素epublic void removeElement(E e){removeElement(head,e);}private void removeElement(Node node,E e){if (node == null){return;}if (node.next.e.equals(e)){node.next = node.next.next;}else {removeElement(node.next,e);}}@Overridepublic String toString() {StringBuilder res = new StringBuilder();Node cur = head;while (cur != null) {res.append(cur + "->");cur = cur.next;}res.append("NULL");return res.toString();}public static void main(String[] args) {RecursionForLinkedList<Integer> list = new RecursionForLinkedList<>();for (int i = 0; i < 10; i++) list.addFirst(i);System.out.println(list);list.removeElement(3);System.out.println(list);}}
