链表
- 是一个物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的
- 存储结构(和数组对比)
- 数组需要连续内存
- 链表不需要,也就是不需要整块内存,更适合有很多碎片内存的环境
- 组成:由一个数据域(存储数据元素),一个指针域(存储下一个节点地址)
- 类型
- 单链表
- 每个节点都有一个指向下一个的节点,尾部下一个指向的是null
- 循环链表
- 双向链表
- 每个节点都有两个指针,一个指向下一个节点,一个指向上一个节点,头部的上一个节点为null,尾部的下一个节点为null
- 双向循环链表
- 和数组性能对比
- 网上都说数组的查询快,增删改慢,链表是增删改快,查询慢,但是如果先初始化list的话,越长的新增的话,链表是没有数组快的
public static void main(String[] args) {
long listBefore = System.currentTimeMillis();
doAdd();
long listAfter = System.currentTimeMillis();
System.out.println("list add spend {}"+(listBefore -listAfter));
long linkedBefore = System.currentTimeMillis();
doLinkenAdd();
long linkedAfter = System.currentTimeMillis();
System.out.println("linkd add spend {}"+(linkedBefore -linkedAfter));
}
private static void doLinkenAdd() {
LinkedList<Object> objects = new LinkedList<>();
for(int i =0;i < 10000000 ;i++){
objects.add(i);
}
}
private static void doAdd() {
List list = new ArrayList<>(10000000);
for(int i =0;i < 10000000 ;i++){
list.add(i);
}
}
public class MyLinkedlist<E> {
private Node head;
private Node end;
private int size;
static class Node<E> {
private Node<E> prv;
private Node<E> next;
E node;
public Node() {
}
public Node(Node prv, Node next, E node) {
this.next = next;
this.node = node;
this.prv = prv;
}
}
public void add(E e) {
if (head == null && end == null) {
Node node = new Node<>(null, null, e);
end = node;
head = node;
} else {
//如果里面已经有数据的情况下,就只需要将自己挂在尾部
Node<E> eNode = new Node<>(end, null, e);
end.next = eNode;
end = eNode;
}
size++;
}
public void remove(E e) {
Node first = head;
for (int i = 0; i < size; i++) {
if (first.node.equals(e)) {
removeNode(first);
} else {
first = first.next;
}
}
}
private void removeNode(Node first) {
//判断是否只剩下一个节点
if (size > 1) {
//判断是否首尾节点,首节点的话,只需要把下一个节点的前置索引设置为null,再把head更新下
if (first.prv == null) {
Node node = first.next;
node.prv = null;
this.head = node;
//如果是尾部节点,只需要上一个节点的后置索引设置为null,在把end更新
} else if (first.next == null) {
Node node = first.prv;
node.next = null;
end = node;
//如果是中间节点,取前后两节点,相互建立关联
} else {
Node prvNode = first.prv;
Node nextNode = first.next;
prvNode.next = nextNode;
nextNode.prv = nextNode;
}
}else{
head = null;
end = null;
}
size -- ;
}
}