【问题标题】:Circular Doubly LinkedList ListIterator循环双向链表 ListIterator
【发布时间】:2013-10-11 09:54:32
【问题描述】:

这是一道作业题。我有一个双链接节点类、一个实现Iterable 的循环双链表类和一个实现迭代器的迭代器类。我理解迭代器的概念,其中隐式游标位于两个节点之间,并且在调用 next() 时它会返回它刚刚跳过的节点。我用一个新的列表对象创建了一个测试类。然后我创建了一个迭代器并调用 next,我收到了正确的 No Such Element exception,但是当我将一些节点添加到列表中时,我收到了 Null Pointer Exception 而不是它返回最后一个返回的节点。我该如何纠正这个问题?

我的节点类:

public class DoubleLinkedNode<E>{
private E data;

private DoubleLinkedNode<E> next;

private DoubleLinkedNode<E> prev;


public DoubleLinkedNode(E data, DoubleLinkedNode<E> next, DoubleLinkedNode<E> prev){
    this.data = data;
    this.next = next;
    this.prev = prev;
}
/**
 * Used to construct a node that points to null for its prev and next.
 * @param data Data is a generic variable to be stored in the node.
 */
public DoubleLinkedNode(E data){
    this(data, null, null);
} 


//getters
public E getData(){
    return data;
}

public DoubleLinkedNode<E> getNext(){
    return next;
}

public DoubleLinkedNode<E> getPrev(){
    return prev;
}
//setters
public void setData(E data){
    this.data = data;
}

public void setNext(DoubleLinkedNode<E> next){
    this.next = next;
}

public void setPrev(DoubleLinkedNode<E> prev){
    this.prev = prev;
}

@Override public String toString(){
    if(data == null){
        return null;
    }
    else{
        return data.toString();
    }
}

}

具有私有内部迭代器类的 List 类:

import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;


public class CircularDoubleLinkedList<E> implements Iterable<E>{

private int size;   
private DoubleLinkedNode<E> head;


public CircularDoubleLinkedList(){
    this.head = null;
    this.size = 0;      
}       
/**
 * Adds an item to the end of the list.
 * 
 * @param data The Data that is to be stored in the node.
 */ 
public void add(E data){    
    DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
    if(this.head == null){
        newNode.setNext(newNode);
        newNode.setPrev(newNode);
        this.head = newNode;
        this.size++;
        //if list is empty create a new node and insert
    }
    else{
        DoubleLinkedNode<E> temp = this.head.getPrev();
        this.head.getPrev().setNext(newNode);
        this.head.setPrev(newNode);
        newNode.setPrev(temp);
        newNode.setNext(this.head);     
        this.size++;
    }
}
/**
 * Which adds an item at the specified index.
 * 
 * @param index The index in which the new Node is added. 
 * @param data The data which is to be stored in the node.
 */
public void add(int index, E data){
    int currIndex = 0;
    DoubleLinkedNode<E> currNode = this.head;
    DoubleLinkedNode<E> nextNode = this.head.getNext();
    DoubleLinkedNode<E> prevNode = this.head.getPrev();
    DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
    if(index == 0){
        prevNode.setNext(newNode);
        currNode.setPrev(newNode);
        newNode.setPrev(prevNode);
        newNode.setNext(currNode);
        this.head = newNode;
        this.size++;    
    }
    else if (index > 0){        
        while(currIndex != this.size){
            if(currIndex != index%size){
                currIndex++;
                currNode = currNode.getNext();
                nextNode = nextNode.getNext();
                prevNode = prevNode.getNext();                  
            }else{              
                newNode.setPrev(prevNode);
                newNode.setNext(currNode);
                prevNode.setNext(newNode);
                currNode.setPrev(newNode);
                currNode = newNode;
                this.size++;
                break;                                      
            }
        }       
    }
    else if (index < 0){
        while(currIndex != -this.size){
            if(currIndex != index%size){
                currIndex--;
                currNode = currNode.getPrev();
                prevNode = prevNode.getPrev();
                nextNode = nextNode.getPrev();
            }else{              
                newNode.setNext(nextNode);
                newNode.setPrev(currNode);
                currNode.setNext(newNode);
                nextNode.setPrev(newNode);          
                currNode = newNode;
                this.size++;
                break;                                      
            }
        }   
    }
}
/**
 * Returns the data stored at the specified index.
 * 
 * @param index The index determines the node whose data is returned.
 * @return Returns the data of the node at the index.
 */
public E get(int index){//returns the data stored at the specified index
    int currIndex = 0;
    DoubleLinkedNode<E> currNode = this.head;
    E temp = null;      
    if(index == 0){//zero case          
        temp = currNode.getData();
    }
    else if(index > 0){//positive           
        while(currIndex != this.size){
            if(currIndex != index%size){
                currIndex++;
                currNode = currNode.getNext();                              
            }else{                              
                temp = currNode.getData();
                break;                                      
            }
        }   
    }
    else if(index < 0){//negative       
        while(currIndex != -this.size){
            if(currIndex != index%size){
                currIndex--;
                currNode = currNode.getPrev();
            }else{              
                temp = currNode.getData();
                break;                                      
            }
        }           
    }
    return temp;
}   
/**
 * Which removes and returns an item from the list.
 * 
 * @param index Removes the node at the current index.
 * @return Returns the data of the removed node.
 */
public E remove(int index){//which removes and returns an item from the list
    int currIndex = 0;
    DoubleLinkedNode<E> currNode = this.head;
    DoubleLinkedNode<E> nextNode = this.head.getNext();
    DoubleLinkedNode<E> prevNode = this.head.getPrev();
    E temp = null;  
    if(index == 0){
        temp = currNode.getData();
        prevNode.setNext(currNode.getNext());
        nextNode.setPrev(currNode.getPrev());
        this.head = nextNode;
        size--;
    }
    else if(index > 0){//positive           
        while(currIndex != this.size){
            if(currIndex != index%size){
                currIndex++;
                currNode = currNode.getNext();
                nextNode = nextNode.getNext();
                prevNode = prevNode.getNext();                  
            }else{                              
                temp = currNode.getData();
                prevNode.setNext(currNode.getNext());
                nextNode.setPrev(currNode.getPrev());
                currNode = nextNode;
                size--;
                break;                                      
            }
        }   
    }
    else if(index < 0){//negative       
        while(currIndex != -this.size){
            if(currIndex != index%size){
                currIndex--;
                currNode = currNode.getPrev();
                prevNode = prevNode.getPrev();
                nextNode = nextNode.getPrev();
            }else{              
                temp = currNode.getData();
                prevNode.setNext(currNode.getNext());
                nextNode.setPrev(currNode.getPrev());
                currNode = prevNode;
                size--;
                break;                                      
            }
        }           
    }
    return temp;
} 
/**
 * Returns the size.
 * 
 * @return
 */
public int size(){
    return size;
}
@Override public String toString(){
    String str = "[";
    int index = 0;
    DoubleLinkedNode<E> curr = head;
    if(size == 0){
        return "There is no one here to kill.";         
    }else{      
        while (index <this.size) {
            str += curr.getData();  
            curr = curr.getNext();
            index++;
                if (index<this.size) {
                    str += ", ";
                }
        }
            str += "]";
    }
    return str;
  } 
@Override
public Iterator<E> iterator() {

    return new CircularDoubleIterator();
}   
// Iterator inner class begins
private class CircularDoubleIterator implements ListIterator<E> {

    private DoubleLinkedNode<E> nextItem;//reference to next item
    private int index = 0;
    private DoubleLinkedNode<E> lastReturned;// the last node to be returned by prev() or next()
                                            // reset to null after a remove() or add()

    @Override
    public E next() {
        if(!hasNext()){
            throw new NoSuchElementException("No such element.");
        }
        else{
                            nextItem = head; //edited 11Sept13
            lastReturned = nextItem.getNext();
            nextItem = nextItem.getNext();
                            head = nextItem; //edited 11Sept13
            index++;
            return lastReturned.getData();


        }
    }

    @Override
    public E previous() {
        if(!hasPrevious()){
            throw new NoSuchElementException("No such element.");
        }
        else{       

        index--;

        return ;
        }
    }

    @Override
    public int nextIndex() {
        return index;
    }

    @Override
    public int previousIndex() {
        return index-1;
    }
    @Override 
    public boolean hasNext() {  
        return size != 0;
    }

    @Override
    public boolean hasPrevious() {      
        return size!= 0;
    }
    @Override
    public void remove() {
    }

    @Override
    public void set(E theData) {
        if(lastReturned == null){
            throw new IllegalStateException();
        }
        else{
        }

    }

    @Override
    public void add(E theData) {
        if(size == 0){              
        }
        else if(size != 0){
        }

    }

}

//Iterator inner class ends
}

【问题讨论】:

    标签: java doubly-linked-list next listiterator circular-list


    【解决方案1】:

    当您创建迭代器时,我看不到您将值分配给 private DoubleLinkedNode&lt;E&gt; nextItem; 的位置。 我看不到整个代码。所以我假设nextItem 为空或其next 字段为空。

    【讨论】:

    • 好的,我在next()中设置nextItem为head,next()方法返回第一个元素但调用next元素返回相同元素。看起来每次 next() 调用都会将 nextItem 重置为 head。
    • 啊好吧!然后我在返回 lastReturned 之前将 head 设置为 nextItem。它有效,感谢您提醒我注意未分配的 nextItem!