Java实现单链表

一、IList

IList 是一个链表操作规范接口,它只规定要实现什么函数,具体实现内容在别的地方,代码如下。

java 复制代码
public interface IList {
    void addFirst(int data);
    void addLast(int data);
    void addIndex(int index,int data);
    boolean contains(int key);
    void remove(int key);
    void removeAllKey(int key);
    int size();
    void clear();
    void display();
}

二、MySingleList

MySingleList是一个单链表实现类,实现了接口 IList 中规定的所有操作功能,包括头插、尾插、任意位置插入、查找、删除、统计长度、清空和遍历等。内部使用 ListNode 节点类,通过 next 指针把节点串成一条链。代码如下。

java 复制代码
public class MySingleList implements IList{

    static class ListNode{
        public int val;
        public ListNode next;

        public ListNode(int val){
            this.val=val;
        }
    }

    public ListNode head;

    public void creatList(){

        ListNode node1=new ListNode(12);
        ListNode node2=new ListNode(23);
        ListNode node3=new ListNode(34);
        ListNode node4=new ListNode(45);
        ListNode node5=new ListNode(56);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;

        this.head=node1;
    }
    @Override
    public void addFirst(int data) {
        ListNode node=new ListNode(data);
        if(this.head==null)
        {
            this.head=node;
        }else {
            node.next=this.head;
            this.head=node;
        }
    }

    @Override
    public void addLast(int data) {
        ListNode node=new ListNode(data);
        ListNode cur=this.head;
        if(this.head==null){
            this.head=node;
        }else{
            while(cur.next!=null){
                cur=cur.next;
            }
            cur.next=node;
        }
    }

    private ListNode searchPrev(int index){
        ListNode cur=this.head;
        int count=0;
        while(count!=index-1)
        {
            cur=cur.next;
            count++;
        }
        return cur;
    }
    @Override
    public void addIndex(int index, int data) {
        if(index<0||index>size()){
            return;
        }
        if(index==0){
            addFirst(data);
            return;
        }
        if(index==size()){
            addLast(data);
            return;
        }
        ListNode cur=searchPrev(index);
        ListNode node=new ListNode(data);
        node.next=cur.next;
        cur.next=node;
    }

    @Override
    public boolean contains(int key) {
        ListNode cur=this.head;
        while(cur!=null)
        {
            if(cur.val==key){
                return true;
            }
            cur=cur.next;
        }
        return false;
    }

    private ListNode findPrev(int key){
        ListNode cur=this.head;
        while(cur.next!=null){
            if(cur.next.val==key){
                return cur;
            }
            cur=cur.next;
        }
        return null;
    }

    @Override
    public void remove(int key) {
        if(this.head==null){
            return;
        }
        if(this.head.val==key){
            this.head=this.head.next;
            return;
        }
        ListNode cur=findPrev(key);
        if (cur == null) {
            System.out.println("没找到");
            return;
        }
        ListNode del=cur.next;
        cur.next=del.next;
    }


    @Override
    public void removeAllKey(int key) {
        if(this.head==null){
            return;
        }
        if(head.val==key){
            head=head.next;
        }
        ListNode prev=head;
        ListNode cur=head.next;
        while(cur!=null){
            if(cur.val==key){
                prev.next=cur.next;
                cur=cur.next;
            }else{
                prev=cur;
                cur=cur.next;
            }
        }
    }

    @Override
    public int size() {
        int count=0;
        ListNode cur=head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }

    @Override
    public void clear() {
        ListNode cur=head;
        while(cur!=null){
            ListNode curNext=cur.next;
            cur.next=null;
            cur=curNext;
        }
        head=null;
    }

    @Override
    public void display() {
        ListNode cur=this.head;
        while(cur!=null){
            System.out.print(cur.val+" ");
            cur=cur.next;
        }
        System.out.println();
    }
}

creatList()通过手动创建多个节点对象,然后用 next 指针把它们依次连接起来,这样可以快速得到一条固定数据的链表。

addFirst(int data)用于头插新节点。首先创建一个新节点,如果链表为空,直接让 head 指向该节点即可;如果链表不为空,就先让新节点的 next 指向当前头节点,再让 head 指向新节点,这样新节点就成为新的第一个节点。

addLast(int data)用于尾插新节点。先创建新节点,如果链表为空,直接让 head 指向它;如果不为空,就从头节点开始遍历,找到最后一个节点,再让这个节点的 next 指向新节点,从而把新节点接到链表末尾。

searchPrev(int index)这个私有方法用于查找指定下标位置的前一个节点。从头节点开始遍历,用计数器记录当前位置,当计数器等于 index - 1 时停止,此时返回的节点正好是目标插入位置的前驱节点。

addIndex(int index, int data)该方法用于在指定下标位置插入新节点。首先判断下标是否合法,如果非法直接返回;如果插入位置是 0,就调用 addFirst();如果插入位置是链表长度,就调用 addLast();否则通过 searchPrev(index) 找到前驱节点,再把新节点插入到前驱节点与其后继节点之间。

contains(int key)该方法用于判断链表中是否存在指定值。从头节点开始遍历链表,只要发现某个节点的值等于 key,就立即返回 true;如果遍历完整个链表仍未找到,则返回 false

findPrev(int key)这个私有方法用于查找第一个值为 key 的节点的前驱节点。从头节点开始遍历,如果发现 cur.next.val == key,就返回当前节点 cur;如果遍历到尾部仍未找到,则返回 null,表示链表中不存在该值。

remove(int key)该方法用于删除链表中第一次出现的指定值节点。若链表为空直接返回;如果头节点的值等于 key,则直接让 head 指向第二个节点完成删除;否则通过 findPrev(key) 找到目标节点的前驱节点,然后让该前驱节点跳过目标节点,即 cur.next = cur.next.next,从而完成删除。

removeAllKey(int key)该方法用于删除链表中所有值为 key 的节点。先单独处理头节点为 key 的情况,然后使用 prevcur 两个指针遍历链表:当 cur.val == key 时,让 prev.next 指向 cur.next 实现删除;否则两个指针同时向后移动,直到遍历结束。

size()该方法用于统计链表长度。从头节点开始遍历链表,每访问一个节点就让计数器加一,直到遍历到 null,最终返回计数值,即链表中节点的个数。

clear()该方法用于清空链表。通过遍历链表,将每个节点的 next 置为 null,断开节点之间的引用关系,最后将 head 置为 null,使链表恢复为空状态。

display()该方法用于输出链表中所有节点的值。从头节点开始遍历,每访问一个节点就打印其 val,直到遍历结束并换行,用于直观查看链表当前结构。

三、Test

下面是测试代码。

java 复制代码
public class Test {
    public static void main(String[] args) {
        MySingleList list = new MySingleList();

        System.out.println("=== 1. 测试 creatList ===");
        list.creatList();
        list.display();   // 12 23 34 45 56

        System.out.println("=== 2. 测试 addFirst ===");
        list.addFirst(100);
        list.display();   // 100 12 23 34 45 56

        System.out.println("=== 3. 测试 addLast ===");
        list.addLast(200);
        list.display();   // 100 12 23 34 45 56 200

        System.out.println("=== 4. 测试 addIndex ===");
        list.addIndex(3, 999);
        list.display();   // 100 12 23 999 34 45 56 200

        System.out.println("=== 5. 测试 contains ===");
        System.out.println(list.contains(34));   // true
        System.out.println(list.contains(888));  // false

        System.out.println("=== 6. 测试 remove ===");
        list.remove(100);   // 删头
        list.display();
        list.remove(999);   // 删中间
        list.display();
        list.remove(200);   // 删尾
        list.display();

        System.out.println("=== 7. 测试 removeAllKey ===");
        list.addLast(34);
        list.addLast(34);
        list.display();
        list.removeAllKey(34);
        list.display();

        System.out.println("=== 8. 测试 size ===");
        System.out.println(list.size());

        System.out.println("=== 9. 测试 clear ===");
        list.clear();
        list.display();   // 空
        System.out.println(list.size()); // 0
    }
}
相关推荐
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子5 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划6 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿6 小时前
Jsoniter(java版本)使用介绍
java·开发语言
2013编程爱好者6 小时前
【C++】树的基础
数据结构·二叉树··二叉树的遍历
NEXT066 小时前
二叉搜索树(BST)
前端·数据结构·面试
化学在逃硬闯CS6 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar1236 小时前
C++使用format
开发语言·c++·算法
探路者继续奋斗7 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd