zoukankan      html  css  js  c++  java
  • 《剑指Offer》附加题_用两个队列实现一个栈_C++版

      在《剑指Offer》中,在栈和队列习题中,作者留下来一道题目供读者自己实现,即“用两个队列实现一个栈”。
      在计算机数据结构中,栈的特点是后进先出,即最后被压入(push)栈的元素会第一个被弹出(pop);队列的特点是先进先出,即第一个进入队列的元素将会被第一个弹出来。虽然栈和队列特点是针锋相对,但是两者却相互联系,可以互相转换。
      在“用两个队列实现一个栈”问题中,我们用两个队列的压入和弹出来模拟栈的压入和弹出。我们通过画图的手段把抽象的问题形象化。
      在上图中,我们先往栈内压入一个元素a。由于两个队列现在都是空,我们可以选择把a插入两个队列中的任一个。我们不妨把a插入queue1,接下来继续网栈内压入b,c两个元素。我们把它们都插入queue1。这个时候 queue1包含3个元素a,b,c,其中a位于队列的头部,c位于队列的尾部。
      现在我们考虑从栈内弹出一个元素。根据栈的后入先出的原则,最后被压入栈的c应该最先被弹出。由于c位于queue1的尾部,而我们每次只能从队列的头部删除元素,因此我们可以从queueu中依次删除a、b并插入到queue2中,再从queue1中删除c。这就相当于从栈中弹出元素c了。我们可以用同样的方法从栈内弹出元素b。
      接下来我们考虑从栈内压入一个元素d.此时queue1已经有了一个元素,我们就把d插入到queue1的尾部。如果我们再从栈内弹出一个元素,此时被弹出的应该是最后被压入的d.由于d位于queue1的尾部,我们只能先从头部删除queue1的元素并插入到queue2,直到queue1中遇到d再直接把它删除。
      注意:在上述思路中,两个队列存在全空队列和一个空队列的情况。所以,在程序中进入子函数第一步,要判断两个队列是否同时不为空(异常),增加程序的鲁棒性。另外,空栈删除元素要报异常,即两个队列均为空;
      程序实时更新在Github中: https://github.com/wylloong/TinyPrograms/blob/master/Coding%20Interviews/CStacks
                   https://github.com/wylloong/TinyPrograms/blob/master/Coding%20Interviews/StackwithTwoQueues
      
    ************************************************************
      C++程序实现: 
    // 面试题9附加题:用两个队列实现栈
    // 题目:用两个队列实现一个栈。栈的声明如下,请实现它的两个函数appendTail
    // 和deleteHead,分别完成在栈尾部插入结点和在栈头部删除结点的功能。
    
    #pragma once
    #include<queue>
    #include<exception>
    
    using namespace std;
    
    template <typename T> class CStack
    {
    public:
        CStack();
        ~CStack();
    
        void appendTail(const T& node);
        T deleteHead();
    
    private:
        queue<T> queue1;
        queue<T> queue2;
    };
    
    template<typename T> CStack<T>::CStack()
    {
    }
    
    template<typename T>  CStack<T>::~CStack()
    {
    }
    
    // 插入元素
    template<typename T> void CStack<T>::appendTail(const T& node)
    {
        if (queue1.size() > 0 && queue2.size() > 0)
        {
            //异常情况
        }
        else
        {
            //插入到非空队列,如果均为空则插入到queue2中
            if (queue1.size() == 0)
            {
                queue2.push(node);
            }
            else
            {
                queue1.push(node);
            }
        }
    }
    
    template<typename T> T CStack<T>::deleteHead()
    {
        if (queue1.size() == 0 && queue2.size() == 0)
        {
            //异常情况
            throw new exception("stack is empty");
        }
        T head;
        if (queue1.size() > 0)
        {
            while (queue1.size()>1)
            {
                //queue1中的元素依次删除,并插入到queue2中,其中queue1删除最后一个元素
                //相当于从栈中弹出队尾元素
    
                T& data = queue1.front();
                queue1.pop();
                queue2.push(data);
            }
            head = queue1.front();
            queue1.pop();
        }
        else
        {
            while (queue2.size()>1)
            {
                //queue2中的元素依次删除,并插入到queue1中,其中queue2删除最后一个元素
                //相当于从栈中弹出队尾元素
    
                T& data = queue2.front();
                queue2.pop();
                queue1.push(data);
            }
            head = queue2.front();
            queue2.pop();
        }
        return head;
    }
    #include"CStacks.h"
    
    // ====================测试代码====================
    void test(char actual, char expected)
    {
        if (actual == expected)
            printf("Test passed.
    ");
        else
            printf("Test failed.
    ");
    }
    
    int main(int argc, char* argv[])
    {
        // 后进先出
        CStack<char> stack;
    
        stack.appendTail('a');
        stack.appendTail('b');
        stack.appendTail('c');
    
        char head = stack.deleteHead();
        test(head, 'c');
    
        head = stack.deleteHead();
        test(head, 'b');
    
        stack.appendTail('d');
        head = stack.deleteHead();
        test(head, 'd');
    
        stack.appendTail('e');
        head = stack.deleteHead();
        test(head, 'e');
    
        head = stack.deleteHead();
        test(head, 'a');
    
        //空栈删除,触发异常
        //head = stack.deleteHead();
    
        getchar();
        return 0;
    }
     
  • 相关阅读:
    无限维
    黎曼流形
    why we need virtual key word
    TOJ 4119 Split Equally
    TOJ 4003 Next Permutation
    TOJ 4002 Palindrome Generator
    TOJ 2749 Absent Substrings
    TOJ 2641 Gene
    TOJ 2861 Octal Fractions
    TOJ 4394 Rebuild Road
  • 原文地址:https://www.cnblogs.com/DHUtoBUAA/p/7389076.html
Copyright © 2011-2022 走看看