链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表和双向链表。本文只针对单链表进行说明。一个单链表的节点包含两个值:当前节点的值和指向下一个节点的链接。
基本结构就如上图所示,其中数值 1 所在的节点为链表的头节点,头节点的 value 域存储当前节点的值,next 域存储指向下一个节点的链接。
Java 中 LinkedList 与 ArrayList 类似,是一种常用的数据容器。提供了很多的常用方法:
方法 | 描述 |
---|---|
public boolean add(E e) | 往链表末尾添加元素,即尾插,返回是否成功 |
public void add(int index, E e) | 向指定位置插入指定元素 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表尾部,返回是否成功 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置,返回是否成功 |
public void addFirst(E e) | 将元素添加到链表头部,即头插 |
public void addLast(E e) | 将元素添加到链表尾部,即尾插 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功 |
public void clear() | 清空链表 |
public E removeFirst() | 删除并返回第一个元素 |
public E removeLast() | 删除并返回最后一个元素 |
public boolean remove(E e) | 删除指定元素,返回是否成功 |
public E remove(int index) | 删除指定位置的元素 |
public E poll() | 删除并返回第一个元素 |
public E remove() | 删除并返回第一个元素 |
public boolean contains(E e) | 判断链表中是否包含指定元素 |
public E get(int index) | 获取指定位置的元素 |
public E getFirst() | 获取第一个元素 |
public E getLast() | 获取最后一个元素 |
public int indexOf(E e) | 查找指定元素在链表中第一次出现的位置索引 |
public int lastIndexOf(E e) | 查找指定元素在链表中最后一次出现的位置索引 |
public E peek() | 获取第一个元素 |
public E element() | 获取第一个元素 |
public E peekFirst() | 获取头部元素 |
public E peekLast() | 获取尾部元素 |
public E set(int index, E e) | 设置指定位置的元素 |
public Object clone() | 复制该链表 |
public Iterator descendingIterator() | 返回倒序迭代器 |
public int size() | 获取链表元素个数 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组 |
public Object[] toArray() | 返回一个由链表元素组成的数组 |
其中有些获取元素、删除元素的方法我们在平时使用过程中并不会用到。
代码示例:
public static void main(String[] args) {
List<Integer> list = new ArrayList() {{
add(1);
add(4);
add(7);
add(2);
add(5);
add(8);
}};
LinkedList linkedList = new LinkedList();
// 将集合的所有元素添加到链表尾部
linkedList.addAll(list);
System.out.println("链表初始化:" + linkedList);
// 向链表的头部插入元素 0
linkedList.addFirst(0);
System.out.println("头插元素0之后的链表为:" + linkedList);
// 向链表的尾部插入元素 11
linkedList.addLast(11);
System.out.println("尾插元素11之后的链表为:" + linkedList);
// 向链表的下标为 5 的位置插入元素 15
linkedList.add(5, 15);
System.out.println("指定位置插入元素15之后的链表为:" + linkedList);
// 判断链表中是否包含元素15
System.out.println("链表中是否包含元素15:" + linkedList.contains(15));
// 获取链表中元素的个数
System.out.println("该链表中元素的个数为:" + linkedList.size());
// 获取链表头部元素
System.out.println("链表头部元素为:" + linkedList.getFirst());
// 获取链表尾部元素
System.out.println("链表尾部元素为:" + linkedList.getLast());
}
执行结果为:
一般来说,常用的方法就只有获取元素、计算元素个数、插入元素等。
自定义实现链表代码如下:
package com.xyy.insurance.web.service.impl;
/**
* @ClassName: LinkedList
* @Author: jiaoxian
* @Date: 2021/9/8 16:00
* @Description:
*/
public class LinkedList<Data> {
/**
* 头结点
*/
private ListNode head;
/**
* 链表元素个数
*/
private int size;
public class ListNode {
// 当前节点的值
private Data value;
// 指向下一个节点的链接
private ListNode next;
public ListNode(Data value, ListNode next) {
this.value = value;
this.next = next;
}
public ListNode(Data value) {
this(value, null);
}
public ListNode() {
this(null, null);
}
}
/**
* 无参构造函数
*/
public LinkedList() {
this.head = null;
this.size = 0;
}
/**
* 有参构造函数
* @param size
*/
public LinkedList(int size) {
this.head = null;
this.size = size;
}
/**
* 获取链表元素的个数
* @return
*/
public int getSize() {
return this.size;
}
/**
* 判断链表是否为空
* @return
*/
public boolean isEmpty() {
return this.size == 0;
}
/**
* 往链表头部添加元素
* @param value
*/
public void addFirst(Data value) {
// 要插入的节点对象
ListNode node = new ListNode(value);
node.next = this.head;
this.head = node;
this.size++;
}
/**
* 向链表尾部插入元素
* @param value
*/
public void addLast(Data value) {
this.add(value, this.size);
}
/**
* 在指定位置插入元素
* @param value
* @param index
*/
public void add(Data value, int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is error");
}
if (index == 0) {
this.addFirst(value);
return;
}
ListNode preNode = this.head;
// 找到要插入节点的前一个节点
for (int i = 0; i < index - 1; i++) {
preNode = preNode.next;
}
// 待插入的节点对象
ListNode node = new ListNode(value);
// 要插入的节点的下一个节点指向 preNode 节点的下一个节点
node.next = preNode.next;
// preNode 的下一个节点指向要插入节点
preNode.next = node;
this.size++;
}
/**
* 删除链表元素
* @param value
*/
public void remove(Data value) {
if (head == null) {
System.out.println("无元素可删除");
return;
}
// 要删除的元素与头结点的元素相同
while (head != null && head.value.equals(value)) {
head = head.next;
this.size--;
}
ListNode cur = this.head;
while (cur != null && cur.next != null) {
if (cur.next.value.equals(value)) {
this.size--;
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
}
/**
* 删除链表第一个元素
* @return
*/
public Data removeFirst() {
if (this.head == null) {
System.out.println("无元素可删除");
return null;
}
ListNode delNode = this.head;
this.head = this.head.next;
delNode.next = null;
this.size--;
return delNode.value;
}
/**
* 删除链表的最后一个元素
* @return
*/
public Data removeLast() {
if (this.head == null) {
System.out.println("无元素可删除");
return null;
}
// 只有一个元素时
if (this.getSize() == 1) {
return this.removeFirst();
}
// 记录当前结点
ListNode cur = this.head;
// 记录要删除结点的前一个结点
ListNode pre = this.head;
while (cur.next != null) {
pre = cur;
cur = cur.next;
}
pre.next = cur.next;
this.size--;
return cur.value;
}
/**
* 判断链表中是否包含某个元素
* @param value
* @return
*/
public boolean contains(Data value) {
ListNode cur = this.head;
while (cur != null) {
if (cur.value.equals(value)) {
return true;
} else {
cur = cur.next;
}
}
return false;
}
/**
* 链表元素打印
*/
public void display(){
if (head == null) {
System.out.println("empty");
} else {
ListNode cur = head;
while (cur.next != null) {
System.out.print(cur.value + " -> ");
cur = cur.next;
}
System.out.println(cur.value);
}
}
public LinkedList mergeTwoLists(LinkedList linkedList1, LinkedList linkedList2) {
LinkedList linkedList = new LinkedList();
ListNode cur = linkedList.head;
ListNode listNode1 = linkedList1.head;
ListNode listNode2 = linkedList2.head;
while (listNode1 != null && listNode2 != null) {
if ((Integer) listNode1.value < (Integer) listNode2.value) {
cur.next = listNode1;
cur = cur.next;
listNode1 = listNode1.next;
linkedList1.head = listNode1;
} else {
cur.next = listNode2;
cur = cur.next;
listNode2 = listNode2.next;
linkedList2.head = listNode2;
}
}
if (linkedList1 == null) {
linkedList = linkedList2;
} else {
linkedList = linkedList1;
}
return linkedList;
}
public static void main(String[] args) {
LinkedList linkedList1 = new LinkedList();
linkedList1.addFirst(3);
linkedList1.addFirst(2);
linkedList1.addFirst(1);
System.out.println("linkedList1 = " + linkedList1.getSize());
linkedList1.display();
LinkedList linkedList2 = new LinkedList();
linkedList2.addLast(4);
linkedList2.addLast(5);
linkedList2.addLast(6);
System.out.println("linkedList2 = " + linkedList2.getSize());
linkedList2.display();
LinkedList linkedList = new LinkedList();
linkedList = linkedList.mergeTwoLists(linkedList1, linkedList2);
linkedList.display();
// linkedList.addLast(33);
// linkedList.addFirst(33);
// linkedList.add(33, 5);
// System.out.println(linkedList);
// linkedList.remove(33);
// System.out.println(linkedList);
// System.out.println("删除第一个元素:" + linkedList.removeFirst());
// System.out.println(linkedList);
// System.out.println("删除最后一个元素:" + linkedList.removeLast());
// System.out.println(linkedList);
}
}