双向链表的模拟实现 —— LinkedList

MyLinkedList类

java 复制代码
public class MyLinkedList {
    // 定义节点类
    static class Node {
        int val;
        Node prev;
        Node next;

        public Node() {

        }

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

    // 定义头节点
    private Node head;
    // 定义尾结点
    private Node tail;

    // 头插
    public void headInsert(int val) {
        // 申请节点
        Node node = new Node(val);
        // 判空
        if (head == null) {
            // head 和 tail 都指向 node
            head = node;
            tail = node;
            return;
        }
        // head 不为空,则进行头插
        node.next = head;
        head.prev = node;
        // 重置头节点
        head = node;
    }

    // 尾插
    public void tailInsert(int val) {
        // 申请节点
        Node node = new Node(val);

        // 判空
        if (head == null) {
            head = node;
            tail = node;
            return;
        }

        // 非空情况下进行尾插
        tail.next = node;
        node.prev = tail;
        // 重置尾结点
        tail = node;
    }

    // 在 index 处插入元素
    public void randomInsert(int index, int val) {
        // 判空
        if (head == null) return;
        // 下标判断
        if (index < 0 || index > size()) {
            throw new IndexOfLinkedListException("下标 index :" + index + " 出现异常!");
        }

        // 头插
        if (index == 1) {
            headInsert(val);
            return;
        }
        // 尾插
        if (index == size()) {
            tailInsert(val);
            return;
        }

        // 找到要插入的位置
        Node cur = head;
        Node node = new Node(val);
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }

        // 进行插入
        cur.prev.next = node;
        node.next = cur;
        node.prev = cur.prev;
        cur.prev = node;
    }

    // 删除与 val 相等的元素节点
    public void remove(int val) {
        // 判空
        if (head == null) return;

        Node cur = head;
        while (cur != null) {
            // 值相等,进行删除
            if (cur.val == val) {
                // 头节点的情况
                if (cur == head) {
                    head = head.next;
                    head.prev = null;
                    break;
                }
                // 尾结点的情况
                if (cur == tail) {
                    tail = tail.prev;
                    tail.next = null;
                    break;
                }

                // 中间节点删除
                cur.prev.next = cur.next;
                cur.next.prev = cur.prev;
            }
            cur = cur.next;
        }
    }


    // 删除 index 处的元素
    public void removeOfIndex(int index) {
        // 判空
        if (head == null) return;

        // 下标判断
        if (index < 0 || index > size()) {
            throw new IndexOfLinkedListException("下标 index :" + index + " 出现异常!");
        }

        // 头删
        if (index == 1) {
            head = head.next;
            head.prev = null;
            return;
        }

        // 尾删
        if (index == size()) {
            tail = tail.prev;
            tail.next = null;
            return;
        }

        // 找到要删除的位置
        Node cur = head;
        for (int i = 1; i < index; i++) {
            cur = cur.next;
        }

        // 进行删除操作
        cur.prev.next = cur.next;
        cur.next.prev = cur.prev;
    }


    // 删除所有与 val 相等的节点
    public void removeAllVal(int val) {
        // 判空
        if (head == null) return;

        // 判断 val 值是否在链表中出现
        if (!contains(val)) return;

        // 从头节点开发判断
        Node cur = head;
        while (cur != null) {
            // 相等则进行删除
            if (cur.val == val) {
                // 是头节点的情况
                if (head == cur) {
                    // head 走到下一个节点处
                    head = head.next;
                    head.prev = null;
                } else if (tail == cur) {
                    // tail 走到上一个节点处
                    tail = tail.prev;
                    tail.next = null;
                } else {
                    // 中间节点,让删除节点的前一个节点和后一个节点进行连接
                    cur.next.prev = cur.prev;
                    cur.prev.next = cur.next;
                }
            }
            // 注意,cur 无论是否删除了当前节点,都应该要走到下一步
            cur = cur.next;
        }
    }

    // 查找 val 第一次出现的下标
    public int indexOf(int val) {
        // 判空
        if (head == null) return -1;

        Node cur = head;
        for (int i = 1; i < size() + 1; i++) {
            // 找到了
            if (cur.val == val) {
                return i;
            }
            cur = cur.next;
        }
        // 没找到
        return -1;
    }

    // 查找 val 最后一次出现的下标
    public int lastOfIndex(int val) {
        // 判空
        if (head == null) return -1;

        int index = -1;
        Node cur = tail;
        for (int i = size(); i > 0; i--) {
            // 找到了
            if (cur.val == val) {
                index = i;
            }
            cur = cur.prev;
        }
        // 没找到
        return index;
    }

    // 判断 val 是否在链表中
    public boolean contains(int val) {
        // 判空
        if (head == null) return false;

        Node cur = head;
        while (cur != null) {
            // 找到了
            if (cur.val == val) {
                return true;
            }
            cur = cur.next;
        }
        // 没找到
        return false;
    }

    // 获取元素个数
    public int size() {
        Node cur = head;
        // 获取链表中的元素个数
        int count = 0;

        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    // 打印链表
    public void display() {
        Node cur = head;
        // 进行打印操作
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        // 换行
        System.out.println();
    }

    // 清空链表
    public void clear() {
        Node cur = head;

        // 把每个节点都置为 null
        while (cur != null) {
            Node tmp = cur.next;
            cur.next = null;
            cur.prev = null;
            cur = tmp;
        }

        // 头节点和尾结点置空
        head = null;
        tail = null;
    }
}

IndexOfLinkedListException类

java 复制代码
public class IndexOfLinkedListException extends RuntimeException {
    public IndexOfLinkedListException() {
    }

    public IndexOfLinkedListException(String message) {
        super(message);
    }
}

Test类

java 复制代码
public class Test {
    public static void main(String[] args) {
        MyLinkedList linkedList = new MyLinkedList();
        // 头插
        linkedList.headInsert(1);
        linkedList.headInsert(2);
        linkedList.headInsert(3);
        // 打印链表
        linkedList.display();
        // 获取长度
        System.out.println(linkedList.size());

        // 尾插
        linkedList.tailInsert(4);
        linkedList.tailInsert(5);
        linkedList.tailInsert(6);
        linkedList.display();
        System.out.println(linkedList.size());

        // 任意位置插入
        linkedList.randomInsert(1, 7);
        linkedList.randomInsert(1, 7);
        linkedList.randomInsert(1, 7);
        linkedList.randomInsert(8, 8);
        linkedList.display();
        linkedList.randomInsert(8, 7);
        linkedList.display();
        linkedList.randomInsert(8, 8);
        linkedList.display();
        System.out.println(linkedList.size());
        linkedList.randomInsert(2, 111);
        linkedList.randomInsert(3, 111);
        linkedList.display();
        System.out.println(linkedList.size());

        // 删除所有和 val 相等的节点
        linkedList.removeAllVal(7);
        linkedList.display();
        System.out.println(linkedList.size());

        // 删除链表中第一个 val 相等的节点
        linkedList.remove(111);
        linkedList.remove(6);
        linkedList.remove(3);
        linkedList.display();
        System.out.println(linkedList.size());

        // 删除 index 处的节点
        linkedList.removeOfIndex(1);
        linkedList.removeOfIndex(6);
        linkedList.removeOfIndex(2);
        linkedList.display();
        System.out.println(linkedList.size());

        // 找到 val 第一次出现的位置
        System.out.println(linkedList.indexOf(2));
        System.out.println(linkedList.indexOf(8));

        // 找到val 最后一次出现的位置
        System.out.println(linkedList.lastOfIndex(2));
        System.out.println(linkedList.lastOfIndex(8));

        // 清空链表
        linkedList.clear();
        System.out.println(linkedList.size());
    }
}
相关推荐
Yeats_Liao5 分钟前
Spring 框架:配置缓存管理器、注解参数与过期时间
java·spring·缓存
Yeats_Liao5 分钟前
Spring 定时任务:@Scheduled 注解四大参数解析
android·java·spring
码明5 分钟前
SpringBoot整合ssm——图书管理系统
java·spring boot·spring
某风吾起9 分钟前
Linux 消息队列的使用方法
java·linux·运维
xiao-xiang13 分钟前
jenkins-k8s pod方式动态生成slave节点
java·kubernetes·jenkins
取址执行24 分钟前
Redis发布订阅
java·redis·bootstrap
墨楠。26 分钟前
数据结构学习记录-树和二叉树
数据结构·学习·算法
小唐C++32 分钟前
C++小病毒-1.0勒索
开发语言·c++·vscode·python·算法·c#·编辑器
S-X-S37 分钟前
集成Sleuth实现链路追踪
java·开发语言·链路追踪
快乐就好ya1 小时前
xxl-job分布式定时任务
java·分布式·spring cloud·springboot