笔记:
1:单链表 的按内容、按下标:增、删、查、改
- KEY:单链表按内容添加的核心逻辑:
若不空,从头结点向后遍历,找到尾结点
在尾结点后部加上一个新的节点,- KEY:单链表按照内容删除,分为:删除头、中间、尾
删除中间时,先查找到要删除节点的前一个,再删除
注意删完要size--,- KEY: 单链表按照内容查找的核心逻辑:
先判空,不空则从头向尾遍历
不分头中尾,统一处理
用mid记录要查找的节点
当mid不为null,且内容不相等,curr就向后移动
上述循环有两个跳出条件,
把链表从头遍历到尾都没有找到---> 没有存储这个数据
否则就是因为找到数据而退出。- KEY: 单链表按照内容修改的核心逻辑:
先判空,不空则从头向尾遍历
不分头中尾,统一处理
用mid记录要查找的节点
当mid不为null,且内容不相等,curr就向后移动
上述循环有两个跳出条件,
把链表从头遍历到尾都没有找到---> 没有存储这个数据
找到了--> 赋新值
- KEY: 单链表按下标添加的核心逻辑:
根据下标找到位置, 添加
找到的位置: 头, 中间, 尾
中间和尾部可以统一处理,
用一个curr记录要添加位置的前一个结点
用tag = 1,记录curr.next 的下标
别忘记添加完成要size++。- KEY: 单链表按照下标删除的核心逻辑:
先根据下标查找, 找到之后删除
分为头,中间或尾部两种
remove get set 下标判非法要加 = ,add的判非法不要加 =
用mid记录要删除节点的前一个
用tag记录mid.next的下标,用来和要删除节点的下标判等
别忘记删除成功后size--。- KEY: 单链表按照下标查找的核心逻辑:
先根据下标查找, 找到之后返回内容
不分头中尾,统一处理
用mid记录要查找的节点
用tag记录mid的下标,用来和要查找节点的下标判等。- KEY: 单链表按照下标修改的核心逻辑:
先根据下标查找, 找到之后修改
不分头中尾,统一处理
用mid记录要查找的节点
用tag记录mid的下标,用来和要修改节点的下标判等。
基于上述逻辑的代码:
package com._28_datastructure._01_linkedlist._01mylinkedlist;
import java.util.Objects;
/**
* 单链表的 按照内容和下标
* 增、删、改、查
*
* @author zxcsjf
* @since 2022/07/06 11:20
*/
public class MyLinkedList {
public Node first; // 链表维护一个头结点
public int size; // 当前链表存储的元素个数
/* 根据内容:增、删、查、改 */
/**
* 按内容,在尾部添加结点
* 不要动头结点!!!避免被垃圾回收
*
* @param value 要添加的结点值
* @return 添加成功 返回true
* @author zxcsjf
* @since 2022/07/06 11:23:42
*/
public boolean add(String value) {
// 判空
if (isEmpty()) {
first = new Node(value);
size++;
return true;
}
// KEY:单链表按内容添加的核心逻辑:
// 若不空,从头结点向后遍历,找到尾结点
// 在尾结点后部加上一个新的节点,
Node mid = first;
while (mid.next != null) {
mid = mid.next;
}
// 退出循环,mid指向尾结点
// 把新结点加在尾部,
mid.next = new Node(value);
size++;
return true;
}
/**
* 按内容,删除结点
*
* @param value 要删除的结点值
* @return 删除成功,返回true
* @author zxcsjf
* @since 2022/07/06 11:37:09
*/
public boolean remove(String value) {
// 判空
if (isEmpty()) {
throw new IllegalStateException("链表为空!");
}
// KEY:单链表按照内容删除,分为:删除头、中间、尾
// 删除中间时,先查找到要删除节点的前一个,再删除
// 注意删完要size--,
// 判断要删除的是否为头结点
if (Objects.equals(value, first.value)) {
first = first.next;
size--;
return true;
}
// 删除中间、或者尾结点
// curr记录要删除的结点的前一个
Node curr = first;
// 遍历的结点的下一个不为null,
// 并且当前结点的下一个不是要找的值
// 就向后遍历
while (curr.next != null && !Objects.equals(curr.next.value, value)) {
curr = curr.next;
}
// 上述循环结束, 有两个结束条件
// 1.没找到要删除的结点
if (curr.next == null) {
return false;
}
// 2.找到要删除的结点,要删除的是curr.next
curr.next = curr.next.next;
size--;
return true;
}
/**
* 按内容,查找结点
*
* @param value 要找的节点值
* @return boolean
* @author zxcsjf
* @since 2022/07/07 9:43:10
*/
public boolean contains(String value) {
// 判空, 抛异常
if (isEmpty()) {
throw new RuntimeException("链表为空!");
}
// 不空 ---> 从头向尾遍历, 查找这个元素是否存在
Node curr = first;
// 当前结点不为null,且内容不相等,curr就向后移动
while (curr != null && !Objects.equals(value, curr.value)) {
curr = curr.next;
}
// 上述循环有两个跳出条件,
// 把链表从头遍历到尾都没有找到---> 没有存储这个数据
if (curr == null) {
return false;
}
// 否则就是因为找到数据而退出
return true;
}
/**
* 根据内容,替换第一个找到的内容
*
* @param oldValue 被替换的内容
* @param newValue 用来替换的内容
* @return boolean
* @author zxcsjf
* @since 2022/07/07 9:50:43
*/
public boolean set(String oldValue, String newValue) {
// 判空, 抛异常
if (isEmpty()) {
throw new RuntimeException("链表为空!");
}
// curr向后查找
Node curr = first;
// 当前结点不为null,且内容不相等,curr就向后移动
while (curr != null && !Objects.equals(oldValue, curr.value)) {
curr = curr.next;
}
// 上述循环有两个跳出条件
if (curr == null) {
// 把链表从头遍历到尾都没有找到 --> 没有存储这个数据
return false;
}
// 找到了--> 赋新值
curr.value = newValue;
return true;
}
/**
* 判空方法
* 没有效率的提高,但提高可读性
*
* @return boolean
* @author zxcsjf
* @since 2022/07/06 11:30:46
*/
public boolean isEmpty() {
return first == null;
}
/* 作为线性表,按照下标:增、删、查、改*/
/**
* 按照下标增加元素
*
* @param index
* @param value
* @return boolean 增加成功,返回true,否则抛异常
* @author zxcsjf
* @since 2022/07/07 10:00:51
*/
public boolean add(int index, String value) {
// 判断下标合法,可以在 0 ~ size 处添加
if (index < 0 || index > size) {
throw new IllegalArgumentException("传入的下标不合法!");
}
// KEY: 核心逻辑&#