2013WorksApplication笔试题之我见PesistentQueue

这一提目是提高算法的时间效率。自己当时看的时候没有懂,后来看别人在github写的才略懂了一点,又回归到了 对于数据结构这个最原本的理解。不得不佩服这个日本公司。

以下代码转自https://github.com/Clouderlab/worksapplication2013recruite/blob/master/Exam/src/jp/co/wap/exam/PersistentQueue.java

import java.util.NoSuchElementException;
import java.util.Queue;

/**
 * The Queue class represents an immutable first-in-first-out (FIFO) queue of
 * objects. The key to implement such an immutable queue is maintaining two
 * reversed stack A and B, A is used to enqueue element and B is used to dequeue
 * element. When B is empty, simply reverse stack A and "clear" the elements in
 * A. Notice that A and B are immutable stacks. The performance test shows that
 * this implementation can be hundreds times faster than the sample code.
 * Enqueue and Dequeue 1 million random object only take about 100 milliseconds
 * in total.
 * 
 * @author Felix
 * @param <E>
 */
public class PersistentQueue<E> {
        /**
         * This is the internal immutable stack.
         * 
         * @author Felix
         * @param <E>
         */
        private static class PersistentStack<E> {
                private E head;
                private PersistentStack<E> tail;
                private int size;

                private PersistentStack(E obj, PersistentStack<E> tail) {
                        this.head = obj;
                        this.tail = tail;
                        this.size = tail.size + 1;
                }

                public static PersistentStack emptyStack() {
                        return new PersistentStack();
                }

                private PersistentStack() {
                        this.head = null;
                        this.tail = null;
                        this.size = 0;
                }

                /**
                 * Get a new reversed stack.
                 * 
                 * @return
                 */
                public PersistentStack<E> toReverseStack() {
                        PersistentStack<E> stack = new PersistentStack<E>();
                        PersistentStack<E> tail = this;
                        while (!tail.isEmpty()) {
                                stack = stack.push(tail.head);
                                tail = tail.tail;
                        }
                        return stack;
                }

                public boolean isEmpty() {
                        return this.size == 0;
                }

                public PersistentStack<E> push(E obj) {
                        return new PersistentStack<E>(obj, this);
                }
        }

        private PersistentStack<E> order;
        /**
         * The reverse stack of order
         */
        private PersistentStack<E> reverse;

        
        private PersistentQueue(PersistentStack<E> order, PersistentStack<E> reverse) {
                this.order = order;
                this.reverse = reverse;
        }
        
        /**
         * requires default constructor.
         */
        public PersistentQueue() {
                this.order = PersistentStack.emptyStack();
                this.reverse = PersistentStack.emptyStack();
        }

        /**
         * Returns the queue that adds an item into the tail of this queue without
         * modifying this queue.
         * 
         * <pre>
         * e.g.
         *  When this queue represents the queue (2,1,2,2,6) and we enqueue the value 4 into this queue,
         *  this method returns a new queue (2,1,2,2,6,4)
         *  and this object still represents the queue (2,1,2,2,6)
         * </pre>
         * 
         * @param e
         * @return
         */
        public PersistentQueue<E> enqueue(E e) {
                if (null == e)
                        throw new IllegalArgumentException();
                return new PersistentQueue<E>(this.order.push(e), this.reverse);
        }

        /**
         * Returns the queue that removes the object at the head of this queue
         * without modifying this queue.
         * 
         * <pre>
         * e.g.
         *  When this queue represents the queue (7,1,3,3,5,1) .
         *  this method returns a new queue (1,3,3,5,1)
         *  and this object still represents the queue (7,1,3,3,5,1)
         * </pre>
         * 
         * If this queue is empty, throws java.util.NoSuchElementException.
         * 
         * @param e
         * @return
         */
        public PersistentQueue<E> dequeue() {
                if (this.isEmpty())
                        throw new NoSuchElementException();
                if (!this.reverse.isEmpty()) {
                        return new PersistentQueue<E>(this.order, this.reverse.tail);
                } else {
                        // revers the ordered stack then "clean" that stack
                        return new PersistentQueue<E>(PersistentStack.emptyStack(),
                                        this.order.toReverseStack().tail);
                }
        }

        /**
         * This method simply reverse the order stack and assign it to reverse
         * stack, the internal queue is not modified, it is necessary since all new
         * objects are enqueued to order stack, while peek() looking at the reverse
         * stack, we do not want to reverse the order stack again and again while
         * looking for the head of reverse when it is empty.
         */
        private void balanceQueue() {
                this.reverse = this.order.toReverseStack();
                this.order = PersistentStack.emptyStack();
        }

        /**
         * Looks at the object which is the head of this queue without removing it
         * from the queue.
         * 
         * <pre>
         * e.g.
         *  When this queue represents the queue (7,1,3,3,5,1) .
         *  this method returns 7 and this object still represents the queue (7,1,3,3,5,1)
         * </pre>
         * 
         * If this queue is empty, throws java.util.NoSuchElementException.
         * 
         * @param e
         * @return
         */
        public E peek() {
                if (this.isEmpty())
                        throw new NoSuchElementException();
                if (this.reverse.isEmpty())
                        balanceQueue();
                return this.reverse.head;
        }

        public boolean isEmpty() {
                return size() == 0;
        }

        /**
         * Returns the number of objects in this queue.
         * 
         * @return
         */
        public int size() {
                return this.order.size + this.reverse.size;
        }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值