前言
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
一、单链表概要
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的),链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
二、单链表实现
代码如下(示例):
/**
* @Author sen
* @Date 2021/9/7
*/
public class SingleLinkQueue {
private Person head; // 头结点,用来标识定位链表
private int size; // 链表长度
public SingleLinkQueue() { // 初始化链表,头结点为空
this.head = new Person();
}
// 按序号有序添加
public void add(Person p) {
Person temp = head.getNext(); // 获取链表中当前节点和前置节点,方便指针修改
Person prev = head;
int no = p.getNo();
while (true) {
if (temp == null) {
prev.setNext(p);
++size;
return;
}
int no1 = temp.getNo();
if (no > no1) {
prev.setNext(p);
p.setNext(temp);
++size;
return;
} else if (no == no1) {
throw new RuntimeException("序号不能相同");
} else {
prev = temp;
temp = temp.getNext();
}
}
}
// 删除
public boolean del(int pno) {
Person temp = head.getNext();
Person prev = head;
while (true) {
if (temp == null) {
return false;
}
int no = temp.getNo();
if (no == pno) {
prev.setNext(temp.getNext());
--size;
return true;
} else {
prev = temp;
temp = temp.getNext();
}
}
}
// 查找
public Person find(int pno) {
Person temp = head.getNext();
while (true) {
if (temp == null) {
return null;
}
int no = temp.getNo();
if (no == pno) {
return temp;
} else {
temp = temp.getNext();
}
}
}
// 修改
public boolean update(Person p) {
int pno = p.getNo();
Person temp = head.getNext();
while (true) {
if (temp == null) {
return false;
}
int no = temp.getNo();
if (no == pno) {
temp.setName(p.getName());
return true;
} else {
temp = temp.getNext();
}
}
}
// 展示
public void show() {
Person temp = head.getNext();
while (true) {
if (temp == null) {
return;
}
System.out.println(temp);
temp = temp.getNext();
}
}
// 长度
public int getSize() {
return size;
}
}
二、快慢指针实现倒叙查找
快慢指针就是使用两根指针,其中一个指针快,另一个指针慢,可以利用两根指针的速度差去解决遇到的问题,比如判断链表是否成环、求出中位节点、倒叙查找等等
// 查找倒数第几个元素
public Person lastIndex(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("异常");
}
Person temp1 = head.getNext();
Person temp2 = head;
if (temp1 == null) {
throw new RuntimeException("数组为空");
}
for (int i = 0; i < index; i++) {
temp2 = temp2.getNext();
}
for (; ; ) {
if (temp2.getNext() == null)
return temp1;
temp1 = temp1.getNext();
temp2 = temp2.getNext();
}
}
二、反转
利用两根指针对链表进行反转,原理与快慢指针类似
// 反转
public void reversal() {
Person reversalHead = new Person();
Person temp = head.getNext();
if (temp == null) {
throw new RuntimeException("kong");
}
if (temp.getNext() == null) {
System.out.println(temp);
return;
}
Person prev = temp;
temp = temp.getNext();
for (; ; ) {
if (temp == null) {
Person next = reversalHead.getNext();
reversalHead.setNext(prev);
prev.setNext(next);
break;
}
Person next = reversalHead.getNext();
reversalHead.setNext(prev);
prev.setNext(next);
prev = temp;
temp = temp.getNext();
}
// show
Person next = reversalHead.getNext();
for (; ; ) {
if (next == null) {
return;
} else {
System.out.println(next);
next = next.getNext();
}
}
}
总结
加油噢!