链表
- 链表基本介绍
- 链表与数据结构有些不同。栈和队列都是申请一段连续的空间,然后按顺序存储数据;链表是一种物理上非连续、非顺序的存储结构,数据元素之间的顺序是通过每个元素的指针关联的。
- 链表由一系列节点组成,每个节点一般至少会包含两部分信息:一部分是元素数据本身,另一部分是指向下一个元素地址的指针。这样的存储结构让链表相比其他线性的数据结构来说,操作会复杂一些。
- 与数组相比,链表具有其优势:链表克服了数组需要提前设置长度的缺点,在运行时可以根据需要随意添加元素;计算机的存储空间并不总是连续可用的,而链表可以灵活地使用存储空间,还能更好地对计算机的内存进行动态管理。
- 链表分为两种类型:单向链表和双向链表。我们平时说道的链表指的是单向链表。双向链表的每个节点除存储元素数据本身为,还额外存储两个指针,分别指向上一个节点和下一个节点的地址。
-
单向链表的存储结构图:
从链表的存储结构可知,链表的每个节点包含两个部分,分别是数据(叫做data)和指向下个节点地址的指针(叫做next)。在存储了一个链表之后怎么找到它?这里需要一个头结点,这个头结点是一个链表的第1个节点,它的指针指向下一个节点的地址,以此类推,直到指针指向为空时,便表示没有下一个元素了。 -
下面我们用代码实现一个单向链表
public class Link<E> {
private int size = 0;
private Node<E> first;
public Link() {
}
/**
* 往头节点添加数据
* @param e
*/
public void addFirst(E e) {
Node<E> temp = first;
Node<E> newNode = new Node<>(e,temp);
first = newNode;
size++;
}
public void addLast(E e) {
if (first == null) {
first = new Node<>(e, null);
size++;
return;
}
Node<E> tag = first;
while (true) {
if (tag.next != null) {
// 指针后移
tag = tag.next;
} else {
tag.next = new Node<>(e, null);
size++;
break;
}
}
}
public void print() {
if (first == null) {
System.out.println("链表暂无数据");
}
Node<E> next = first;
while (true) {
if (next == null) {
break;
}
System.out.println(next.item.toString());
next = next.next;
}
}
/**
* 反转链表
*/
public void reverseLink() {
if (first == null || first.next == null) {
return;
}
// 1. 创建一个新的链表,
Node<E> newNode = null;
// 2.从头开始遍历链表,把遍历的每一个元素添加到新链表的头结点处
Node<E> next = first;
while (true) {
if (next == null) {
break;
}
Node<E> temp = newNode;
newNode = new Node<>(next.item, null);
newNode.next = temp;
next = next.next;
}
first = newNode;
}
}
public class Node<E> {
E item;
Node<E> next;
public Node(E element, Node<E> next) {
this.item = element;
this.next = next;
}
}