算法 数据结构 双向环形链表 手撸环形链表 环形链表实现容器 环形链表添加修改删除获取大小 环形链表实现自定义容器 手撸容器 双向环形哨兵链表 数据结构(六)

  1. 环形链表:
  1. 建议先不要看我写得自己先实现下,只将Node内部类复制自己命名得容器内,

实现方法:

a. add方法(添加到头部,尾部添加,指定位置添加)

b. get方法(获取首部,获取尾部,获取指定位置)

c. remove方法(删除首部,删除尾部,删除指定位置)

d. size方法(手动维护一个size变量,实现0(1)复杂度 )

e. 迭代器(实现迭代器,能够循环遍历)

手动实现之后(每个功能只实现一种也可以),再回头参照,思考下即可!

java 复制代码
package com.nami.algorithm.study.day05;

import java.io.Serializable;
import java.util.Iterator;
import java.util.function.Consumer;

/**
 * 环形双向哨兵链表
 * 非线程安全
 * beyond u self and trust u self.
 *
 * @Author: lbc
 * @Date: 2023-09-01 9:07
 * @email: 594599620@qq.com
 * @Description: keep coding
 */
public class RingLinkedList<E> implements Serializable, Iterable<E>, Cloneable {

    /**
     * 容器已添加的元素
     */
    private int size = 1;

    /**
     * 哨兵节点
     */
    private Node sentinel = new Node(null, "-1", null);

    /**
     * 初始化哨兵
     */
    public RingLinkedList() {
        this.sentinel.prev = this.sentinel;
        this.sentinel.next = this.sentinel;
    }

    /**
     * 向链表添加数据
     *
     * @param element 添加的元素
     */
    public void addFirst(E element) {
        Node first = this.sentinel;
        Node next = first.next;
        Node node = new Node<>(first, element, next);
        first.next = node;
        next.prev = node;
        ++this.size;
    }

    /**
     * 向链表尾部添加数据
     *
     * @param element
     */
    public void addLast(E element) {
        Node last = this.sentinel.prev;
        Node node = new Node<>(last, element, sentinel);
        last.next = node;
        sentinel.prev = node;
        ++this.size;
    }
    
    /**
     * 获取容器指定位置的值
     *
     * @param index
     * @return
     */
    public E get(int index) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException("元素不存在");
        }
        Node next = sentinel.next;

        for (int i = 0; i < index; next = next.next, i++) {
        }
        if (sentinel == next) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }
        return (E) next.value;
    }

    /**
     * 获取指定位置节点node
     *
     * @param index
     * @return
     */
    private Node getNode(int index) {
        Node next = sentinel.next;

        for (int i = 0; i < index; next = next.next, i++) {
        }

        return next;
    }

    /**
     * 向元素指定节点添加值
     *
     * @param index
     * @param e
     */
    public void add(int index, E e) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException("元素不存在");
        }
        Node node = getNode(index);

        Node prev = node.prev;

        Node node1 = new Node(prev, e, node);
        node.prev = node1;
        prev.next = node1;
        ++this.size;
    }

    /**
     * 移除容器内第一个元素
     */
    public void removeFirst() {
        Node node = getNode(0);
        if (sentinel == node) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", 0));
        }
        Node prev = node.prev;
        Node next = node.next;
        prev.next = next;
        next.prev = prev;
        --this.size;
    }

    /**
     * 删除第一个元素
     */
    public void removeFirst0() {
        Node removed = this.sentinel.next;

        if (removed == this.sentinel) {
            throw new IndexOutOfBoundsException("容器内已无元素");
        }
        Node next = removed.next;

        this.sentinel.next = next;
        next.prev = this.sentinel;
    }

    /**
     * 移除容器内指定位置元素
     *
     * @param index
     */
    public void remove(int index) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }

        Node node = getNode(index);

        if (sentinel == node) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", 0));
        }

        Node prev = node.prev;

        Node next = node.next;

        prev.next = next;
        next.prev = prev;
        --this.size;
    }

    /**
     * 删除最后一个节点
     */
    public void removeLast() {
        Node prev = this.sentinel.prev;
        if (prev == this.sentinel) {
            return;
        }

        Node next = prev.next;
        Node prev0 = prev.prev;
        prev0.next = next;
        next.prev = prev0;
        --this.size;
    }

    /**
     * 获取容器大小
     *
     * @return
     */
    public int size() {
        return this.size - 1;
    }

    /**
     * 迭代器遍历
     *
     * @return
     */
    @Override
    public Iterator iterator() {
        return new NodeIterator();
    }

    /**
     * 匿名内部类
     * 内部类使用到了外部类的成员变量时,不能使用static修饰
     */
    private class NodeIterator implements Iterator {
        Node node = sentinel.next;

        @Override
        public boolean hasNext() {
            return node != sentinel;
        }

        @Override
        public Object next() {
            Object value = node.value;
            node = node.next;
            return value;
        }
    }

    /**
     * while实现
     *
     * @param consumer
     */
    public void forEach(Consumer consumer) {
        Node firstNode = this.sentinel.next;
        while (firstNode != sentinel) {
            consumer.accept(firstNode.value);
            firstNode = firstNode.next;
        }
    }

    /**
     * Node类型 节点对象
     * 二者为组合关系,所以 由外部类变为内部类,对外隐藏实现细节
     */
    private static class Node<E> {

        /**
         * 上一个节点
         */
        private Node<E> prev;

        /**
         * 值
         */
        private E value;

        /**
         * 下一个节点
         */
        private Node<E> next;


        public Node(Node<E> prev, E value, Node<E> next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }

    }

}
相关推荐
侯小啾21 分钟前
【03】C语言 强制类型转换 与 进制转换
c语言·数据结构·算法
Xの哲學44 分钟前
Linux NAPI 架构详解
linux·网络·算法·架构·边缘计算
京东零售技术4 小时前
扛起技术大梁的零售校招生们 | 1024技术人特别篇
算法
爱coding的橙子5 小时前
每日算法刷题Day78:10.23:leetcode 一般树7道题,用时1h30min
算法·leetcode·深度优先
Swift社区5 小时前
LeetCode 403 - 青蛙过河
算法·leetcode·职场和发展
地平线开发者5 小时前
三种 Badcase 精度验证方案详解与 hbm_infer 部署实录
算法·自动驾驶
papership5 小时前
【入门级-算法-5、数值处理算法:高精度的减法】
算法·1024程序员节
lingran__5 小时前
算法沉淀第十天(牛客2025秋季算法编程训练联赛2-基础组 和 奇怪的电梯)
c++·算法
DuHz5 小时前
基于MIMO FMCW雷达的二维角度分析多径抑制技术——论文阅读
论文阅读·物联网·算法·信息与通信·毫米波雷达
一二学长6 小时前
快速排序(JAVA详细讲解快速排序的四种方式)
数据结构