【Java实战经验】Java 实现自定义单链表

本文档展示了一个自定义的单链表实现,包括添加、删除、头尾插入等功能。作者指出了在没有泛型的情况下,按内容删除结点的功能尚未完善,但通过下标删除结点是可行的。测试部分展示了各种操作的实例,如向链表不同位置插入结点和删除结点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实战写了一个自定义单链表

存在问题:

  • 由于还没到泛型,暂时先用 Object 代替
  • 没到泛型,链表中指定内容删除结点的功能目前还是残缺的,待完善,不过通过下标删除结点这个还是没问题的

Node 结点类

/**
 * @Author IceClean
 * @Date 2021-2-24
 * 单链表的结点
 */
public class Node
{
    private Object data;
    private Node next;

    /**
     * 创建空结点
     */
    public Node() { }

    /**
     * 创建有数据和指向的结点
     * @param data 该节点的数据
     * @param next 该节点的指向
     */
    public Node(Object data, Node next)
    {
        this.data = data;
        this.next = next;
    }

    /**
     * 使链表指向新的结点
     * @param next 下一个结点
     */
    public void setNext(Node next)
    {
        this.next = next;
    }

    /**
     * 修改该结点的数据
     * @param data 该结点的新数据
     */
    public void setData(Object data)
    {
        this.data = data;
    }

    /**
     * 获取下一个结点
     * @return 下一个结点
     */
    public Node getNext() {
        return next;
    }

    /**
     * 获取该节点的数据
     * @return 该节点的数据
     */
    public Object getData() {
        return data;
    }
}

Link 链表类

/**
 * @Author IceClean
 * @Date 2021-2-24
 * 单链表对象
 */
public class Link
{
    private Node head;  // 头节点
    private int length;  // 链表长度

    /**
     * 创建空链表
     */
    public Link()
    {
        head = new Node(null, null);
    }

    /**
     * 创建有头节点的链表
     * @param data
     */
    public Link(Object data)
    {
        head = new Node(data, null);
        length = 1;
    }

    /**
     * 默认向尾部添加数据
     * @param data 新节点的数据
     */
    public void add(Object data)
    {
        if(length == 0) head = new Node(data, null);  // 长度为 0 的话链表为空,应初始化头节点
        else
        {
            Node temp = head;  // 创建一个临时的结点对象
            Node newNode = new Node(data, null);  //设置新结点的数据,并且将其指向空变成新的尾节点
            while(temp.getNext()!=null) temp = temp.getNext();  // 遍历到尾节点处
            temp.setNext(newNode);  // 将其指向新的尾结点
        }
        length++;  // 长度自增 1
    }

    /**
     * 指定位置添加数据
     * @param index
     * @param data
     */
    public void add(int index, Object data)
    {
        if(index == 0 && length == 0) head = new Node(data, null);  // 从头节点处加入且长度为 0 的话,应初始化头节点
        else if(index<0 || index>length) throw new IndexOutOfBoundsException("下标 "+index+" 越界啦!!!");  // 抛数组越界异常
        else
        {
            Node newNode = new Node(data, null);  // 创建新节点
            if(index == 0)  // 等于 0 的话表示在头部插入,应该把头节点换了
            {
                newNode.setNext(head);
                head = newNode;
            }
            else  // 不等于 0 表示从中间插入,头节点不用换
            {
                Node temp = head;  // 使用临时结点
                int nowIndex = 0;
                while(nowIndex < index-1)  // 遍历到指定结点的前一个位置
                {
                    temp = temp.getNext();
                    nowIndex++;
                }
                newNode.setNext(temp.getNext());  // 将新结点指向当前结点的下一个结点
                temp.setNext(newNode);  // 将当前结点指向新节点
            }
        }
        length++;  // 成功到这里的话说明参数没问题,长度自增 1
    }

    /**
     * 采用头插法插入结点
     * @param data 插入结点的数据
     */
    public void addHead(Object data)
    {
        add(0, data);
    }

    /**
     * 采用尾插法插入数据
     * @param data 插入结点的数据
     */
    public void addLast(Object data)
    {
        add(length, data);
    }

    /**
     * 按内容删除结点
     * @param data 要删除结点的内容
     * @return 删除成功返回 true ,否则 false
     */
    public boolean remove(Object data)
    {
        int index = 0;  // 存放指定内容对应结点的下标
        Node temp = head;  // 存放临时结点
        while(temp!=null)
        {
            // 找出匹配的结点,根据需求可重写 equals 方法
            if(temp.getData().equals(data))
                return remove(index);  // 删除结点,并返回

            temp = temp.getNext();
            index++;
        }

        return false;  // 到这里说明删除不成功
    }

    /**
     * 通过下标删除结点
     * @param index 要删除结点的下标
     * @return 删除成功返回 true ,否则 false
     */
    public boolean remove(int index)
    {
        if(index<0 || index>length-1) throw new IndexOutOfBoundsException("下标 "+index+" 越界啦!!!");  // 抛数组越界异常
        else
        {
            if(index == 0) head = head.getNext();  //如果删除的是头结点的话,头结点应换掉
            else
            {
                Node temp = head;  // 使用临时结点
                int nowIndex = 0;
                while(nowIndex < index-1)  // 遍历到指定结点的前一个位置
                {
                    temp = temp.getNext();
                    nowIndex++;
                }
                temp.setNext(temp.getNext().getNext());  // 当前结点指向要删除结点的下一个结点,完成删除
            }

            length--;  // 长度减 1

            return true;
        }
    }

    /**
     * 获取链表的长度
     * @return 链表的长度
     */
    public int length() {
        return length;
    }

    /**
     * 返回整条链表的数据
     * @return 整条链表的数据
     */
    @Override
    public String toString() {
        StringBuilder allData = new StringBuilder();
        Node temp = head;  // 使用临时结点
        while(temp!=null)
        {
            allData.append(temp.getData()).append(" -> ");
            temp = temp.getNext();
        }
        allData.delete(allData.length()-4, allData.length());  // " -> " 占 4 个字符
        return allData.toString();
    }
}

测试:

Link link = new Link();
System.out.println(link);  // 空链表

link.add("第一结点");
link.add("第二结点");  // 以默认形式加入两个结点
System.out.println(link);
System.out.println(link.length());  // 获取链表长度

link.add(0, "插入的第三结点");
System.out.println(link);
link.add(1, "插入的第四结点");
System.out.println(link);
link.add(link.length(), "插入的第五结点");
System.out.println(link);  // 测试两个端点以及从中间插入

link.addHead("插入的头结点");
System.out.println(link);
link.addLast(1200);
System.out.println(link);  // 测试头尾插入两个方法

System.out.println(link.remove(2));  // 测试删除方法
System.out.println(link);

运行结果:

第一结点 -> 第二结点
2
插入的第三结点 -> 第一结点 -> 第二结点
插入的第三结点 -> 插入的第四结点 -> 第一结点 -> 第二结点
插入的第三结点 -> 插入的第四结点 -> 第一结点 -> 第二结点 -> 插入的第五结点
插入的头结点 -> 插入的第三结点 -> 插入的第四结点 -> 第一结点 -> 第二结点 -> 插入的第五结点
插入的头结点 -> 插入的第三结点 -> 插入的第四结点 -> 第一结点 -> 第二结点 -> 插入的第五结点 -> 1200
true
插入的头结点 -> 插入的第三结点 -> 第一结点 -> 第二结点 -> 插入的第五结点 -> 1200

以上纯个人思路,如果存在漏洞或者有改善方法的话,还请多多指出~


不断积累实战经验 —— Level Up ⬆⬆⬆ (寒冰小澈)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒冰小澈IceClean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值