如何实现将Sequence ADT定义为双链表的类SequenceDLList?
我一直在尝试用单链表修改下面的代码....但是没有到达那里。 这应该有用..
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
*/
public class SequenceList
{
/**
* Member class Node encapsulates the nodes of the linked list in
* which the stack is stored. Each node contains a data item and a
* reference to another node - the next in the linked list.
*/
protected class Node
{
public Node(Object o)
{
this(o, null);
}
public Node(Object o, Node n)
{
datum = o;
next = n;
}
//The Node data structure consists of two object references.
//One for the datum contained in the node and the other for
//the next node in the list.
protected Object datum;
protected Node next;
}
//We use object references to the head and tail of the list (the head
//and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
//Only require a single constructor, which sets both object
//references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList()
{
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o)
{
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o)
{
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException
{
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
if(index == 0) {
listHead = new Node(o, listHead);
listTail = listHead;
}
else throw new SequenceListException("Indexed element is out of range");
}
//There is another special case for insertion at the head of
//the sequence.
else if(index == 0) {
listHead = new Node(o, listHead);
}
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while(i < index) {
nodePointer = nodePointer.next;
i += 1;
if(nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
//Finally we need to check that the tail pointer is
//correct. Another special case occurs if the new
//node was inserted at the end, in which case, we need
//to update the tail pointer.
if(nodePointer == listTail) {
listTail = listTail.next;
}
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we just unlink the first node of the
//list.
else {
listHead = listHead.next;
}
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we need to chain all the way down the
//list in order to reset the link of the second to last
//element to null.
else {
Node nodePointer = listHead;
while(nodePointer.next != listTail) {
nodePointer = nodePointer.next;
}
//Unlink the last node and reset the tail pointer.
nodePointer.next = null;
listTail = nodePointer;
}
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
if(index == 0) {
listHead = null;
listTail = null;
} else throw new SequenceListException("Indexed element is out of range.");
}
//There is also a special case when the first element has to
//be removed.
else if(index == 0) {
deleteFirst();
}
//In the general case, we need to chain down the list to find
//the node in the indexed position.
else {
Node nodePointer = listHead;
int i = 1;
while(i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Unlink the node and reset the tail pointer if that
//node was the last one.
if(nodePointer.next == listTail) {
listTail = nodePointer;
}
nodePointer.next = nodePointer.next.next;
}
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException
{
if(listHead != null) {
return listHead.datum;
}
else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException
{
if(listTail != null) {
return listTail.datum;
}
else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException
{
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//We need to chain down the list until we reach the indexed
//position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if(nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty()
{
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size()
{
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while(nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear()
{
listHead = null;
listTail = null;
}
}
答案 0 :(得分:2)
正如其他人已经提到的那样,每个节点都必须在列表中引用它的下一个和前一个邻居。
基本上,整个解决方案看起来与您的示例不同。您必须注意,无论您在何处添加或删除节点,都需要相应地调整相邻节点的引用。
唯一不同的方法是 deleteLast 。在这里,您不需要遍历整个列表来查找倒数第二个节点。您只需使用最后一个节点的“prev”参考。
我担心我刚做完作业,但无论如何这里都是完整的例子。请注意,我根本没有真正测试该代码:
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
public class SequenceList {
/**
* Member class Node encapsulates the nodes of the linked list in which the
* stack is stored. Each node contains a data item and a reference to
* another node - the next in the linked list.
*/
protected class Node {
public Node(Object o) {
this(o, null, null);
}
public Node(Object o, Node p, Node n) {
datum = o;
prev = p;
next = n;
}
// The Node data structure consists of three object references.
// One for the datum contained in the node and two for
// the next and previous node in the list.
protected Object datum;
protected Node next;
protected Node prev;
}
// We use object references to the head and tail of the list (the head
// and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
// Only require a single constructor, which sets both object
// references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList() {
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o) {
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o);
listTail = listHead;
}
// In the general case, we simply add a new node at the start
// of the list via the head pointer.
else {
listHead.prev = new Node(o, null, listHead);
listHead = listHead.prev;
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o) {
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o);
listTail = listHead;
}
// In the general case, we simply add a new node to the end
// of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail, null);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException {
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
if (index == 0) {
listHead = new Node(o);
listTail = listHead;
} else {
throw new SequenceListException("Indexed element is out of range");
}
return;
}
// There is another special case for insertion at the head of
// the sequence.
if (index == 0) {
insertFirst(o);
return;
}
// In the general case, we need to chain down the linked list
// from the head until we find the location for the new
// list node. If we reach the end of the list before finding
// the specified location, we know that the given index was out
// of range and throw an exception.
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
// Now we've found the node before the position of the
// new one, so we 'hook in' the new Node.
Node newNode = new Node(o, nodePointer, nodePointer.next);
if (nodePointer.next != null) {
nodePointer.next.prev = newNode;
}
nodePointer.next = newNode;
// Finally we need to check that the tail pointer is
// correct. Another special case occurs if the new
// node was inserted at the end, in which case, we need
// to update the tail pointer.
if (nodePointer == listTail) {
listTail = newNode;
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
return;
}
// In the general case, we just unlink the first node of the
// list.
listHead = listHead.next;
listHead.prev = null;
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
return;
}
// In the general case, we just unlink the last node of the
// list.
listTail = listTail.prev;
listTail.next = null;
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
if (index == 0) {
listHead = null;
listTail = null;
} else {
throw new SequenceListException("Indexed element is out of range.");
}
return;
}
// There is also a special case when the first element has to
// be removed.
if (index == 0) {
deleteFirst();
return;
}
// In the general case, we need to chain down the list to find
// the node in the indexed position.
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
// Unlink the node and reset the tail pointer if that
// node was the last one.
if (nodePointer.next == listTail) {
listTail = nodePointer;
}
// Change reference of node after the node which is removed.
if (nodePointer.next.next != null) {
nodePointer.next.next.prev = nodePointer;
}
// Change reference of node before the node which is removed.
nodePointer.next = nodePointer.next.next;
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException {
if (listHead != null) {
return listHead.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException {
if (listTail != null) {
return listTail.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException {
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// We need to chain down the list until we reach the indexed
// position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
} else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty() {
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size() {
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while (nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear() {
listHead = null;
listTail = null;
}
public Node lastNode() {
return listTail;
}
public Node firstNode() {
return listHead;
}
}
答案 1 :(得分:0)
在双向链表中,每个节点指向下一个节点和前一个节点。 所以它会是这样的。所以我会给你一个提示。您的节点应该有一个Node next和Node previous
________ _______
| | | |
| |------>| |
| |<------| |
| | | |
|_______| |______|
答案 2 :(得分:0)
您使用对象和Node
next
构建Node
。要将此列为双向链接列表,您还需要存储previous
Node
:
private class DLNode<T> {
private final T datum;
private DLNode<T> next;
private DLNode<T> previous;
private DLNode(final T datum) { this.datum = datum; }
// Manipulate next and previous directly instead of setting them in constructors.
}
public DLNode<T> insertAfter(DLNode<T> node, T datum) {
final DLNode<T> inserted = new DLNode<T>(datum);
final DLNode<T> currentNext = node.next;
inserted.next = currentNext;
inserted.previous = node;
currentNext.previous = inserted;
node.next = inserted;
return inserted;