双向链表的模拟实现 —— 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());
    }
}
相关推荐
人需要PID1 分钟前
【C语言练习(5)—回文数判断】
c语言·开发语言·学习·算法
喜欢AC~不爱WA7 分钟前
简单的Java小项目
java·开发语言
互联网动态分析12 分钟前
Apache Kafka:实时数据流处理的强大引擎
java·kafka
泰山小张只吃荷园16 分钟前
期末复习-计算机网络篇
java·网络·网络协议·计算机网络·面试
qq85722263119 分钟前
java+springboot+mysql科研成果管理系统
java·spring boot·mysql
m0_7482526031 分钟前
用Maven开发Spring Boot 项目
java·spring boot·maven
小五Z32 分钟前
高阶数据结构--B树&&B+树实现原理&&B树模拟实现--Java
java·数据结构·b树·算法
卜及中34 分钟前
【数据结构】B树家族解析:B树、B+树与B*树的理论与B树插入实现(C++)
开发语言·数据结构·c++·b树
机智阳35 分钟前
介绍一个InnoDB的数据页,和B+树的关系是什么?
java·数据结构·分布式·后端·b树
toto41235 分钟前
红黑树和B+树
数据结构·b树·算法