循环双向链表 ListIterator

Posted

技术标签:

【中文标题】循环双向链表 ListIterator【英文标题】:Circular Doubly LinkedList 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

【问题讨论】:

【参考方案1】:

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

【讨论】:

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

以上是关于循环双向链表 ListIterator的主要内容,如果未能解决你的问题,请参考以下文章

数据结构双向链表的实现

双向链表无限循环? [关闭]

循环双向链表的C++实现

循环双向链表的

C语言数据结构——带哨兵结点的循环双向链表

数据结构C语言版 —— 链表增删改查实现(单链表+循环双向链表)