JAVA实现单链表修改和删除数据节点

java,实现,单链,修改,删除,数据,节点 · 浏览次数 : 119

小编点评

**代码分析:** * **IdDataNode**类用于存储链表节点信息,包括id、数据和next域。 * ****SingleLinkedListAddOrder**类用于创建和管理单链表,包含添加数据节点和遍历链表的方法。 * ****SingleLinkedListDeleteNodeTest**类用于测试删除节点的操作。 **主要功能:** * 添加数据节点。 * 遍历链表,显示元素信息。 * 删除节点。 **测试结果:** * 没有找到要删除的节点! **总结:** * 单链表是存储数据节点的线性结构。 * 单链表添加和删除数据节点的操作比较简单。 * 在删除节点时,需要根据其位置找到上一个节点。

正文

JAVA实现单链表修改和删除数据节点

一、修改单链表中的一个节点

①实现思路

  1. 因为带头节点的链表中头节点的next域不能发生改变(始终指向单链表的头节点),否则将找不到该链表。所以我们需要先找一个辅助节点temp来进行节点代理操作。
  2. 通过遍历链表,使辅助节点temp后移,找到要修改的节点。
  3. 然后进行修改操作。

②updateNode代码实现

/**
 * 修改节点的信息,根据id修改除id之外的节点信息,id是不能改变的
 * 根据IdDataNode的id来修改
 *
 * @param idDataNode 待修改的数据节点
 */
public void updateNode(IdDataNode idDataNode) {
    // 先判断链表是否为空
    if (head.getNext() == null) {
        System.out.println("链表为空");
    }

    // 定义辅助节点
    IdDataNode temp = head.getNext();

    // 标记是否找到了数据节点
    boolean flag = false;

    // 遍历找到要修改的数据节点
    while (true) {
        if (temp.getNext() == null) {
            break;
        }
        if (temp.getId() == idDataNode.getId()) {
            flag = true;    // 说明找到这个编号为id的节点了
            break;
        }
        temp = temp.getNext();  // 辅助节点后移
    }

    // 根据flag判断是否找到了要修改的节点
    if (flag) {
        temp.setData(idDataNode.getData());
    } else {
        System.out.println("没有找到等于这个节点的编号,修改失败!");
    }

}

③updateNode方法测试-整体代码

说明:本次实验的整体测试代码是在《JAVA实现节点加入到单链表时按需求排序》一文实验代码上做出的updateNode方法增加。

/**
 * ClassName: SingleLinkedListAddOrder
 * Package: com.zhao.test
 * Description:
 *
 * @Author XH-zhao
 * @Create 2023/3/27 13:31
 * @Version 1.0
 */
public class SingleLinkedListAddOrder {

    // 创建单链表头节点
    private IdDataNode head = new IdDataNode(0, "");

    // 将数据节点按照数据id添加进链表
    public void addByIdOrder(IdDataNode idDataNode) {

        // 使用辅助变量temp代替head进行移动
        IdDataNode temp = head;

        while (true) {

            // 说明temp走到了最后,必须要添加元素了(添加到最后)
            if (temp.getNext() == null) {
                break;
            }

            // temp节点的后一个节点的id比要添加节点的id大代表可以添加元素了
            if (temp.getNext().getId() > idDataNode.getId()) {
                break;
            } else if (temp.getNext().getId() == idDataNode.getId()) {
                System.out.println("您添加的元素已经存在了!!");
                // 直接结束方法
                return;
            }

            // 将temp元素后移(继续遍历)
            temp = temp.getNext();
        }

        // 当遍历结束时,temp已经指向了要插入的位置的前一个节点(开始插入)
        idDataNode.setNext(temp.getNext());
        temp.setNext(idDataNode);
    }

    // 遍历整个链表
    public void showLinkedListAll() {
        // 当链表为空时不进行遍历,直接结束
        if (head.getNext() == null) {
            System.out.println("链表为空");
            return;
        }
        // 遍历链表时同样需要辅助变量,因为head节点不能移动,否则就找不到该链表了
        IdDataNode temp = head;
        while (true) {
            // 当链表为空时,不进行遍历,直接结束循环
            if (temp.getNext() == null) {
                break;
            }
            // 直接输出链表节点存的数据
            System.out.println(temp.getNext());
            //将temp指针往后移动
            temp = temp.getNext();
        }
    }

    /**
     * 修改节点的信息,根据id修改除id之外的节点信息,id是不能改变的
     * 根据IdDataNode的id来修改
     *
     * @param idDataNode 待修改的数据节点
     */
    public void updateNode(IdDataNode idDataNode) {
        // 先判断链表是否为空
        if (head.getNext() == null) {
            System.out.println("链表为空");
        }

        // 定义辅助节点
        IdDataNode temp = head.getNext();

        // 标记是否找到了数据节点
        boolean flag = false;

        // 遍历找到要修改的数据节点
        while (true) {
            if (temp.getNext() == null) {
                break;
            }
            if (temp.getId() == idDataNode.getId()) {
                flag = true;    // 说明找到这个编号为id的节点了
                break;
            }
            temp = temp.getNext();  // 辅助节点后移
        }

        // 根据flag判断是否找到了要修改的节点
        if (flag) {
            temp.setData(idDataNode.getData());
        } else {
            System.out.println("没有找到等于这个节点的编号,修改失败!");
        }

    }

}

// 带ID的数据节点类
class IdDataNode {

    private int id; // 用来作为排序依据,即实现以id进行排序的单链表
    private String data;    // data域,要存储的数据
    private IdDataNode next;  // next域,用于指向下一个数据节点地址

    // 数据节点构造器
    public IdDataNode(int id, String data) {
        this.id = id;
        this.data = data;
    }

    @Override
    public String toString() {
        return "IdDataNode{" +
                "id=" + id +
                ", data='" + data + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public IdDataNode getNext() {
        return next;
    }

    public void setNext(IdDataNode next) {
        this.next = next;
    }
}



// 更新节点数据测试类
class SingleLinkedListUpdateNodeTest {
    public static void main(String[] args) {

        // 创建四个数据节点,id分别是1-2-3-4
        IdDataNode dataNode1 = new IdDataNode(1, "data1");
        IdDataNode dataNode2 = new IdDataNode(2, "data2");
        IdDataNode dataNode3 = new IdDataNode(3, "data3");
        IdDataNode dataNode4 = new IdDataNode(4, "data4");

        // 创建带头节点的单链表
        SingleLinkedListAddOrder singleLinkedListAddOrder = new SingleLinkedListAddOrder();

        // 将四个数据节点增添到链表当中
        singleLinkedListAddOrder.addByIdOrder(dataNode1);
        singleLinkedListAddOrder.addByIdOrder(dataNode2);
        singleLinkedListAddOrder.addByIdOrder(dataNode3);
        singleLinkedListAddOrder.addByIdOrder(dataNode4);

        IdDataNode dataNode1_update = new IdDataNode(1, "data1_被修改");
        IdDataNode dataNode5_update = new IdDataNode(5, "data5_被修改");

        singleLinkedListAddOrder.updateNode(dataNode1_update);
        singleLinkedListAddOrder.updateNode(dataNode5_update);
        
        System.out.println("***************************************");
        
        // 显示链表中元素,查看数据是否被修改
        singleLinkedListAddOrder.showLinkedListAll();

    }
}

④测试结果

没有找到等于这个节点的编号,修改失败!
***************************************
IdDataNode{id=1, data='data1_被修改'}
IdDataNode{id=2, data='data2'}
IdDataNode{id=3, data='data3'}
IdDataNode{id=4, data='data4'}

进程已结束,退出代码0

二、删除单链表中的一个节点

①实现思路

理论思路:

  1. 我们依旧要找一个辅助节点temp来进行节点代理操作,通过遍历链表,找到需要删除的这个节点的前一个节点,将temp指向该节点。
  2. 然后将待删除节点的后一个节点的引用赋值给待删除节点前一个节点的next域(temp.next=temp.next.next)
  3. 待删除的节点,将不会有其他引用指向,会被垃圾回收机制回收

图解思路:

image-20230327194446569

②deleteNode代码实现

// 删除节点
public void deleteNode(IdDataNode idDataNode) {

    // 先判断链表是否为空
    if (head.getNext() == null) {
        System.out.println("链表为空");
    }

    // 使用辅助节点temp来进行节点代理操作
    IdDataNode temp = head;

    boolean flag = false;   // 标识是否找到删除节点的上一个节点

    while(true) {

        if(temp.getNext() == null) {
            break;
        }

        if(temp.getNext() == idDataNode){

            // 找到了要删除节点的上一个节点了,此时temp代理该节点
            flag = true;
            break;
        }

        temp = temp.getNext();  // 辅助节点后移

    }

    if(flag) {
        temp.setNext(temp.getNext().getNext()); // 然后将待删除节点的后一个节点的引用赋值给待删除节点前一个节点的next域
    }else {
        System.out.println("没有找到要删除的节点!");
    }

}

③deleteNode方法测试-整体代码

/**
 * ClassName: SingleLinkedListAddOrder
 * Package: com.zhao.test
 * Description:
 *
 * @Author XH-zhao
 * @Create 2023/3/27 13:31
 * @Version 1.0
 */
public class SingleLinkedListAddOrder {

    // 创建单链表头节点
    private IdDataNode head = new IdDataNode(0, "");

    // 将数据节点按照数据id添加进链表
    public void addByIdOrder(IdDataNode idDataNode) {

        // 使用辅助变量temp代替head进行移动
        IdDataNode temp = head;

        while (true) {

            // 说明temp走到了最后,必须要添加元素了(添加到最后)
            if (temp.getNext() == null) {
                break;
            }

            // temp节点的后一个节点的id比要添加节点的id大代表可以添加元素了
            if (temp.getNext().getId() > idDataNode.getId()) {
                break;
            } else if (temp.getNext().getId() == idDataNode.getId()) {
                System.out.println("您添加的元素已经存在了!!");
                // 直接结束方法
                return;
            }

            // 将temp元素后移(继续遍历)
            temp = temp.getNext();
        }

        // 当遍历结束时,temp已经指向了要插入的位置的前一个节点(开始插入)
        idDataNode.setNext(temp.getNext());
        temp.setNext(idDataNode);
    }

    // 遍历整个链表
    public void showLinkedListAll() {
        // 当链表为空时不进行遍历,直接结束
        if (head.getNext() == null) {
            System.out.println("链表为空");
            return;
        }
        // 遍历链表时同样需要辅助变量,因为head节点不能移动,否则就找不到该链表了
        IdDataNode temp = head;
        while (true) {
            // 当链表为空时,不进行遍历,直接结束循环
            if (temp.getNext() == null) {
                break;
            }
            // 直接输出链表节点存的数据
            System.out.println(temp.getNext());
            //将temp指针往后移动
            temp = temp.getNext();
        }
    }

    /**
     * 修改节点的信息,根据id修改除id之外的节点信息,id是不能改变的
     * 根据IdDataNode的id来修改
     *
     * @param idDataNode 待修改的数据节点
     */
    public void updateNode(IdDataNode idDataNode) {
        // 先判断链表是否为空
        if (head.getNext() == null) {
            System.out.println("链表为空");
        }

        // 定义辅助节点
        IdDataNode temp = head.getNext();

        // 标记是否找到了数据节点
        boolean flag = false;

        // 遍历找到要修改的数据节点
        while (true) {
            if (temp.getNext() == null) {
                break;
            }
            if (temp.getId() == idDataNode.getId()) {
                flag = true;    // 说明找到这个编号为id的节点了
                break;
            }
            temp = temp.getNext();  // 辅助节点后移
        }

        // 根据flag判断是否找到了要修改的节点
        if (flag) {
            temp.setData(idDataNode.getData());
        } else {
            System.out.println("没有找到等于这个节点的编号,修改失败!");
        }

    }

    // 删除节点
    public void deleteNode(IdDataNode idDataNode) {

        // 先判断链表是否为空
        if (head.getNext() == null) {
            System.out.println("链表为空");
        }

        // 使用辅助节点temp来进行节点代理操作
        IdDataNode temp = head;

        boolean flag = false;   // 标识是否找到删除节点的上一个节点

        while(true) {

            if(temp.getNext() == null) {
                break;
            }

            if(temp.getNext() == idDataNode){

                // 找到了要删除节点的上一个节点了,此时temp代理该节点
                flag = true;
                break;
            }

            temp = temp.getNext();  // 辅助节点后移

        }

        if(flag) {
            temp.setNext(temp.getNext().getNext()); // 然后将待删除节点的后一个节点的引用赋值给待删除节点前一个节点的next域
        }else {
            System.out.println("没有找到要删除的节点!");
        }

    }

}

// 带ID的数据节点类
class IdDataNode {

    private int id; // 用来作为排序依据,即实现以id进行排序的单链表
    private String data;    // data域,要存储的数据
    private IdDataNode next;  // next域,用于指向下一个数据节点地址

    // 数据节点构造器
    public IdDataNode(int id, String data) {
        this.id = id;
        this.data = data;
    }

    @Override
    public String toString() {
        return "IdDataNode{" +
                "id=" + id +
                ", data='" + data + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public IdDataNode getNext() {
        return next;
    }

    public void setNext(IdDataNode next) {
        this.next = next;
    }
}

// 删除节点数据测试类
class SingleLinkedListDeleteNodeTest {
    public static void main(String[] args) {

        // 创建四个数据节点,id分别是1-2-3-4
        IdDataNode dataNode1 = new IdDataNode(1, "data1");
        IdDataNode dataNode2 = new IdDataNode(2, "data2");
        IdDataNode dataNode3 = new IdDataNode(3, "data3");
        IdDataNode dataNode4 = new IdDataNode(4, "data4");

        // 创建带头节点的单链表
        SingleLinkedListAddOrder singleLinkedListAddOrder = new SingleLinkedListAddOrder();

        // 将四个数据节点增添到链表当中
        singleLinkedListAddOrder.addByIdOrder(dataNode1);
        singleLinkedListAddOrder.addByIdOrder(dataNode2);
        singleLinkedListAddOrder.addByIdOrder(dataNode3);
        singleLinkedListAddOrder.addByIdOrder(dataNode4);

        IdDataNode dataNode5_delete = new IdDataNode(5, "data5");

        singleLinkedListAddOrder.deleteNode(dataNode1);
        singleLinkedListAddOrder.deleteNode(dataNode5_delete);
        System.out.println("***************************************");
        // 显示链表中元素,查看数据是否被修改
        singleLinkedListAddOrder.showLinkedListAll();

    }
}

④测试结果

没有找到要删除的节点!
***************************************
IdDataNode{id=2, data='data2'}
IdDataNode{id=3, data='data3'}
IdDataNode{id=4, data='data4'}

进程已结束,退出代码0

三、实验总结

通过以上实验,我们实现了单链表修改和删除数据节点的操作。

与JAVA实现单链表修改和删除数据节点相似的内容:

JAVA实现单链表修改和删除数据节点

JAVA实现单链表修改和删除数据节点 一、修改单链表中的一个节点 ①实现思路 因为带头节点的链表中头节点的next域不能发生改变(始终指向单链表的头节点),否则将找不到该链表。所以我们需要先找一个辅助节点temp来进行节点代理操作。 通过遍历链表,使辅助节点temp后移,找到要修改的节点。 然后进行

节点加入到单链表时按需求排序

JAVA实现节点加入到单链表时按需求排序 回顾 在上文《带头节点的单链表的思路及代码实现(JAVA)》中我们想要去实现让数据节点不考虑加入顺序实现数据节点排序效果。 那么我们要如何实现这一需求呢? 一、实现思路 ①理论思路 假设我们要根据数据节点的ID进行排序,那么我们可以通过使用待增加的节点id逐

带头节点的单链表的思路及代码实现

带头节点的单链表的思路及代码实现(JAVA) 一、什么是的单链表 ①标准定义 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) +指针(指示后继元素存储位置,元素就是存储数据的存储单元,指针就是连接每

数组模拟单向队列的思路及代码

JAVA实现数组模拟单向队列的思路及代码 一、什么是队列? 队列是一种特殊的线性表 ,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。 进行插入操作的端称为队尾,进行删除操作的端称为队头。 队列中没有元素时,称为

数组模拟环形队列的思路及代码

JAVA实现数组模拟环形队列的思路及代码 前言 在对Java实现数组模拟队列零了解的情况下,建议先去阅读《JAVA实现数组模拟单向队列的思路及代码》一文,可以辅助理解本文核心思想。 一、环形数组队列 实现:让数组达到复用的效果,即:当我们从数组队列中取出了数据,那取出数据后后这个空间可以再次使用。

Java面试题:Spring Bean线程安全?别担心,只要你不写并发代码就好了!

Spring Bean是单例模式,即在整个应用程序上下文中只有一个实例。在多线程环境下,Singleton Scope Bean可能会发生线程安全问题。Spring Bean是否线程安全取决于Bean的作用域和Bean本身的实现。在使用Singleton Scope Bean时需要特别注意线程安全问...

Java进阶:HashMap底层原理(通俗易懂篇)

1.底层结构 Java 7及之前版本 在Java 7及之前的版本中,HashMap的底层数据结构主要是数组加链表。具体实现如下: 数组:HashMap的核心是一个Entry数组(Entry[] table),这个数组的大小总是2的幂。每个数组元素是一个单一的Entry节点,或者是一个链表的

《优化接口设计的思路》系列:第二篇—接口用户上下文的设计与实现

前言 大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。 作为一名从业已达六年的老码农,我的工作主要是开发后端Java业务系统,包括各种管理后台和小程序等。在这些项目中,我设计过单/多租户体系系统,对接

C++的动态分派在HotSpot VM中的重要应用

众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。C++ 和 Java 作为当前最为流行的两种面向对象编程语言,其内部对于多态的支持对于单继承的实现非常类似。 首先来体现一下C++的动态分派,如下: class Base1{ pub

多线程知识:三个线程如何交替打印ABC循环100次

本文博主给大家讲解一道网上非常经典的多线程面试题目。关于三个线程如何交替打印ABC循环100次的问题。 > 下文实现代码都基于Java代码在单个JVM内实现。 ## 问题描述 给定三个线程,分别命名为A、B、C,要求这三个线程按照顺序交替打印ABC,每个字母打印100次,最终输出结果为: ``` A