数据结构: Java中LinkedList的简单实现

来源:互联网 发布:软件项目保密协议 编辑:程序博客网 时间:2024/05/23 18:20

更新:以下代码是初学链表后的简单实现,时隔一年再看一下代码。觉得有点惨不忍睹,测试了一下,标准库的链表插入1000万个元素用了10秒钟,以下代码花费的时间远超标准库。因为如果要将元素插入到链表末尾,都需要遍历整个链表。是个O(N)的算法。但实际上,大部分插入都是插入到最后(或是最前)。我们其实只需要维护一个tail节点就能解决这个问题。这样时间复杂度就为O(1)了。

    public void add(T val)    {        if(head==null)        {            head = new Node(val);            tail = head;        }        else        {            tail.next = new Node(val);            tail = tail.next;        }        ++size;    }

下面是LinkedList的简单实现。

LinkedList的优点: 新项的插入和现有项的删除花费常数时间。(前提是已有变动项的位置,不然还是要在索引上花费O(N) )
LinkedList的缺点: 很难索引现有项,对get操作的调用花费很多时间。

MyLinkedList作为双向链表,get()方法可以从头结点或者尾节点开始。所以最坏的情况下需要遍历 【N/2】 个元素。

代码中changedTimes和itChangedTimes的作用: 如果获取了一个迭代器之后修改它所对应的MyLinkedList对象,则让该迭代器失效。

package list;import java.util.ConcurrentModificationException;import java.util.Iterator;import java.util.NoSuchElementException;/** * MyLinkedList * @author earayu * @param <T> */public class MyLinkedList<T> implements Iterable<T> {    //双向链表的节点    private static class Node<T>{        public T data;        public Node<T> prevNode;        public Node<T> nextNode;        public Node(T data, Node<T> prevNode, Node<T> nextNode) {            this.data = data;            this.prevNode = prevNode;            this.nextNode = nextNode;        }    }    //定义链表的长度,修改次数,头结点和尾节点。    private int size;    private int changedTimes;    private Node<T> firstNode;    private Node<T> lastNode;    /**     * 调用init()方法,初始化链表     */    public MyLinkedList(){        init();    }    /**     * 初始化MyLinkedList,将长度,被改变次数,头结点和尾节点都初始化。以免发生错误。     */    private void init(){        size = 0;        changedTimes = 0;        firstNode = new Node<T>(null, null, null);        lastNode = new Node<T>(null, null, null);        firstNode.nextNode = lastNode;        lastNode.prevNode = firstNode;    }    /**     * 将链表清空,修改次数+1     */    public void clear(){        size = 0;        changedTimes++;        firstNode = new Node<T>(null, null, null);        lastNode = new Node<T>(null, null, null);        firstNode.nextNode = lastNode;        lastNode.prevNode = firstNode;    }    public boolean isEmpty(){        return size() == 0;    }    /**     * 返回当前链表长度(不含头尾节点)     * @return     */    public int size(){        return size;    }    /**     * 将idx索引出节点的值设置成newData     * @param idx     * @param newData     * @return     */    public T set(int idx, T newData){        Node<T> p = getNode(idx);        T oldVal = p.data;        p.data = newData;        return oldVal;    }    /**     * 删除制定索引出的节点,索引从0开始     * @param idx     * @return     */    public T remove(int idx){        return remove(getNode(idx));    }    private T remove(Node<T> p){        p.nextNode.prevNode = p.prevNode;        p.prevNode.nextNode = p.nextNode;        --size;        ++changedTimes;        return p.data;    }    /**     * 将data添加到链表尾部。     * @param data     * @return     */    public boolean add(T data){        add(size, data);        return true;    }    /**     * 将链表添加到idx索引出,索引从0开始     * @param idx     * @param data     * @return     */    public boolean add(int idx, T data){        if(idx < 0 || idx > size){            throw new IndexOutOfBoundsException();        }        Node<T> beforeNode = firstNode;        for(int i=0;i<size;i++){            beforeNode = beforeNode.nextNode;        }        Node<T> afterNode = beforeNode.nextNode;        beforeNode.nextNode = new Node(data, beforeNode, afterNode);        afterNode.prevNode = beforeNode.nextNode;        ++size;        ++changedTimes;        return true;    }    /**     * 获取idx索引出的节点的数据,索引从0开始     * @param idx     * @return     */    public T get(int idx){        return getNode(idx).data;    }    /**     * 获取idx索引出的节点     * @param idx     * @return     */    private Node<T> getNode(int idx){        if(idx < 0 || idx >= size){            throw new IndexOutOfBoundsException();        }        Node<T> p;        if(idx < size/2){            p = firstNode.nextNode;            for(int i=0; i<idx; i++){                p = p.nextNode;            }        }else{            p = lastNode;            for(int i=size; i>idx; i--){                p = p.prevNode;            }        }        return p;    }    /**     * 返回一个迭代器     */    @Override    public Iterator<T> iterator() {        return new LinkedListIterator();    }    /**     *      * @author earayu     *     */    private class LinkedListIterator implements Iterator<T>{        //迭代器的当前指向节点,修改次数,可否移除        private Node<T> currentNode = firstNode.nextNode;        private int itChangedTimes = changedTimes;        private boolean removable = false;        /**         * 返回是否有下一个节点(不包含尾节点)。         */        @Override        public boolean hasNext() {            return currentNode != lastNode;        }        /**         * 返回当前指向节点的下一个节点的值,并将指向的节点后移一位。         */        @Override        public T next() {            if(changedTimes != itChangedTimes){                throw new ConcurrentModificationException();            }            if(!hasNext()){                throw new NoSuchElementException();            }            T nextItem = currentNode.data;            currentNode = currentNode.nextNode;            removable = true;            return nextItem;        }        /**         * 调用外部类的remove方法,移除上一个访问过的节点。即,当前指向节点的前一个节点。         */        public void remove(){            if(changedTimes != itChangedTimes){                throw new ConcurrentModificationException();            }            if(!removable){                throw new IllegalStateException();            }            MyLinkedList.this.remove(currentNode.prevNode);            removable = false;            ++itChangedTimes;        }    }}
0 0
原创粉丝点击