数据结构《21》----2014 WAP 初试题----Immutable queue

2014 WAP初试题----实现一个不可变的队列:

看似很简单。。实则,不同的版本效率的差距可能是巨大的。。甚至难以想象。。

之前用STL库的queue进行了对比,差别非常大。。


用上一篇文章的immutable stack 来实现 immutable queue.

其实就是用两个栈实现队列,具体的思想可以参考 编程之美。。

注意:代码中析构函数那一段代码的目的主要是为了避免析构函数递归调用时递归深度太大。。

通过将链表后序的节点的智能指针复制到局部的vector中,通过vector的析构函数自动调用成员的析构函数的规则来实现。。

可能有点绕,大家可以仔细琢磨以下。。


附加题:

实现一个reverse操作(这道题据说坑了不少同学,其实非常地简单,一句话就能搞定)

//copyrigt @ L.J.SHOU May.25, 2014
#include 
   
   
    
    
using namespace std;

/**
 * This class is a functional datatype, representing 
 *      an immutable first-in-first-out(FIFO) queue of objects.
 *
 * amortized O(1) cost
 *
 * implementation details:
 * 1. two lists are used as stacks to mimic queue
 *    front: for dequeue 
 *    rear:  for enqueue
 *    Once front is empty, rear are reversed and added to front
 *    so front is empty, if and only if rear is empty too.
 *
 * 2. std::shared_ptr is used to collect garbage
 */
template
    
    
     
     
class immutable_queue
{
  class List;
public:
  immutable_queue();
  immutable_queue(List front, List rear);
  ~immutable_queue();
  immutable_queue
     
     
      
       enqueue(const T &element);
  immutable_queue
      
      
       
        dequeue();
  immutable_queue
       
       
         reverse(); immutable_queue 
        
          append(immutable_queue 
         
           & rhs) { immutable_queue 
          
            res = *this; immutable_queue 
           
             temp = rhs; while(!temp.empty()) { res = res.enqueue(temp.peek()); temp = temp.dequeue(); } return res; } T getMax(); T peek(); int size(); bool empty() { return front_.empty() && rear_.empty(); } private: List front_, rear_; // two stacks to mimic queue // utility list class class List { struct Node { Node(T x, shared_ptr 
            
              &tail) : val_(x), next_(tail), max_(x){ if(tail) max_ = max(val_, tail->max_); } /** * To avoid too deep recursive call * * Normally, default destructor provided by c++ compiler is enough * but in some cases, where the list is too long, * the recursive call of this function would be too deep, * leading a stack overflow error. */ ~Node() { shared_ptr 
             
               *ptr = &next_, *next(nullptr); vector 
               
               
                 > vec; while(*ptr) { if((*ptr).unique() == false) break; next = &((*ptr)->next_); vec.push_back(*ptr); *ptr = nullptr; ptr = next; } } T val_; T max_; shared_ptr 
                
                  next_; }; public: List(): count_(0), head_(nullptr) {} List(T x, List tail): head_(make_shared 
                 
                   (x, tail.head_)){ count_ = 1 + tail.count_; } int size() { return count_;} bool empty() { return count_ == 0;} T getMax() { assert(!empty()); return head_->max_;} T getHead() { assert(!empty()); return head_->val_;} List getTail() { assert(!empty()); return List(head_->next_, count_-1);} List addHead(const T &x) { return List(x, *this); } // *this should not be changed List reverse() { List new_list; List it = *this; // make a "copy" first for(int i=0; i 
                  
                    tail, int count) : head_(tail), count_(count) {} shared_ptr 
                   
                     head_; int count_; }; }; /** * requires default ructor */ template 
                    
                      immutable_queue 
                     
                       ::immutable_queue() { front_ = List(); rear_ = List(); } template 
                      
                        immutable_queue 
                       
                         ::immutable_queue(List front, List rear) { // front is empty only if rear is empty too if(front.empty() && !rear.empty()) { this->front_ = rear.reverse(); this->rear_ = List(); } else { this->front_ = front; this->rear_ = rear; } front = List(); rear = List(); } /** * default destructor */ template 
                        
                          immutable_queue 
                         
                           ::~immutable_queue() { } /** * Returns the queue that adds an item into the tail of this queue without * modifying this queue. * * 
                          * * @param e * @return */ template 
                         
                           immutable_queue 
                          
                            immutable_queue 
                           
                             ::enqueue(const T &element) { //make this method faster return immutable_queue 
                            
                              (front_, rear_.addHead(element)); } /** * Returns the queue that removes the object at the head of this queue * without modifying this queue. * * 
                             
 * 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)
 * 
* * If this queue is empty, throws range_error * * @param e * @return */ template immutable_queue immutable_queue ::dequeue() { //make this method faster if(empty()) { throw range_error("Opps, this queue is empty, nothing to dequeue"); } return immutable_queue (front_.getTail(), rear_); } template immutable_queue immutable_queue ::reverse() { return immutable_queue (rear_, front_); } template T immutable_queue ::getMax() { //make this method faster if(empty()) { throw range_error("Opps, this queue is empty"); } T res = front_.getMax(); if(!rear_.empty()) res = max(res, rear_.getMax()); return res; } /** * Looks at the object which is the head of this queue without removing it * from the queue. * *
 * 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)
 * 
* * If this queue is empty, throws range_error * * @param e * @return */ template inline T immutable_queue ::peek() { if(empty()) { throw range_error("Opps, this queue is empty. nothing to peek"); } return front_.getHead(); } /** * Return the number of objectes in this queue * @return */ template inline int immutable_queue ::size() { return front_.size() + rear_.size(); } int main(void) { immutable_queue p1; p1 = p1.enqueue(1); p1 = p1.enqueue(2); p1 = p1.enqueue(3); assert(p1.size() == 3); immutable_queue p2 = p1.enqueue(0); p2 = p2.enqueue(4); p2 = p2.enqueue(5); p2 = p2.enqueue(6); assert(p2.size() == 7); assert(p1.size() == 3); p1 = p1.append(p2); assert(p1.size() == 10); assert(p2.getMax() == 6); immutable_queue temp = p2.reverse(); while(!temp.empty()) { cout << temp.peek() << " "; temp = temp.dequeue(); } cout << endl; return 0; }

 * 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)
 * 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值