单向链表-JAVA

 如果某个节点的next是null则代表该节点是最后一个节点,属性名为head的为第一个节点。

虚拟头结点(dummyHead)对于链表的使用者来说毫无意义,只是为了让头结点固定不改动、实现起来更方便而设计出来的一个概念。

 实现代码

package blacktv.linkedlist;

/**
 * 在008号文档编写的单向列表基础上,为提高在此基础上实现的队列的效率,牺牲了一些删除节点的速度,
 * 将从末尾添加节点的性能从O(n)提高到O(1)。
 */
public class LinkedList<E> {
    private Node dummyHead;//虚拟头结点,值为空
    private Node tail;//链表末尾的节点
    private Integer size;

    public LinkedList() {
        size = 0;
        tail = null;
        dummyHead = new Node(null, tail);
    }

    /**
     * 创建链表并添加一个元素
     *
     * @param e
     */
    public LinkedList(E e) {
        dummyHead = new Node(null, new Node(e));
        size = 1;
    }

    /**
     * 将指定值插入到本链表头,原本的链表头改为第二个元素
     *
     * @param e
     */
    public void addFirst(E e) throws Exception {
        this.inset(0, e);
    }

    /**
     * 在链表尾部添加一个元素
     *
     * @param e
     * @throws Exception
     */
    public void addLast(E e) throws Exception {
        if (tail == null)
            this.addFirst(e);
        else {
            tail.next = new Node(e);
            tail = tail.next;
            size++;
        }
    }

    /**
     * 将指定值插入到链表中的指定位置,(链表里没有索引,只是引用一下这个概念),从0开始数。
     *
     * @param index
     * @param e
     */
    public void inset(Integer index, E e) throws Exception {
        if (index < 0 || index > size)
            throw new Exception("索引值错误");
        else if (index.equals(size) && tail != null)
            this.addLast(e);
        else {
            Node buffer = dummyHead;
            for (Integer i = 0; i < index; i++) {
                buffer = buffer.next;
            }
            buffer.next = new Node(e, buffer.next);
            // 如果tail为空代表本次添加的元素是第一个元素,即是头结点也是尾节点
            if (tail == null)
                tail = buffer.next;
            size++;
        }
    }

    /**
     * 获取最后一个链表的元素
     *
     * @return
     * @throws Exception
     */
    public E getLast() throws Exception {
        return this.get(size - 1);
    }

    /**
     * 获取链表头一个元素
     *
     * @return
     * @throws Exception
     */
    public E getFirst() throws Exception {
        return this.get(0);
    }

    /**
     * 获取指定位置的元素,从0开始
     *
     * @param index
     * @return
     */
    public E get(Integer index) throws Exception {
        this.checkIndex(index);
        Node node = dummyHead.next;
        for (Integer i = 0; i < index; i++)
            node = node.next;
        return node.e;
    }

    /**
     * 更新指定位置元素的值,从0开始
     *
     * @param index
     * @param e
     * @throws Exception
     */
    public void update(Integer index, E e) throws Exception {
        this.checkIndex(index);
        Node node = dummyHead.next;
        for (Integer i = 0; i < index; i++)
            node = node.next;
        node.e = e;
    }

    /**
     * 查询链表中是否包含指定元素
     *
     * @param e
     * @return
     */
    public Boolean contains(E e) {
        Node node = dummyHead.next;
        while (node != null) {
            if (node.e.equals(e))
                return true;
            node = node.next;
        }
        return false;
    }

    /**
     * 删除指定元素的节点,如果不存在该节点则什么也不做
     *
     * @param e
     * @return
     */
    public void removeElement(E e) {
        Node node = dummyHead.next;
        while (node != null) {
            if (node.next.e.equals(e)) {
                Node deleteNode = node.next;
                node.next = deleteNode.next;
                deleteNode = null;//jvm回收
                size--;
                break;
            }
            node = node.next;
        }
    }

    /**
     * 删除指定位置的元素,从0开始
     *
     * @param index
     * @throws Exception
     */
    public E delete(Integer index) throws Exception {
        this.checkIndex(index);
        Node buffer = dummyHead;//因为这里获取的虚拟空节点,所以下面i<index而不是i<index-1
        Node deleteNode = null;
        for (Integer i = 0; i < index; i++)
            buffer = buffer.next;
        deleteNode = buffer.next;// 获取到要删除的节点
        buffer.next = deleteNode.next;//覆盖掉要删除的节点
        if (index.equals(size))
            tail = buffer;
        E e = deleteNode.e;
        deleteNode = null;// 这是为了让JVM回收垃圾
        size--;
        return e;
    }

    /**
     * 删除最后一个元素
     *
     * @return
     * @throws Exception
     */
    public E deleteLast() throws Exception {
        return this.delete(size - 1);
    }

    /**
     * 删除第一个元素
     *
     * @return
     * @throws Exception
     */
    public E deleteFirst() throws Exception {
        return this.delete(0);
    }

    /**
     * 获取链表的元素个数
     *
     * @return
     */
    public Integer getSize() {
        return size;
    }

    /**
     * 链表是否为空
     *
     * @return
     */
    public Boolean isEmpty() {
        return size == 0;
    }

    @Override
    public String toString() {
        String string = "size:" + size + "\tLinkedList[";
        //若不用虚拟节点,那么这里不用.next,因为dummyHead是个空节点不展现给用户
        Node buffer = dummyHead.next;
        for (Integer i = 0; i < size; i++) {
            string += buffer.e;
            buffer = buffer.next;
            if (i != size - 1)
                string += ", ";
        }
        string += "]";
        // 最右边是头
        return string;
    }

    private void checkIndex(Integer index) throws Exception {
        if (index < 0 || index >= size)
            throw new Exception("索引值错误");
    }

    /**
     * 用个内部类编写节点,对使用者屏蔽实现细节
     */
    private class Node {
        public E e;
        public Node next;

        public Node(E e) {
            this.e = e;
        }

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public Node() {
        }

        @Override
        public String toString() {
            return e.toString();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值