Java实现单链表的增删改查

单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:数据域和指针域,数据域就是存储数据的存储单元,指针域就是连接每个结点的地址数据。

思路分析

首先我们定义一个操作类,用来实现链表的增删改查。在操作类类中再定义一个内部私有的节点类(封装性),在其中定义数据域和指针域,并重写toString()方法。为了便于链表的管理和使用,在操作类中定义一个虚拟头节点head,里面不存放数据,只存放下一个结点的地址。虚拟头节点的下一个结点才是真正的头节点。

public class LinkedList {//链表操作类,对链表进行增删改查
    private  class Node {// 链表的组成部分————结点
        private int no;//编号
        private String data;//数据
        private Node next;//下一个结点的地址

        public Node(int no, String data) {//构造方法,给节点赋值
            this.no = no;
            this.data = data;
        }

        public String toString() { //输出结点信息
            return "No:" + no + "\tdata:" + data + "\t" + next;
        }

    }
    Node head = new Node(0, "");//定义一个虚拟头节点
}

类定义完成后,接下来定义添加结点的方法。

 public void add(int no, String data) {//传入数据域的值
        Node newNode = new Node(no, data);//创建一个新节点把传进来的值赋进去
        Node temp = head;//头节点是链表的开始位置,不能动,所以定义一个指针temp指向虚拟头节点
        while (true) {//循环遍历链表
            if (temp.next == null) { // 如果temp指向的节点的下一个节点为空,那么说明已经遍历到了链表的最后一个节点
                break; //退出循环
            }
            temp = temp.next;//否则temp后移,指向下一个节点
        }
        temp.next = newNode; // 在链表的最后一个节点的后面添加新节点
  }

这里肯定很多人会疑惑,为什么节点的next就是下一个节点,你是怎么保证的?请看下图分析。
在这里插入图片描述
将下一节点的地址值赋给当前结点的next,通过值传递来实现节点的next就是下一个节点。可以看出,是一个套娃的过程。

接下来是链表的更新。

public void update(int no, String data) { //传入节点中的数据,通过no来找到响应的结点
        Node temp = head; // 定义一个temp指向虚拟头节点
        while (true) {//循环遍历链表
            if (temp.next == null) { //  如果temp的下一个节点为空,那么就说明没有找到该节点,跳出循环
                System.out.println("没有编号为" + no + "的结点");
                break;
            }
            if (temp.next.no == no) {//如果找到对应编号的结点,则修改数据,跳出循环
                temp.next.data = data;
                break;
            }
            temp = temp.next;//如果不满足两个if中的条件,则指针后移
        }
    }

接下来是链表的删除。

 public void remove(int no) { // 传入no值
        Node temp = head; // 和前面一样,定义一个temp指向虚拟head节点
        while (true) {//循环遍历链表
            if (temp.next == null) { // 如果遍历到最后,temp的下一节点为空,则没有与编号匹配的节点
                System.out.println("没有编号为" + no + "的结点");
                break;
            }
            if (temp.next.no == no) {//如果有和编号相匹配的节点
                //将temp的下一个节点设为空
                Node trash = temp.next;
                trash = null;
                //让temp的下一个节点等于下下个节点
                temp.next = temp.next.next;
                break;
            }
            temp = temp.next;//如果不满足两个if中的条件,则指针后移,继续遍历链表
        }
    }

接下来是链表的查询

public void search(int no) { // 传入编号
        Node temp = head; //和前面一样,定义一个temp指向虚拟head节点
        if (head.next == null) { // 如果虚拟头节点的后一个节点位空,则链表为空
            System.out.println("链表为空!");
            return;
        }
        while (true) {
            if (temp.next == null) { //如果遍历到最后,temp的下一节点为空,则没有与编号匹配的节点
                System.out.println("查询不到节点");
                break;
            }
            if (temp.next.no == no) {//如果有,则输出该节点的数据
                System.out.println(temp.next);
                break;
            }
            temp = temp.next;//指针后移
        }
    }

接下来是链表的打印

 public void show() {
        Node temp = head; // 头节点不能改变,否则无法遍历! 定义一个temp指针指向头节点
        if (temp.next == null) { //  如果虚拟头节点的后一个节点位空,则链表为空
            System.out.println("链表为空");
        }
        while (true) {
            if (temp.next != null) { // 如果temp的下一个节点为空
                temp = temp.next; //temp指向后一个节点
                System.out.println(temp);//输出后一个节点的值
            } else {
                break; //为空跳出循环
            }
        }
    }

最后是链表的按序添加
这里要注意,如图所示:

在这里插入图片描述

 public void addByOrder(int no, String data) { // 按顺序添加,将值传入
        Node newNode = new Node(no, data); //创建新节点将值赋进去
        Node temp = head;//定义一个temp指向头节点
        while (true) {
            if (temp.next == null) {//如果遍历到最后,即链表到了最后一个节点
                temp.next = newNode;//将最后一个节点的后一位指向newNode
                break;
            }
            if (temp.next.no >= newNode.no) {//如果链表中temp.next的编号大于待插入编号
                newNode.next = temp.next;//将新节点的下一个节点指向原来temp指向的下一个节点
                temp.next = newNode;//temp指向新的节点
                break;//跳出循环
            }
            //temp = temp.next;//temp后移
        }
    }

这样我们就实现了单链表的CRUD操作啦!
下面附上完整代码,代码还可以更进一步优化,欢迎指正!


public class LinkedList {//链表操作类,对链表进行增删改查

    private class Node {// 链表的组成部分————结点
        private int no;//编号
        private String data;//数据
        private Node next;//下一个结点的地址

        public Node(int no, String data) {//构造方法,给节点赋值
            this.no = no;
            this.data = data;
        }

        public String toString() { //输出结点信息
            return "No:" + no + "\tdata:" + data;
        }

    }

    Node head = new Node(0, "");//定义一个虚拟头节点

    public void add(int no, String data) {//传入数据域的值
        Node newNode = new Node(no, data);//创建一个新节点把传进来的值赋进去
        Node temp = head;//头节点是链表的开始位置,不能动,所以定义一个temp节点指向虚拟头节点
        while (true) {
            if (temp.next == null) { // 如果temp节点的下一个节点为空,那么说明已经遍历到了链表的最后一个节点
                break; //退出循环
            }
            temp = temp.next;//否则temp后移,指向下一个节点
        }
        temp.next = newNode; // 在链表的最后一个节点的后面添加新节点
        /*while (true){
            if (temp.next !=null){
                temp = temp.next;
            }else {
                temp.next = newNode;// 在链表的最后一个节点的后面添加新节点
                break;
            }
        }*/
    }

    public void addByOrder(int no, String data) { // 按顺序添加,将值传入
        Node newNode = new Node(no, data); //创建新节点将值赋进去
        Node temp = head;//定义一个temp指向头节点
        while (true) {
            if (temp.next == null) {//如果遍历到最后,即链表到了最后一个节点
                temp.next = newNode;//将最后一个节点的后一位指向newNode
                break;
            }
            if (temp.next.no >= newNode.no) {//如果链表中temp.next的编号大于待插入编号
                newNode.next = temp.next;//将新节点的下一个节点指向原来temp指向的下一个节点
                temp.next = newNode;//temp指向新的节点
                break;//跳出循环
            }
            //temp = temp.next;//temp后移
        }
    }

    public void update(int no, String data) { //传入节点中的数据
        Node temp = head; // 定义一个temp指向虚拟头节点
        while (true) {
            if (temp.next == null) { //  如果temp的下一个节点为空,那么就说明没有找到该节点,跳出循环
                System.out.println("没有编号为" + no + "的结点");
                break;
            }
            if (temp.next.no == no) {//如果找到对应编号的结点,则修改数据,跳出循环
                temp.next.data = data;
                break;
            }
            temp = temp.next;//如果不满足两个if中的条件,则指针后移,继续遍历链表
        }
    }

    public void remove(int no) { // 传入no值
        Node temp = head; // 和前面一样,定义一个temp指向head节点
        while (true) {//循环遍历链表
            if (temp.next == null) { // 如果遍历到最后,temp的下一节点为空,则没有与编号匹配的节点
                System.out.println("没有编号为" + no + "的结点");
                break;
            }
            if (temp.next.no == no) {//如果有和编号相匹配的节点
                //将temp的下一个节点设为空
                Node trash = temp.next;
                trash = null;
                //让temp的下一个节点等于下下个节点
                temp.next = temp.next.next;
                break;
            }
            temp = temp.next;//如果不满足两个if中的条件,则指针后移,继续遍历链表
        }
    }

    public void search(int no) { // 传入编号
        Node temp = head; //和前面一样,定义一个temp指向虚拟head节点
        if (head.next == null) { // 如果虚拟头节点的后一个节点位空,则链表为空
            System.out.println("链表为空!");
            return;
        }
        while (true) {
            if (temp.next == null) { //如果遍历到最后,temp的下一节点为空,则没有与编号匹配的节点
                System.out.println("查询不到节点");
                break;
            }
            if (temp.next.no == no) {//如果有,则输出该节点的数据
                System.out.println(temp.next);
                break;
            }
            temp = temp.next;//指针后移
        }
    }

    public void show() {
        Node temp = head; // 头节点不能改变,否则无法遍历! 定义一个temp指针指向头节点
        if (temp.next == null) { //  如果虚拟头节点的后一个节点位空,则链表为空
            System.out.println("链表为空");
        }
        while (true) {
            if (temp.next != null) { // 如果temp的下一个节点为空
                temp = temp.next; //temp指向后一个节点
                System.out.println(temp);//输出后一个节点的值
            } else {
                break; //为空跳出循环
            }
        }
    }
    
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值