LinkedList实现

LinkedList实现

  本节给出LinkedList的实现,命名为MyLinkedList。采用普遍的双链表,与ArrayList相比,可以较快地进行插入和删除操作,只需要将元素的指针指向改变即可,实现常数次操作。保存该链表的首末段指针(引用),保证对头尾元素的访问为O(1),并且,如果已知访问元素的位置,就可以决定从哪个端点开始遍历,一定程度上补偿链表的访问速度问题,双端列表的简单结构如下图。

链表结构图

功能描述

  • MyLinkedList包含链表两端,大小以及一些常用方法;
  • Node类,用来描述链表节点,包含自身数据、指向下一个节点和上一个节点的指针,以及一些适当的构造方法;
  • LinkedListIterator类,该类实现了Iterator接口,可以作为内部类或嵌套类在MyLinkedList内部实现,提供next(), hasNext(0和remove()方法实现。

代码实现

package com.yam.base;

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * LinkedList简单实现
 * @author: Ympery
 * @date: 2017/3/13 15:00.
 */
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
    
    

    /**
     * 链表长度
     */
    private int theSize;

    /**
     * 用于标记链表自构造起,对其的操作次数,防止并发错误
     */
    private int modCount = 0;

    /**
     * 整个链表的头结点
     */
    private Node<AnyType> beginMarker;
    /**
     * 整个链表的尾节点
     */
    private Node<AnyType> endMarker;

    public MyLinkedList() { clear(); }

    /**
     * 清除链表,当链表为null时,只有头尾
     */
    public void clear() {
        beginMarker = new Node<>(null, null, null);
        endMarker = new Node<>(null, beginMarker, null);
        beginMarker.next = endMarker;

        theSize = 0;
        modCount++;
    }

    /**
     * 返回长度
     * @return
     */
    public int size() { return theSize; }

    /**
     * 判断链表是否为空
     * @return
     */
    public boolean isEmpty() { return theSize == 0; }

    /**
     * 在链表末端添加值
     * @param x
     * @return
     */
    public boolean add(AnyType x) {
        add(size(), x);
        return true;
    }

    /**
     * 按索引位置添加值
     * @param idx 位置
     * @param x 添加的元素
     */
    public void add(int idx, AnyType x) {
        addBefore(getNode(idx), x);
    }

    /**
     * 按索引位置获取节点值
     * @param idx
     * @return
     */
    public AnyType get(int idx) {
        return getNode(idx).data;
    }

    /**
     * 按索引位置设置新值
     * @param idx 索引
     * @param newVal 值
     * @return
     */
    public AnyType set(int idx, AnyType newVal) {
        Node<AnyType> p = getNode(idx);
        AnyType oldVal = p.data;
        p.data = newVal;
        return oldVal;
    }

    /**
     * 按索引位置删除值
     * @param idx
     * @return
     */
    public AnyType remove(int idx) {
        return remove(getNode(idx));
    }

    /**
     * 删除指定节点
     * @param p
     * @return
     */
    private AnyType remove(Node<AnyType> p) {
        p.prev.next = p.next;
        p.next.prev = p.prev;
        theSize--;
        modCount++;
        return p.data;
    }

    /**
     * 在节点前插入节点
     * @param p 指定节点(在此节点之前插入新节点)
     * @param x 要插入的节点的值
     */
    private void addBefore(Node<AnyType> p, AnyType x) {

        Node<AnyType> newNode = new Node<>(x, p.prev, p);

        newNode.prev.next = newNode;
        p.prev = newNode;
        theSize++;
        modCount++;
    }

    /**
     * 按索引位置获取链表节点
     * @param idx 索引位置
     * @return
     */
    private Node<AnyType> getNode(int idx) {
        Node<AnyType> p;

        if (0 > idx || idx > size())
            throw new IndexOutOfBoundsException();

        // 判断查询位置在链表的前半部分
        if (size() / 2 > idx) {
            p = beginMarker.next;
            for (int i = 0; i < idx; i++)
                p = p.next;
        }

        // 判断查询位置在链表的后半部分
        else {
            p = endMarker;
            for (int i = size(); i > idx; i--)
                p = p.prev;
        }

        return p;
    }

    public Iterator<AnyType> iterator() {
        return new LinkedListIterator();
    }

    /**
     * MyLinkedList的迭代器,使用内部类实现
     */
    private class LinkedListIterator implements Iterator<AnyType> {
    
    

        private Node<AnyType> current = beginMarker.next;
        private int expectedModCount = modCount;
        private boolean okToRemove = false;

        @Override
        public boolean hasNext() {
            return current != endMarker;
        }

        @Override
        public AnyType next() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (!hasNext())
                throw new NoSuchElementException();

            AnyType nextItem = current.data;
            current = current.next;
            okToRemove = true;
            return nextItem;
        }

        @Override
        public void remove() {

            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (!okToRemove)
                throw new IllegalStateException();

            MyLinkedList.this.remove(current);
            okToRemove = false;
            expectedModCount++;
        }
    }

    /**
     * 链表节点
     * @param <AnyType>
     */
    private static class Node<AnyType> {
    
    

        public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) {
            data = d;
            prev = p;
            next = n;
        }

        /**
         * 当前节点数据
         */
        public AnyType data;
        /**
         * 上一个节点的引用
         */
        public Node<AnyType> prev;
        /**
         * 下一个节点引用
         */
        public Node<AnyType> next;
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {

        MyLinkedList<Character> chLinkList = new MyLinkedList<>();
        char c = 'a';
        for (int i = 0; i < 20; i++)
            chLinkList.add(c++);

        for (char ch : chLinkList)
            System.out.print(ch + " ");
        System.out.println("删除之前");

        chLinkList.remove(10);

        for (char ch : chLinkList)
            System.out.print(ch + " ");
        System.out.println("删除之后");

        Iterator iterator = chLinkList.iterator();

        System.out.println("采用迭代器遍历");

        while (iterator.hasNext())
            System.out.print(iterator.next() + " ");

    }
}

猜你喜欢

转载自blog.csdn.net/wizard_rp/article/details/70942344