一、线性链表类型
1、单链表:节点只有一个指针域的链表,称为单链表或者线性链表
2、双链表:节点只有两个指针域的链表
3、循环链表:首尾相接的链表
二、单链表
1、头指针,头节点,首元结点
2、单链表的存储结构
三、单链表的基本操作
public class Node {
/**
* 存储节点的值
*/
public User data;
/**
* 存储下一个节点
*/
public Node next;
public Node(User data) {
this.data = data;
}
}
/**
* @ClassName: ListNode
* @Description: LinkListDemo
* @Author: Administrator
* @Date: 2023-03-26 16:17
* @Version:1.0
*/
public class SingleLinkedList {
/**
* 第一个节点
*/
private Node head = new Node(null);
/**
* 记录单链表的长度
*/
private int linkedListSize;
/**
* 头插法
*/
public void addFirst(User user) {
Node currentNode = new Node(user);
if (this.head == null) {
this.head = currentNode;
} else {
currentNode.next = this.head;
this.head = currentNode;
}
linkedListSize++;
}
//尾插法
public void addLast(User data) {
Node node = new Node(data);
if (this.head == null) {
this.head = node;
} else {
Node cur = this.head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
this.linkedListSize++;
}
//打印单链表
public void myToString() {
Node cur = this.head;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(User key) {
Node cur = this.head;
while (cur != null) {
if (cur.data == key) {
return true;
}
cur = cur.next;
}
return false;
}
//得到单链表的长度
public int length() {
Node cur = this.head;
int length = 0;
while (cur != null) {
length++;
cur = cur.next;
}
return length;
}
//寻找待插入位置的前驱结点
public Node getIndex(int pos) {
Node cur = this.head;
int index = 0;
while (index != pos - 1) {
cur = cur.next;
index++;
}
return cur;
}
//任意位置插入,第一个数据节点为0号下标
public void insert(int pos, User data) {
if (pos < 0 || pos > this.linkedListSize) {
throw new RuntimeException("插入位置不合法");
}
if (pos == 0) {
addFirst(data);
return;
}
if (pos == this.linkedListSize) {
addLast(data);
return;
}
Node node = new Node(data);
Node prev = getIndex(pos);
node.next = prev.next;
prev.next = node;
this.linkedListSize++;
}
//修改指定位置的值
public void modify(int pos, User data) {
if (head == null) {
throw new RuntimeException("链表为空,无法进行修改");
}
if (pos < 0 || pos > this.linkedListSize - 1) {
throw new RuntimeException("操作位置不合法");
}
Node cur = this.head;
int index = 0;
while (index != pos) {
cur = cur.next;
index++;
}
cur.data = data;
}
//寻找关键字key的前一个结点
private Node getPrev(User key) {
Node prev = this.head;
while (prev.next != null) {
if (prev.next.data == key) {
return prev;
}
prev = prev.next;
}
return null;
}
//删除第一次出现关键字为key的节点
public void remove(User key) {
if (this.head == null) {
throw new RuntimeException("链表为空,无法进行操作");
}
if (this.head.data == key) {
//如果链表为空或第一个结点为删除的值
this.linkedListSize--;
this.head = this.head.next;
return;
}
Node prev = getPrev(key);
prev.next = prev.next.next;
this.linkedListSize--;
}
//删除所有值为key的节点
public void removeAll(User key) {
if (this.head == null) {
throw new RuntimeException("单链表为空,无法进行删除");
}
Node prev = this.head;
Node cur = prev.next;
while (cur != null) {
if (cur.data == key) {
prev.next = cur.next;
cur = cur.next;
this.linkedListSize--;
} else {
prev = cur;
cur = cur.next;
}
}
if (this.head.data == key) {
this.head = this.head.next;
this.linkedListSize--;
}
}
//清空单链表
public void clear() {
this.head = null;
}