【问题标题】:Java Deque ImplementationJava双端队列实现
【发布时间】:2016-08-18 04:41:47
【问题描述】:

Java 新手问题:我正在尝试在 Java 中实现双端队列,但遇到了 dequeueBack(从队列后部删除一个元素)和 enqueueFront(将一个元素添加到队列前部)方法的问题。我已经得到了相反的方法(dequeueFront 和 enqueueBack),但我在这一点上被难住了。有什么建议吗?

public class Carr_A06Q4
{
/**
 * Program entry point for deque testing.
 * @param args Argument list.
 */    
public static void main(String[] args)
{
    LinkedDequeue<Integer> deque = new LinkedDequeue<Integer>();

    System.out.println("DEQUE TESTING");

    //per Q1
    deque.enqueueBack(3);
    deque.enqueueBack(7);
    deque.enqueueBack(4);
    deque.dequeueFront();        
    deque.enqueueBack(9);
    deque.enqueueBack(8);
    deque.dequeueFront();
    System.out.println("The size of the deque is: " + deque.size());
    System.out.println("The deque contains:\n" + deque.toString());   

    //new features
    System.out.println(deque.dequeueFront());
    deque.enqueueFront(1);
    deque.enqueueFront(11);                         
    deque.enqueueFront(3);                 
    deque.enqueueFront(5);
    System.out.println(deque.dequeueBack());
    System.out.println(deque.dequeueBack());        
    System.out.println(deque.last());
    deque.dequeueFront();
    deque.dequeueFront();
    System.out.println(deque.first());        
    System.out.println("The size of the deque is: " + deque.size());
    System.out.println("The deque contains:\n" + deque.toString());            
}

/**
 * LinkedDeque represents a linked implementation of a deque.
 * 
 */
public static class LinkedDequeue<T> implements DequeADT<T>
{
    private int count;
    private LinearDoubleNode<T> head, tail; //front, back

    /**
     * Creates an empty queue.
     */
    public LinkedDequeue()
    {
        count = 0;
        head = tail = null;
    }

    /**
     * Adds the specified element to the tail of this queue.
     * @param element the element to be added to the tail of the queue
     */
    public void enqueueBack(T element)
    {
        LinearDoubleNode<T> node = new LinearDoubleNode<T>(element);

        if (isEmpty())
            head = node;
        else
            tail.setNext(node);

        tail = node;
        count++;
    }

    /**
     * Adds the specified element to the head of this queue.
     * @param element the element to be added to the head of the queue
     */
    public void enqueueFront(T element)
    {
        LinearDoubleNode<T> node = new LinearDoubleNode<T>(element);

        count++ ;    
        if (head == null) 
        {
            head = node;
        }
        else 
        {
            node.setNext(head);
            head = node;
        }
    }

    /**
     * Removes the element at the head of this queue and returns a
     * reference to it. 
     * @return the element at the head of this queue
     * @throws EmptyCollectionException if the queue is empty
     */
    public T dequeueFront() throws EmptyCollectionException
    {
       if (isEmpty())
            throw new EmptyCollectionException("queue");

        T result = head.getElement();
        head = head.getNext();
        count--;

        if (isEmpty())
            head = null;

        return result;
    }

    /**
     * Removes the element at the tail of this queue and returns a
     * reference to it. 
     * @return the element at the tail of this queue
     * @throws EmptyCollectionException if the queue is empty
     */
    public T dequeueBack() throws EmptyCollectionException
    {
        if (isEmpty())
            throw new EmptyCollectionException("queue");

        T result = tail.getElement();
        tail = tail.getNext();

        if (isEmpty())
            head = null;
        count --;

        return result;
    }

    /**
     * Returns a reference to the element at the head of this queue.
     * The element is not removed from the queue.  
     * @return a reference to the first element in this queue
     * @throws EmptyCollectionsException if the queue is empty
     */
    public T first() throws EmptyCollectionException
    {
        if (isEmpty())
            throw new EmptyCollectionException("stack");

        T result = head.getElement();
        return result;
    }

    /**
     * Returns a reference to the element at the tail of this queue.
     * The element is not removed from the queue.  
     * @return a reference to the first element in this queue
     * @throws EmptyCollectionsException if the queue is empty
     */
    public T last() throws EmptyCollectionException
    {
        if (isEmpty())
            throw new EmptyCollectionException("stack");

        T result = tail.getElement();
        return result;
    }

    /**
     * Returns true if this queue is empty and false otherwise. 
     * @return true if this queue is empty 
     */
    public boolean isEmpty()
    {
        if (head == null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * Returns the number of elements currently in this queue.
     * @return the number of elements in the queue
     */
    public int size()
    {
        return count;
    }

    /**
     * Returns a string representation of this queue. The front element
     * occurs first, and each element is separated by a space. If the
     * queue is empty, returns "empty".
     * @return the string representation of the queue
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
       LinearDoubleNode<T> tmp = head;
       while (tmp != null)
       {
        sb.append(tmp.getElement()).append(" ");
        tmp = tmp.getNext();
       }
       return sb.toString();
    }
}

}

我需要得到以下输出:

双端测试: 双端队列的大小为:3 双端队列包含:

498

4

8

9

1

11

双端队列的大小为:2 双端队列包含: 11 1

但我却得到:

双端测试: 双端队列的大小为:3 双端队列包含:

498

4

8

然后我在 dequeueBack 方法中得到一个 NullPointerException。

感谢任何帮助!

另外,界面是:

public interface DequeADT<T>
{
/**  
 * Adds one element to the front of this deque. 
 * @param element the element to be added to the front of the deque  
 */
public void enqueueFront(T element); //deque specific

/**  
 * Adds one element to the back of this deque. 
 * @param element the element to be added to the back of the deque  
 */
public void enqueueBack(T element);

/**  
 * Removes and returns the element at the front of this deque.
 * Should throw an exception if the deque is empty.
 * @return the element at the front of this deque
 */
public T dequeueFront();

/**  
 * Removes and returns the element at the back of this deque.
 * Should throw an exception if the deque is empty.
 * @return the element at the back of the deque. 
 */
public T dequeueBack(); //deque specific  

/**  
 * Returns, without removing, the element at the front of this deque.
 * Should throw an exception if the deque is empty.
 * @return the first element in the deque
 */
public T first();

/**  
 * Returns, without removing, the element at the back of this deque.
 * Should throw an exception if the deque is empty.
 * @return the last element in the deque
 */
public T last(); //deque specific  

/**  
 * Returns true if this deque is empty and false otherwise.
 * @return true if this deque is empty
 */
public boolean isEmpty();

/**  
 * Returns the number of elements in this deque. 
 * @return the number of elements in the deque
 */
public int size();

/**  
 * Returns a string representation of this deque. The front element
 * occurs first, and each element is separated by a space. If the
 * deque is empty, returns "empty".
 * @return the string representation of the deque
 */
public String toString();

}

并且节点的描述是:

public class LinearDoubleNode<T>
{
private LinearDoubleNode<T> next;
private T element;

/**
 * Creates an empty node.
 */
public LinearDoubleNode()
{
    next = null;
    element = null;
}

/**
 * Creates a node storing the specified element.
 * @param elem element to be stored
 */
public LinearDoubleNode(T elem)
{
    next = null;
    element = elem;
}

/**
 * Returns the node that follows this one.
 * @return reference to next node
 */
public LinearDoubleNode<T> getNext()
{
    return next;
}

/**
 * Sets the node that follows this one.
 * @param node node to follow this one
 */
public void setNext(LinearDoubleNode<T> node)
{
    next = node;
}

/**
 * Returns the element stored in this node.
 * @return element stored at the node
 */
public T getElement()
{
    return element;
}

/**
 * Sets the element stored in this node.
 * @param elem element to be stored at this node
 */
public void setElement(T elem)
{
    element = elem;
}

}

【问题讨论】:

    标签: java queue deque


    【解决方案1】:

    执行此操作的唯一方法是将内部列表设为double-linked

    否则,您必须扫描整个列表以找到倒数第二个节点,才能删除最后一个节点。

    Double-ended queueDouble-linked list
    或动态数组(参见Implementations 部分)。

    【讨论】:

      【解决方案2】:

      公共类 LinkedDQueue 实现 DQueue {

      private int size;
      private LinearDoubleNode<T> head, tail; // front, back
      private int capcity;
      
      public LinkedDQueue() {
          capcity = 10;
      }
      
      public LinkedDQueue(int capcity) {
      
          this.capcity = capcity;
      }
      
      @Override
      public boolean full() {
          return size == capcity;
      }
      
      @Override
      public void addFirst(T e) throws CapcityExceededException {
          if (full())
              throw new CapcityExceededException("size overflow");
      
          LinearDoubleNode<T> node = new LinearDoubleNode<T>(e);
      
          if (head == null) {
              head = node;
              tail = node;
          } else {
              node.setNext(head);
              head = node;
          }
          size++;
      
      }
      
      @Override
      public void addLast(T e) throws CapcityExceededException {
          LinearDoubleNode<T> node = new LinearDoubleNode<T>(e);
      
          if (full())
              throw new CapcityExceededException("size overflow");
      
          if (tail == null) {
              head = tail = node;
          } else {
              tail.setNext(node);
              node.setPrevious(tail);
          }
      
          tail = node;
          size++;
      
      }
      
      @Override
      public T removeFirst() {
          if (isEmpty())
              return null;
      
          T result = head.getElement();
          head.getNext().setPrevious(null);
          head = head.getNext();
          size--;
      
          return result;
      }
      
      @Override
      public T removeLast() {
      
          LinearDoubleNode<T> temp = tail; // Save address of Node to delete
          if (isEmpty()) {
              return null;
          }
      
          if (head == tail) {
              head = null;
              tail = null;
              size = 0;
              return tail.getElement();
          }
      
          T result = tail.getElement();
          tail = temp.getPrevious();
          tail.setNext(null);
          size--;
      
          return result;
      }
      
      @Override
      public T getFirst() {
          if (isEmpty())
              return null;
      
          T result = head.getElement();
          return result;
      }
      
      @Override
      public T getLast() {
          if (isEmpty())
              return null;
      
          T result = tail.getElement();
          return result;
      }
      
      @Override
      public int length() {
          return size;
      }
      
      @Override
      public void reverse() {
      
      }
      
      @Override
      public boolean isEmpty() {
          if (head == null) {
              return true;
          } else {
              return false;
          }
      }
      
      @Override
      public int size() {
          return size;
      }
      
      @Override
      public String toString() {
          LinearDoubleNode<T> temp = head; // Save address of Node to delete
          StringBuilder builder = new StringBuilder();
          while (temp != null) {
              builder.append(temp.getElement() + "");
              temp = temp.getNext();
      
          }
          return builder.toString();
      }
      
      class LinearDoubleNode<T> {
          private LinearDoubleNode<T> next;
          private LinearDoubleNode<T> previous;
          private T element;
      
          /**
           * Creates an empty node.
           */
          public LinearDoubleNode() {
              next = null;
              previous = null;
              element = null;
          }
      
          /**
           * Creates a node storing the specified element.
           * 
           * @param elem
           *            element to be stored
           */
          public LinearDoubleNode(T elem) {
              next = null;
              previous = null;
              element = elem;
          }
      
          /**
           * Returns the node that follows this one.
           * 
           * @return reference to next node
           */
          public LinearDoubleNode<T> getNext() {
              return next;
          }
      
          public LinearDoubleNode<T> getPrevious() {
              return previous;
          }
      
          public void setPrevious(LinearDoubleNode<T> previous) {
              this.previous = previous;
          }
      
          /**
           * Sets the node that follows this one.
           * 
           * @param node
           *            node to follow this one
           */
          public void setNext(LinearDoubleNode<T> node) {
              next = node;
          }
      
          /**
           * Returns the element stored in this node.
           * 
           * @return element stored at the node
           */
          public T getElement() {
              return element;
          }
      
          /**
           * Sets the element stored in this node.
           * 
           * @param elem
           *            element to be stored at this node
           */
          public void setElement(T elem) {
              element = elem;
          }
      }
      

      }

      类 CapcityExceededException 扩展异常 { 私有字符串消息;

      public CapcityExceededException(String message) {
          super(message);
          this.message = message;
      
      }
      

      }

      【讨论】:

        【解决方案3】:
        import java.util.Iterator;
        import java.util.NoSuchElementException;
        
        /**
         * The type Deque.
         *
         * @param <Item> the type parameter
         */
        public class Deque<Item> implements Iterable<Item> {
            /**
             * The Head.
             */
            private Node<Item> head;
            /**
             * The Tail.
             */
            private Node<Item> tail;
            /**
             * The Deque size.
             */
            private int dequeSize;
        
            private class Node<Item> {
                /**
                 * The Data.
                 */
                Item data;
                /**
                 * The Next.
                 */
                Node<Item> next;
                /**
                 * The Prev.
                 */
                Node<Item> prev;
        
                /**
                 * Instantiates a new Node.
                 *
                 * @param data the data
                 */
                Node(Item data) {
                    this.data = data;
                }
            }
        
            /**
             * Instantiates a new Deque.
             */
            public Deque() {
                dequeSize = 0;
            }
        
            /**
             * Is empty boolean.
             *
             * @return the boolean
             */
            public boolean isEmpty() {
                return dequeSize == 0;
            }
        
            /**
             * Size int.
             *
             * @return the int
             */
            public int size() {
                return dequeSize;
            }
        
            /**
             * Add first.
             *
             * @param item the item
             */
            public void addFirst(Item item) {
                if (item == null) {
                    throw new IllegalArgumentException();
                }
                Node<Item> newNode = new Node<Item>(item);
                if (head == null) {
                    head = newNode;
                    tail = newNode;
                } else {
                    head.prev = newNode;
                    newNode.next = head;
                    head = newNode;
                }
                dequeSize++;
            }
        
            /**
             * Add last.
             *
             * @param item the item
             */
            public void addLast(Item item) {
                if (item == null) {
                    throw new IllegalArgumentException();
                }
                Node<Item> newNode = new Node<Item>(item);
                if (head == null) {
                    head = newNode;
                    tail = newNode;
                } else {
                    tail.next = newNode;
                    newNode.prev = tail;
                    tail = newNode;
                }
                dequeSize++;
            }
        
            /**
             * Remove first item.
             *
             * @return the item
             */
            public Item removeFirst() {
                if (isEmpty()) {
                    throw new NoSuchElementException();
                }
                Item headData = head.data;
                if (dequeSize == 1) {
                    head = null;
                    tail = null;
                } else {
                    Node<Item> headNext = head.next;
                    headNext.prev = null;
                    head = headNext;
                }
                dequeSize--;
                return headData;
            }
        
            /**
             * Remove last item.
             *
             * @return the item
             */
            public Item removeLast() {
                if (isEmpty()) {
                    throw new NoSuchElementException();
                }
                Item tailData = tail.data;
                if (dequeSize == 1) {
                    head = null;
                    tail = null;
                } else {
                    Node<Item> tailPrev = tail.prev;
                    tailPrev.next = null;
                    tail = tailPrev;
                }
                dequeSize--;
                return tailData;
            }
        
            /**
             * Iterator iterator.
             *
             * @return the iterator
             */
            public Iterator<Item> iterator() {
                return new CustomIterator();
            }
        
            private class CustomIterator implements Iterator<Item> {
                private Node<Item> temp;
        
                /**
                 * Instantiates a new Custom iterator.
                 */
                CustomIterator() {
                    temp = head;
                }
        
                public boolean hasNext() {
                    return temp.next != null;
                }
                public Item next() {
                    if (!hasNext()) {
                        throw new NoSuchElementException();
                    }
                    Item tempData = temp.data;
                    temp = temp.next;
                    return tempData;
                }
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            }
        
            /**
             * The entry point of application.
             *
             * @param args the input arguments
             */
            public static void main(String[] args) {
                // unit testing (required)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2013-03-10
          • 2011-06-23
          • 2018-07-27
          • 2016-01-02
          • 2011-08-09
          • 1970-01-01
          • 2010-12-28
          • 2018-07-02
          • 1970-01-01
          相关资源
          最近更新 更多