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

1. 双向链表同单向链表一样,同sentinelLinkedList相同的方法,感觉还没有单向链表难。Node 结构 新增prev node,容器外新增tail节点

2. 建议先不要看我写得源码自己手动实现,只将Node内部类复制自己命名得容器内,

    实现方法:

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

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

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

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

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

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

package com.nami.algorithm.study.day04;

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: [email protected]
 * @Description: keep coding
 */
public class DoublyLinkedList<E> implements Serializable, Iterable<E>, Cloneable {

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

    /**
     * 头节点
     */
    private Node head;

    /**
     * 尾部节点
     */
    private Node tail;


    /**
     * 初始化哨兵
     */
    public DoublyLinkedList() {
        this.head = new Node(null, "head", null);
        this.tail = new Node(null, "tail", null);
        this.head.next = this.tail;
        this.tail.prev = this.head;
    }

    /**
     * 向链表添加数据
     *
     * @param element 添加的元素
     */
    public void addFirst(E element) {
        add(0, element);
    }

    /**
     * 向链表尾部添加数据
     *
     * @param element
     */
    public void addLast(E element) {
//        Node prev = this.tail.prev;
//        Node insertNode = new Node(prev, element, this.tail);
//        prev.next = insertNode;
//        tail.prev = insertNode;
//        ++this.size;
        add(size - 2, element);
    }

    private Node getNode(int index) {
        Node p = this.head;
        for (int i = -1; p != tail; p = p.next, i++) {
            if (i == index) {
                return p;
            }
        }
        return null;
    }

    /**
     * 获取容器指定位置的值
     *
     * @param index
     * @return
     */
    public E get(int index) {
        if (index > size - 2) {
            throw new IndexOutOfBoundsException("元素不存在");
        }

        Node node = getNode(index);
        return (E) node.value;
    }


    /**
     * 向元素指定节点添加值
     *
     * @param index
     * @param e
     */
    public void add(int index, E e) {
        Node prev = getNode(index - 1);
        if (prev == null) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }
        Node next = prev.next;
        Node insertNode = new Node(prev, e, next);
        // 这个好想出来
        prev.next = insertNode;
        // 此节点调试下就调好了。
        next.prev = insertNode;
        ++this.size;
    }

    /**
     * 移除容器内第一个元素
     */
    public void removeFirst() {
        remove(0);
    }

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

        // index =0 返回的是哨兵
        Node prev = getNode(index - 1);
        if (null == prev) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }
        Node needRemoveNode = prev.next;
        if (needRemoveNode == tail) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }
        // 返回删除节点得下一个节点
        Node next = needRemoveNode.next;
        prev.next = next;
        next.prev = prev;
        --this.size;
    }

    /**
     * 删除最后一个节点
     */
    public void removeLast() {
        Node prev = this.tail.prev;
        if (prev == this.head) {
            return;
        }
        Node prev1 = prev.prev;
        prev1.next = this.tail;
        tail.prev = prev1;
        --this.size;
    }

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

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

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

        Node node = head.next;
        private int nextIndex;

        @Override
        public boolean hasNext() {
            return nextIndex < DoublyLinkedList.this.size - 2;
        }

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

    /**
     * while实现
     *
     * @param consumer
     */
    public void forEach(Consumer consumer) {
        Node firstNode = this.head.next;
        while (firstNode != null && firstNode != this.tail) {
            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;
        }

    }

}

猜你喜欢

转载自blog.csdn.net/qq_33919114/article/details/132661627