双链表V3.0(含迭代器,Java语言描述)

更新说明

经过了双链表V1.0的根据接口编写成型、双链表V2.0的功能大幅度增强,这里推出了双链表V3.0,功能的丰富性不及V2.0,但加入了迭代器,代码的编写也更加的合理了,应该说是比较好的作品了。

不过还是推荐看看java.util.LinkedList的源码,那个写的显然吊打这里的所有版本。

简单说说迭代器

迭代器的具体内容这里就不赘述了,无论从是Java语法的层面,还是从理解数据结构的层面,亦或是对迭代器模式的了解,你都应该去深入的认识迭代器。

我们常用的增强for循环,也与迭代器密切联系着。

迭代器的话,无论是顺序表、链表、树还是什么其他的数据结构都可以写出来,迭代器无非是按照某种顺序逐一地遍历数据的序列。

迭代器一定要具备的基本内容:

  • 属性:
    • current: 当前位置
  • 方法
    • hasNext()
    • next()
    • remove()

编程实现

/**
 * LinkedList class implements a doubly-linked list.
 */
public class MyLinkedList<T> implements Iterable<T> {

    private int theSize;
    private int modCount = 0;
    private Node<T> beginMarker;
    private Node<T> endMarker;

    /**
     * Construct an empty LinkedList.
     */
    public MyLinkedList() {
        doClear();
    }
    
    private void clear() {
        doClear();
    }
    
    /**
     * Change the size of this collection to zero.
     */
    public void doClear() {
        beginMarker = new Node<>(null, null, null);
        endMarker = new Node<>(null, beginMarker, null);
        beginMarker.next = endMarker;
        theSize = 0;
        modCount++;
    }
    
    /**
     * Returns the number of items in this collection.
     * @return the number of items in this collection.
     */
    public int size() {
        return theSize;
    }
    
    public boolean isEmpty() {
        return size() == 0;
    }
    
    /**
     * Adds an item to this collection, at the end.
     * @param x any object.
     * @return true.
     */
    public boolean add(T x) {
        add(size(), x);
        return true;         
    }
    
    /**
     * Adds an item to this collection, at specified position.
     * Items at or after that position are slid one position higher.
     * @param x any object.
     * @param index position to add at.
     * @throws IndexOutOfBoundsException if idx is not between 0 and size(), inclusive.
     */
    public void add(int index, T x) {
        addBefore(getNode(index, 0, size()), x);
    }
    
    /**
     * Adds an item to this collection, at specified position p.
     * Items at or after that position are slid one position higher.
     * @param p Node to add before.
     * @param x any object.
     * @throws IndexOutOfBoundsException if idx is not between 0 and size(), inclusive.
     */    
    private void addBefore(Node<T> p, T x) {
        Node<T> newNode = new Node<>(x, p.prev, p);
        newNode.prev.next = newNode;
        p.prev = newNode;         
        theSize++;
        modCount++;
    }   
    
    
    /**
     * Returns the item at position idx.
     * @param index the index to search in.
     * @throws IndexOutOfBoundsException if index is out of range.
     */
    public T get(int index) {
        return getNode(index).data;
    }
        
    /**
     * Changes the item at position idx.
     * @param index the index to change.
     * @param newVal the new value.
     * @return the old value.
     * @throws IndexOutOfBoundsException if index is out of range.
     */
    public T set(int index, T newVal) {
        Node<T> p = getNode(index);
        T oldVal = p.data;
        p.data = newVal;   
        return oldVal;
    }
    
    /**
     * Gets the Node at position idx, which must range from 0 to size( ) - 1.
     * @param index index to search at.
     * @return internal node corresponding to idx.
     * @throws IndexOutOfBoundsException if idx is not between 0 and size( ) - 1, inclusive.
     */
    private Node<T> getNode(int index) {
        return getNode(index, 0, size()-1);
    }

    /**
     * Gets the Node at position idx, which must range from lower to upper.
     * @param index index to search at.
     * @param lower lowest valid index.
     * @param upper highest valid index.
     * @return internal node corresponding to idx.
     * @throws IndexOutOfBoundsException if idx is not between lower and upper, inclusive.
     */    
    private Node<T> getNode(int index, int lower, int upper) {
        Node<T> p;
        if(index < lower || index > upper) {
            throw new IndexOutOfBoundsException("getNode index: " + index + "; size: " + size());
        }
        if(index < size() / 2) {
            p = beginMarker.next;
            for(int i = 0; i < index; i++) {
                p = p.next;
            }
        } else {
            p = endMarker;
            for(int i = size(); i > index; i--) {
                p = p.prev;
            }
        }
        return p;
    }
    
    /**
     * Removes an item from this collection.
     * @param index the index of the object.
     * @return the item was removed from the collection.
     */
    public T remove(int index) {
        return remove( getNode(index));
    }
    
    /**
     * Removes the object contained in Node p.
     * @param p the Node containing the object.
     * @return the item was removed from the collection.
     */
    private T remove(Node<T> p) {
        p.next.prev = p.prev;
        p.prev.next = p.next;
        theSize--;
        modCount++;
        return p.data;
    }
    
    /**
     * Returns a String representation of this collection.
     */
    public String toString() {
        StringBuilder sb = new StringBuilder("[ ");
        for(T x : this) {
            sb.append(x).append(" ");
        }
        sb.append("]");
        return new String(sb);
    }

    /**
     * Obtains an Iterator object used to traverse the collection.
     * @return an iterator positioned prior to the first element.
     */
    public java.util.Iterator<T> iterator() {
        return new LinkedListIterator();
    }

    /**
     * This is the implementation of the LinkedListIterator.
     * It maintains a notion of a current position and of
     * course the implicit reference to the MyLinkedList.
     */
    private class LinkedListIterator implements java.util.Iterator<T> {
        private Node<T> current = beginMarker.next;
        private int expectedModCount = modCount;
        private boolean okToRemove = false;
        
        public boolean hasNext() {
            return current != endMarker;
        }
        
        public T next() {
            if(modCount != expectedModCount) {
                throw new java.util.ConcurrentModificationException();
            }
            if(!hasNext()) {
                throw new java.util.NoSuchElementException();
            }
            T nextItem = current.data;
            current = current.next;
            okToRemove = true;
            return nextItem;
        }
        
        public void remove() {
            if(modCount != expectedModCount) {
                throw new java.util.ConcurrentModificationException();
            }
            if(!okToRemove) {
                throw new IllegalStateException();
            }
            MyLinkedList.this.remove(current.prev);
            expectedModCount++;
            okToRemove = false;       
        }
    }
    
    /**
     * This is the doubly-linked list node.
     */
    private static class Node<T> {
        public Node<T>  prev;
        public Node<T>  next;
        public T data;

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

}

测试

public class LinkedListTest {
    public static void main(String [] args) {
        MyLinkedList<Integer> list = new MyLinkedList<>();
        for(int i = 0; i < 10; i++) {
            list.add(i);
        }
        for(int i = 20; i < 30; i++) {
            list.add(0, i);
        }
        list.remove(0);
        list.remove(list.size()-1);
        System.out.println( list );
        java.util.Iterator<Integer> itr = list.iterator();
        while(itr.hasNext()) {
            itr.next();
            itr.remove();
            System.out.println(list);
        }
    }
}

测试结果:

[ 28 27 26 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 27 26 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 26 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 24 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 23 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 22 21 20 0 1 2 3 4 5 6 7 8 ]
[ 21 20 0 1 2 3 4 5 6 7 8 ]
[ 20 0 1 2 3 4 5 6 7 8 ]
[ 0 1 2 3 4 5 6 7 8 ]
[ 1 2 3 4 5 6 7 8 ]
[ 2 3 4 5 6 7 8 ]
[ 3 4 5 6 7 8 ]
[ 4 5 6 7 8 ]
[ 5 6 7 8 ]
[ 6 7 8 ]
[ 7 8 ]
[ 8 ]
[ ]
发布了569 篇原创文章 · 获赞 1178 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104455428