java实现单链表的常用操作(逆序、插入、遍历等)
简介:
- 分为四个类,节点类(Node),链表类(LinkNode),工具类(Tool),主类
- 链表类的方法:
- 构造方法3个
- 成员方法1:获得链表长度
- 成员方法2:判断链表是否为空
- 成员方法3:获得第n个节点的值
- 成员方法4:遍历输出链表值
- 工具类的方法:
- 构造方法
- 成员方法:链表逆序
- 成员方法:链表指定位置插入
- 成员方法:链表指定位置逆序
- 成员方法:链表中间位置逆序
- 主类附有案例
一、节点类
- 因为暂时没有学习泛型,这里节点内数据设为int类型
public class Node {
/*
链表节点应具备的属性:
1,节点的属性包括 节点数据 和 下一个节点的地址
2. 没有学泛型,这里节点内容数据设为int,而非引用类型
*/
private int number; // 本节点的值
Node nextNode; // 指针-->指向下一个节点
public Node(int number, Node nextNode) {
this.nextNode = nextNode;
this.number = number;
}
public Node() {
this(0, null); // 由于是int数值->设置0, 如果是引用类型设置为null
}
public int getInt() {
return number;
}
}
二、链表类
- 我理解的单链表:
public class LinkNode {
Node head;
/*
链表:
1. head是一个在链表外的Node对象,头节点不算在链表内,且头节点不算在长度内
2. 链表其实是多个Node类型的数据链接一起
3. 链表的最后一个节点的nextNode属性为null
*/
// 构造方法一:链表为空链表,只有一个头节点
// 因为是int类型, 头指针指向节点其实有默认值0
public LinkNode() {
head = new Node();
}
// 构造方法二:数组传值,形成单链表
// 以数组形式传值. 这里是int数组
// 没有考虑传值数组内值为空的情况(因为为Int类型)
public LinkNode(int[] arr) {
this();
Node rear = head; // 尾指针,便于数组传值
for (int i = 0; i < arr.length; i++) {
// rear.toNextNode() = new Node(arr[i], null);
// 一开始把nextNode设为private, 但这样会报错???
rear.nextNode = new Node(arr[i], null);
rear = rear.nextNode;
}
}
// 构造方法三:链表内有一个Node节点
public LinkNode(int m) {
head = new Node(0, null);
head.nextNode = new Node(m, null);
}
public boolean isEmpty() {
return head.nextNode == null;
}
// 遍历链表,直到rear指针指向null
public int LinkLength() {
Node rear = head;
int length = 0;
while (rear.nextNode != null) {
length++;
rear = rear.nextNode;
}
return length;
}
// 获得第n个节点的值,同样需要遍历
/*
假设需要获得第2个节点的值,需要把rear指针指向第二个节点
即需要遍历2次 --> 获得第n个节点的值需要遍历n次
*/
public int getInfo(int n) {
Node rear = head;
for (int i = 0; i < n; i++) {
rear = rear.nextNode;
}
return rear.getInt();
}
// 输出单向链表
public void showAllNum() {
Node rear = head;
for (int i = 1; i <= this.LinkLength(); i++) {
System.out.print(this.getInfo(i) + "\t");
}
System.out.println("");
}
}
三、工具类
- 链表逆序示例(以链表长度为3的链表,数值分别为1,2,3示例):
- 单链表插入图示:
- 该类的代码:
public class LinkTool {
private LinkNode linkNode;
// 链表逆序
public void linkInverse(LinkNode linkNode) {
if (linkNode.isEmpty()) {
throw new RuntimeException("目前为空链表!");
}
if (linkNode.LinkLength() == 1) {
return;
}
Node temp = null;
Node point = linkNode.head.nextNode;
Node save = point;
while (point != null) {
save = point.nextNode;
point.nextNode = temp;
temp = point;
point = save;
}
linkNode.head.nextNode = temp;
}
// 链表指定第n个和第n+1个节点逆序
public void nodeInverse(LinkNode linkNode, int n) {
Node front = linkNode.head;
Node middle;
Node behind;
// 空链表
if (linkNode.isEmpty()) {
throw new RuntimeException("空链表不可逆转!");
}
// 长度为1的链表逆序
if (linkNode.LinkLength() == 1) {
System.out.println("节点长度为1, 无法逆转");
return;
}
// n的范围
if (n >= linkNode.LinkLength() || n <= 0) {
throw new RuntimeException("节点位置错误,应大于等于1并小于等于链表长度减一!");
}
for (int i = 0; i < n - 1; i++) {
front = front.nextNode;
}
middle = front.nextNode;
behind = middle.nextNode;
middle.nextNode = behind.nextNode;
front.nextNode = behind;
behind.nextNode = middle;
}
// 删除第n个节点
public void linkDel(int n) {
}
// 把节点插入到第n个位置
public void nodeInsert(Node insertNode, LinkNode linkNode, int n) {
if (n >= 1 && n <= linkNode.LinkLength() + 1) {
Node point = linkNode.head;
Node temp;
for (int i = 0; i < n - 1; i++) {
point = point.nextNode;
}
temp = point.nextNode;
point.nextNode = insertNode;
insertNode.nextNode = temp;
} else {
throw new RuntimeException("插入位置错误!");
}
}
// 中间两个节点逆序
public void middleInverse(LinkNode linkNode) {
int middlePosition = linkNode.LinkLength() / 2;
this.nodeInverse(linkNode, middlePosition);
}
}
四、主类示例
- 运行结果:
- 主类代码:
public class Start {
public static void main(String[] args) {
// LinkNode基础操作
int arr[] = {1, 2, 3};
LinkNode linkNode = new LinkNode(arr);
// 链表长度
System.out.println("链表的长度为:" + linkNode.LinkLength());
// 从链表中获取数据
System.out.println("第2个元素为:" + linkNode.getInfo(2));
// 显示链表数据
System.out.println("====该链表的全部数字====");
linkNode.showAllNum();
// 使用LinkTool进行逆序
LinkTool tool = new LinkTool();
try {
tool.linkInverse(linkNode);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====该链表逆转后的全部数字====");
linkNode.showAllNum();
// 使用LinkTool进行插入操作
Node insertNode1 = new Node(10, null);
try {
tool.nodeInsert(insertNode1, linkNode, 3);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====把10插入第3个位置====");
linkNode.showAllNum();
Node insertNode2 = new Node(10, null);
try {
tool.nodeInsert(insertNode2, linkNode, 1);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====把10插入第1个位置====");
linkNode.showAllNum();
Node insertNode3 = new Node(5, null);
try {
tool.nodeInsert(insertNode3, linkNode, linkNode.LinkLength() + 1);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====把5插入尾部====");
linkNode.showAllNum();
// 指定位置进行逆转
try {
tool.nodeInverse(linkNode, 2);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====第2个节点和第3个节点逆转====");
linkNode.showAllNum();
try {
tool.nodeInverse(linkNode, 1);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====第1个节点和第2个节点逆转====");
linkNode.showAllNum();
try {
tool.nodeInverse(linkNode, linkNode.LinkLength() - 1);
} catch (Exception e) {
e.getMessage();
}
System.out.println("====最后两个节点逆转====");
linkNode.showAllNum();
// 中间两个节点逆转
try {
tool.middleInverse(linkNode);
}catch (Exception e) {
e.getMessage();
}
System.out.println("====中间节点逆转====");
linkNode.showAllNum();
}
}