模拟实现单链表 —— SingleLinkedList
模拟实现 java 中单链表的实现,方便后续对 java 中的 LInkedList 进行理解。
MySingleList类:
public class MySingleList {
/**
* 定义节点类
*/
static class ListNode {
// 节点值
private int val;
// 下一个节点的引用
private ListNode next;
public ListNode(int val) {
this.val = val;
}
}
// 头节点
private ListNode head;
/**
* 头插法
*/
public void headInsert(int value) {
// 申请节点
ListNode node = new ListNode(value);
// 头插
node.next = head;
head = node;
}
/**
* 尾插法
*/
public void tailInsert(int value) {
// 申请节点
ListNode node = new ListNode(value);
// head 为空
if (head == null) {
// head 直接指向 node
head = node;
return;
}
ListNode cur = head;
// 找最后一个节点
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
/**
* 任意位置插入
*/
public void randomInsert(int index, int value) {
// 判断下标是否合理
judge(index);
// 判断是否是头插或尾插
if (isInsert(index, value)) {
return;
}
// 中间位置插入
ListNode cur = head;
// 找到插入位置的前一个位置
for (int i = 0; i < index - 1; i++) {
cur = cur.next;
}
// 插入
ListNode node = new ListNode(value);
node.next = cur.next;
cur.next = node;
}
/**
* 判断下标是否合理
*/
private void judge(int index) {
if (index < 0 || index > size()) {
throw new IndexOFBoundException("下标: " + index + "错误!");
}
}
/**
* 判断插入位置是否是头插或尾插
*/
private boolean isInsert(int index, int value) {
if (index == 0) { // 头插
headInsert(value);
return true;
} else if (index == size()) { // 尾插
tailInsert(value);
return true;
} else {
return false;
}
}
/**
* 查找 value 是否在链表中存在
*/
public boolean contains(int value) {
ListNode cur = head;
while (cur != null) {
if (cur.val == value) {
return true;
}
cur = cur.next;
}
return false;
}
/**
* 删除链表中第一次出现 value 的节点
*/
public void remove(int value) {
// head 为空或要删除的节点是 head
if (isNullOrHead(value)) {
return;
}
// 获取要删除节点的前一个节点
ListNode preNode = findFirstDeletePreNode(value);
// 判断 preNode 为空
if (preNode == null) {
System.out.println("没有这个元素对应的节点");
return;
}
// 删除节点
ListNode delNode = preNode.next;
preNode.next = delNode.next;
}
/**
* 要删除的节点为空或是第一个节点
*/
private boolean isNullOrHead(int value) {
if (head == null) { // head 为空
return true;
} else if (head.val == value) { // head 的 val 和 value 相同
// head 后移
head = head.next;
return true;
} else {
return false;
}
}
/**
* 查找要删除 value 节点
*/
private ListNode findFirstDeletePreNode(int value) {
ListNode cur = head;
while (cur.next != null) {
// 找到了要删除节点的前驱
if (cur.next.val == value) {
return cur;
}
cur = cur.next;
}
// 没找到
return null;
}
/**
* 删除所有值为 value 的节点
*/
public void removeAllValue(int value) {
// 判空
if (head == null) return;
ListNode prev = head;
ListNode cur = head.next;
while (cur != null) {
// 判断 cur.val 是否和 value 相等
if (cur.val == value) {
// 相等则让 prev.next 指向 cur.next
prev.next = cur.next;
} else {
// prev 移动到 cur 的位置
prev = cur;
}
// cur 移动到 cur.next
cur = cur.next;
}
// 判断第一个节点的值是否和 value 相等
if (head.val == value) {
head = head.next;
}
}
/**
* 获取单链表的长度
*/
public int size() {
ListNode cur = head;
int count = 0;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
/**
* 清空单链表
*/
public void clear() {
// 把 head 置为 null
this.head = null;
}
/**
* 打印数组中的元素
*/
public void display() {
ListNode cur = head;
while (cur != null) {
System.out.print(cur.val + " ");
// 指向下一个值
cur = cur.next;
}
System.out.println();
}
}
IndexOFBoundException类:
public class IndexOFBoundException extends RuntimeException {
public IndexOFBoundException() {
}
public IndexOFBoundException(String message) {
super(message);
}
}
Test类
public class Test {
public static void main(String[] args) {
MySingleList mySingleList = new MySingleList();
/*mySingleList.headInsert(1);
mySingleList.headInsert(2);
mySingleList.headInsert(3);*/
//mySingleList.display();
mySingleList.tailInsert(1);
mySingleList.tailInsert(2);
mySingleList.tailInsert(3);
mySingleList.tailInsert(4);
mySingleList.tailInsert(5);
mySingleList.tailInsert(6);
mySingleList.display();
mySingleList.randomInsert(0, 111);
mySingleList.randomInsert(7, 111);
mySingleList.randomInsert(3, 111);
//mySingleList.randomInsert(12, 111);
mySingleList.display();
mySingleList.remove(2);
mySingleList.display();
mySingleList.removeAllValue(111);
mySingleList.display();
}
}