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

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

三、实验总结

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

posted @ 2023-04-08 13:58  zhao-XH  阅读(411)  评论(1编辑  收藏  举报