链表基本的增、删、查

package com.mayikt.linkedlistsource;

import com.mayikt.CustomerException;

/**
 * 链表的获取
 *
 * @author zx
 * @date 2022年01月27日 13:56
 */
public class LinkedListExt<E> {
    //定义 first 、Node 标识结点,便于后期操作

    /**
     * 第一个节点
     */
    transient Node<E> first;

    /**
     * 最后一个节点
     */
    transient Node<E> last;

    /**
     * 链表中的个数
     */
    transient int size = 0;

    /**
     * 链表的结点
     *
     * @param <E>
     */
    private static class Node<E> {
        E item;
        Node<E> prev;
        Node<E> next;

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

    /**
     * 添加元素
     *
     * @param e 添加的元素
     * @return true 表示添加成功
     */
    public boolean add(E e) {
        //添加到链表的末尾
        addLinketLast(e);
        return true;
    }

    private void addLinketLast(E e) {
        //先假设 链表中已经有数据结点  ----final 防止引用被改变
        final Node<E> temp = last;
        //添加的结点都是往链表末尾添加,即next结点都为空
        final Node<E> newNode = new Node<>(e, last, null);
        //新添加的结点放到末尾。使用last结点记录末尾结点
        last = newNode;
        if (temp == null) {
            //说明第一次添加
            first = newNode;
        } else {
            //构建链表的关系
            temp.next = newNode;
        }

        size++;

    }

    private void checkElementIndex(int index) {
        if (!(index >= 0 && index < size)) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }


    public E get(int index) {
        //检查索引是否越界
        checkElementIndex(index);
        return node(index).item;
    }

    //使用折半查找,此折 非比折
    private Node<E> node(int index) {
        if (index < (size >> 1)) {
            //index 在 size/2 的 左边,从first 结点循环遍历去找 截止点位 size/2
            Node<E> x = first;
            //往下循环去找 first --->index
            for (int i = 0; i < index; i++) {
                x = x.next;
            }

            return x;
        } else {
            //从last循环遍历往上找,  last ----> index
            Node<E> x = last;
            for (int i = size - 1; i > index; i--) {
                x = x.prev;
            }
            return x;
        }

    }


    public E remove(int index) {
        //检查索引是否越界
        checkElementIndex(index);
        return unLinkedList(node(index));

    }

    private E unLinkedList(Node<E> currentNode) {

        //改变链表引用关系
        Node<E> currentPrev = currentNode.prev;
        Node<E> currentNext = currentNode.next;

        //如果是first 、last结点 分两个结点去改变引用

        //如果删除的是firstNode
        if (currentPrev == null) {
            first = currentNext;
        } else {

            currentPrev.next = currentNext;
            //释放了当前结点上一个结点的引用  ,还有下一个结点的引用没有释放
            currentNode.prev = null;
        }

        //如果删除的是最后一个结点
        if (currentNext == null) {
            //说明删除的是最后一个结点
            last = currentPrev;
        } else {
            currentNext.prev = currentPrev;
            currentNode.next = null;
        }


        currentNode.item = null;
        size--;
        return currentNode.item;
    }


    public void showLinkedList() throws CustomerException {
        checkLinkedListIsEmpty();

        Node<E> temp = first;

        while (true) {
            System.out.println(temp.item);
            if (temp.next == null) {
                //链表遍历到最后了
                break;
            }
            temp = temp.next;

        }
    }

    /**
     * 检查链表是否为空
     */
    private void checkLinkedListIsEmpty() throws CustomerException {
        if (first == null) {
            throw new CustomerException("链表为空");
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值