真正的动态数据结构!
概念:
- 是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
- 每个链表都包含多个节点,节点包含两个部分。
- 数据域:存储节点含有的信息。
- 引用域:存储下一个节点或者上一个节点的地址。
特点:
- 获得数据麻烦,需要遍历查找,比数组慢。
- 方便插入、删除。
分类:
- 单向链表
- 双向链表
- 环形链表
- 双向环形链表

优点:
真正的动态,不需要处理固定容量的问题。
缺点:
丧失了随机访问的能力。
实现原理;
- 创建一个节点类。
- 数据域:链表中存储的信息。
- 节点域:相当于指针。单向链表有一个指针,指向下一个节点;双向链表有两个指针,分别指向上一个和下一个。
- 创建一个链表类。
- 头结点
- 为节点
- 大小
单向链表节点类:
public class Node{public Object data;public Node next;public Node(Object o){this.data = o;}}
双向链表节点类:
public class Node{public Object o;public Node next;public Node pre;public Node(Object o){this.o = o;this.next = null;this.next = null;}}
设计一个简单链表
//链表package com.qingFeng;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 int getSize(){return size;}//返回链表是否为空public boolean isEmpty(){return size == 0;}//在链表头添加新的元素epublic void addFirst(E e){/*Node node = new Node(e);node.next = head;head = node;*/add(0,e);}//在链表中间添加元素epublic void add(int index, E e){if (index < 0 || index > size){throw new IllegalArgumentException("add failed. Illegal index.");}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 ++;}//在链表末尾添加新的元素epublic 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 - 1);}//修改链表第index位置的元素为epublic 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. Index is illegal");}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);}@Overridepublic String toString(){StringBuilder res = new StringBuilder();/*Node cur = dummyHead.next;while (cur != null){res.append(cur + "——>");cur = cur.next;}*/for (Node cur = dummyHead.next ; cur != null ; cur = cur.next){res.append(cur + "——>");}res.append("null");return res.toString();}}//客户端package com.qingFeng;public class Main {public static void main(String[] args) {LinkedList<Integer> linkedList = new LinkedList<>();for (int i = 0 ; i < 5 ; i ++){linkedList.addLast(i);}System.out.println(linkedList);linkedList.remove(1);System.out.println(linkedList);linkedList.removeLast();System.out.println(linkedList);}}
