循环双向链表 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<E> nextItem;
的位置。
我看不到整个代码。所以我假设nextItem
为空或其next
字段为空。
【讨论】:
好的,我在next()中设置nextItem为head,next()方法返回第一个元素但调用next元素返回相同元素。看起来每次 next() 调用都会将 nextItem 重置为 head。 啊好吧!然后我在返回 lastReturned 之前将 head 设置为 nextItem。它有效,感谢您提醒我注意未分配的 nextItem!以上是关于循环双向链表 ListIterator的主要内容,如果未能解决你的问题,请参考以下文章