双向链表实现元素存取容器

1.基于链表结构存取元素的方法API定义

package com.bjsxt;

/**
 * @Author:Dai
 * @Date:2022/4/23 基于链表结构存取元素的方法API定义
 */
public interface MyList<E> {

    void add(E element);

    E get(int index);

    int size();

    E remove(int index);

}

2.基于双向链表实现元素存取容器

package com.bjsxt;

import java.util.List;

/**
 * @Author:Dai
 * @Date:2022/4/24 基于双向链表实现元素存取容器
 */
public class MyDoublyLinkedList<E> implements MyList<E> {

    /**
     * 定义双向链表的节点对象
     */
    class Node<E> {
        E item;//记录元素
        Node<E> prev;//记录前一个节点对象
        Node<E> next;//记录下一个节点对象

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


    private Node head;//记录头节点
    private Node tail;//记录尾节点
    private int size;//记录元素个数

    /**
     * 向双向链表中添加元素
     *
     * @param element
     */
    @Override
    public void add(E element) {
        this.linkLast(element);
    }

    /**
     * 将节点对象添加到双向链表的尾部
     */
    private void linkLast(E element) {
        //获取尾节点
        Node t = this.tail;
        //创建节点对象
        Node<E> node = new Node<>(t, element, null);
        //将新节点定义为尾节点
        this.tail = node;
        if (t == null) {
            this.head = node;
        } else {
            t.next = node;
        }
        this.size++;
    }

    /**
     * 根据指定位置获取元素
     *
     * @param index
     * @return
     */
    @Override
    public E get(int index) {
        //对Index做合法性校验
        this.checkIndex(index);
        //根据位置查找节点对象
        Node<E> node = this.getNode(index);
        return node.item;
    }

    /**
     * 校验Index合法性
     */
    private void checkIndex(int index) {
        if (!(index >= 0 && index < this.size)) {
            throw new IndexOutOfBoundsException("Index:" + index + "Size:" + this.size);
        }
    }

    /**
     * 根据位置获取指定节点对象
     */
    private Node getNode(int index) {
        //判断当前位置距离头或者尾哪个节点更近
        if (index < (this.size >> 1)) {
            Node node = this.head;
            for (int i = 0; i < index; i++) {
                node = node.next;
            }
            return node;
        } else {
            Node node = this.tail;
            for (int i = this.size - 1; i > index; i--) {
                node = node.prev;
            }
            return node;
        }
    }


    /**
     * 返回元素个数
     *
     * @return
     */
    @Override
    public int size() {
        return this.size;
    }

    /**
     * 根据指定位置删除元素
     *
     * @param index
     * @return
     */
    @Override
    public E remove(int index) {
        //校验Index合法性
        this.checkIndex(index);
        //根据指定位置获取节点对象
        Node<E> node = this.getNode(index);
        //获取节点对象中的元素
        E item = node.item;
        //判断当前节点是否为头节点
        if (node.prev == null) {
            this.head = node.next;
        } else {
            //完成当前节点的直接前驱节点与当前节点的直接后继节点挂接
            node.prev.next = node.next;
        }
        //判断当前节点是否为尾节点
        if (node.next == null) {
            this.tail = node.prev;
        } else {
            //完成当前当前节点的直接后继节点与节点的直接前驱节点挂接
            node.next.prev = node.prev;
        }
        //当前节点断掉与直接前驱节点和直接后继节点的连接
        node.prev = null;
        node.next = null;
        node.item = null;
        this.size--;
        return item;
    }

    /**
     * 再双向链表的头添加元素
     */
    public void addFirst(E element) {
        this.linkFirst(element);
    }

    /**
     * 在链表的头添加元素
     */
    private void linkFirst(E element) {
        //获取头节点对象
        Node head = this.head;
        Node node = new Node(null, element, head);
        //将新节点定义为头节点
        this.head = node;
        //判断当前链表中是否有节点,如果没有,该节点既是头节点,也是尾节点
        if (head == null) {
            this.tail = node;
        } else {
            head.prev = node;
        }
        this.size++;
    }

    /**
     * 在链表中的尾部添加元素
     */
    public void addLast(E element) {
        this.linkLast(element);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值