我正在做这个小项目,在同一个类中创建一个队列和一个去队列,同时使用我自己的Node类和一个接口。
我面临的问题是我已经完成了所有方法,但是无法使方法removeLast工作,因为在删除之后我无法让后端链接到节点之前。请帮我提一下你的建议?谢谢。
我的节点类。
public class Node<T> {
T info;
Node<T> next;
public Node(T element) {
info = element;
next = null;
}
public void setInfo(T element) {
info = element;
}
public T getInfo() {
return info;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return next;
}
}
我的界面类
public interface DequeInterface<T> {
void addFront(T element);
void addLast(T element);
T removeFront();
T removeLast();
boolean isEmpty();
int getSize();
}
My deque class
import java.util.NoSuchElementException;
public class Deqeue<T> implements DequeInterface {
public Node<T> front;
public Node<T> rear;
int size;
public Deqeue() {
front = null;
rear = null;
size = 0;
}
@Override
public T removeFront() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = front.getInfo();
front = front.getNext();
size--;
return element;
}
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
size--;
return element;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return rear == null;
}
@Override
public void addFront(Object element) {
Node<T> newNode = front;
if (newNode == null) {
rear = front;
}
front = new Node(element);
front.setNext(newNode);
size++;
}
@Override
public void addLast(Object element) {
Node<T> newNode = rear;
if (newNode == null) {
front = rear;
}
rear = new Node(element);
newNode.setNext(rear);
size++;
}
}
答案 0 :(得分:2)
问题是您的列表是单链接的。不幸的是,删除单链表的最后一个节点需要遍历整个列表。一些替代方案:
答案 1 :(得分:1)
您的Node
也可以引用之前的Node
。这将创建一个双向链表。
public class Node<T> {
T info;
Node<T> next;
Node<T> prev;
public Node(T element) {
info = element;
next = null;
prev = null;
}
public void setInfo(T element) {
info = element;
}
public T getInfo() {
return info;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return next;
}
public void setPrev(Node<T> prev) {
this.prev = prev;
}
public Node<T> getPrev() {
return prev;
}
}
然后在Deque
课程中更改您的removeFront
和removeLast
方法以解释prev
public T removeFront() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = front.getInfo();
front = front.getNext();
front.setPrev(null); //<<<--------------------------
size--;
return element;
}
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
rear.getPrev().setNext(null) //<<<--------------
rear=rear.getPrev(); //<<<--------------
size--;
return element;
}
当然,addFirst
和addLast
方法也必须更新
@Override
public void addFront(Object element) {
Node<T> newNode = front;
front = new Node(element);
front.setNext(newNode);
if (newNode == null) {
rear = front;
}else{
newNode.setPrev(front);
}
size++;
}
@Override
public void addLast(Object element) {
Node<T> newNode = rear;
rear = new Node(element);
newNode.setNext(rear);
if (newNode == null) {
front = rear;
}else{
newNode.setNext(rear);
}
size++;
}
如果您不允许更改Node
的代码并且只能更改removeLast()
方法,那么您可以这样做:
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
if(rear==first){
rear=null;
first=null;
}else{
Node<T> prev = first;
while(prev.getNext()!=rear){
prev=prev.getNext();
}
rear=prev;
prev.setNext(null);
}
size--;
return element;
}
但这需要相当低效,因为它需要从头开始遍历整个列表。
答案 2 :(得分:0)
每个节点都应该有一个指针指向上一个节点的下一个节点和。
答案 3 :(得分:0)
你可以使你的列表双向链接(额外的管理和错误的机会),或者你可以在每次removeLast时重复列表并将后面设置为新的最后一个(当从最后删除时更糟糕的性能,特别是在大型列表上)。 )
答案 4 :(得分:0)
最简单的方法是实现双向链表而不是链表。因此,您的节点类需要跟踪前一个元素。您需要更新添加功能以支持此功能。完成后,删除最后一个功能将如下所示:
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
size--;
rear.getPrev().setNext(null);
rear = rear.getPrev();
return element;
}