Algorithm --> 两个栈实现队列和两个队列实现栈

两个栈实现队列和两个队列实现栈

  队列(queue)先进先出的线性表;栈(stack)先进后出的线性表。

两个栈实现队列

法一思路:

s1是入栈的,s2是出栈的。

  • 入队列:直接压入s1即可;
  • 出队列:如果s2不为空,把s2中的栈顶元素直接弹出;否则,把s1的所有元素全部弹出压入s2中,再弹出s2的栈顶元素。

代码:

#include <stack>
#include <iostream>
#include <cassert>
using namespace std;

template <class T>
class Queue {
public:
    bool empty( ) const { return m_stack1.empty() && m_stack2.empty(); }
    size_t size( ) const { return m_stack1.size() + m_stack2.size(); }
    void push( const T& x );
    void pop( );
private:
    stack<T> m_stack1;
    stack<T> m_stack2;
};

template <class T>
void Queue<T>::push( const T& x )
{
    m_stack1.push( x );
}

template <class T>
void Queue<T>::pop( )
{
    // if m_stack2 is empty, and there are some elements in m_stack1, push them in m_stack2
    if( m_stack2.empty() ) {
        while( !m_stack1.empty() ) {
            T& data = m_stack1.top( );
            m_stack1.pop( );
            m_stack2.push( data );
        }
    }
    // push the element into m_stack2
    assert( !m_stack2.empty() );
    m_stack2.pop( );
}

int main( )
{
    Queue<int> q;
    for( int i = 1; i <= 5; ++i )
        q.push( i );
    q.pop( );
    q.push( 6 );
    q.pop( );
    q.pop( );
    q.push( 7 );
    q.pop( );
    q.pop( );
    q.pop( );
    q.pop( );

    return 0;
}

法二思路:

用两个栈来实现,令其中一个栈inStack专门处理入队工作,另一个栈outStack专门处理出队工作。

  • 入队列:直接把元素加入到 inStack中,复杂度为O(1);
  • 出队列:因为队列是先入先出的,而栈是先入后出,所以输出应该反序。比如inStack接收到的元素顺序为1, 2, 3,栈顶元素是3,但出队希望让1先出。解决方法是把inStack里的元素放到outStack中,这样outStack接收到的元素顺序就是3, 2, 1了,栈顶元素就是我们想要的1,时间复杂度为O(N)。

总结,入队直接inStack.push(元素),出队先判断outStack是否为空,若不为空,则直接outStack.pop(),若为空,则把inStack元素导入到outStack里,再执行outStack.pop()。

#include <stack>
#include <string>
#include <iostream>
#include <cassert>

using namespace std;

template <class T>
class YL_Queue
{
public:
       void enqueue(const T &element); //入队
       T dequeue();   //出队
       T top();   //队首元素
       bool empty() const;  //判断队列是否为空
       size_t size() const;  //队列的尺寸大小
private:
        stack<T> inStack;
        stack<T> outStack;
};

template <class T>
void YL_Queue<T>::enqueue(const T &element)
{
    inStack.push(element);
}

template <class T>
T YL_Queue<T>::dequeue()
{
    assert(!empty());

    T temp;
    if (!outStack.empty())
    {
        temp=outStack.top();
        outStack.pop();
        return temp;
    }
    else
    {
        while(!inStack.empty())
        {
            temp=inStack.top();
            inStack.pop();
            outStack.push(temp);
        }
        temp= outStack.top();
        outStack.pop();
        return temp;
    }
}

template <class T>
T YL_Queue<T>::top()
{
    assert(!empty());

    T temp;
    if (!outStack.empty())
    {
        temp=outStack.top();
        return temp;
    }
    else
    {
        while(!inStack.empty())
        {
            temp=inStack.top();
            inStack.pop();
            outStack.push(temp);
        }
        temp= outStack.top();
        return temp;
    }
}

template <class T>
bool YL_Queue<T>::empty() const
{
    return (size()==0);
}

template <class T>
size_t YL_Queue<T>::size() const
{
    return inStack.size()+outStack.size();
}
void main()
{
    YL_Queue<int> myqueue;
    myqueue.enqueue(1);
    myqueue.enqueue(2);
    myqueue.enqueue(3);
    myqueue.enqueue(4);
    myqueue.enqueue(5);
    cout<<"1队列的大小为: "<<myqueue.size()<<endl;
    cout<<"1队首的元素为: "<<myqueue.top()<<endl;
    myqueue.dequeue();
    myqueue.dequeue();
    cout<<"2队列的大小为: "<<myqueue.size()<<endl;
    cout<<"2队首的元素为: "<<myqueue.top()<<endl;
    myqueue.dequeue();
    myqueue.dequeue();
    myqueue.dequeue();
    cout<<"3队列的大小为: "<<myqueue.size()<<endl;
}

两个队列实现栈

思路

s1是入队列的,s2是辅助s1入队列的。

  • 入队列:如果s1不空,把s1的元素push到s2中,之后push新元素到s1,再把s2的元素都push到s1中;否则,直接push元素到s1
  • 出队列:直接从s1中pop

代码:

#include <iostream>
#include <queue>
#include <cassert>
using namespace std;

template <class T>
class Stack {
public:
    bool empty( ) const { return m_queue1.empty() && m_queue2.empty(); }
    size_t size( ) const { return m_queue1.size() + m_queue2.size(); }
    T& top( );
    const T& top( ) const;
    void push( const T& x );
    void pop( );
private:
    queue<T> m_queue1;
    queue<T> m_queue2;
};

template <class T>
T& Stack<T>::top( )
{
    assert( !m_queue1.empty() );
    return m_queue1.front( );
}

template <class T>
const T& Stack<T>::top( ) const
{
    assert( !m_queue1.empty() );
    return m_queue1.front( );
}

template <class T>
void Stack<T>::push( const T& x )
{
    while( !m_queue1.empty() ) {  //s1不空,把元素push到s2
        const T& val = m_queue1.front( );
        m_queue1.pop( );
        m_queue2.push( val );
    }
    m_queue1.push( x );   //push新元素到s1
    while( !m_queue2.empty() ) {   //s2不空,把元素在push回s1
        const T& val = m_queue2.front( );
        m_queue2.pop( );
        m_queue1.push( val );
    }
}

template <class T>
void Stack<T>::pop( )
{
    assert( !m_queue1.empty() );
    m_queue1.pop( );
}

int main( )
{
    Stack<int> s;
    for( int i = 1; i <= 5; ++i )
        s.push( i );
    cout << "1.栈元素个数:" << s.size( ) << endl;
    cout << "1.栈顶元素:" << s.top( ) << endl;

    s.pop( );
    s.push( 6 );
    cout << "2.栈元素个数:" << s.size( ) << endl;
    cout << "2.栈顶元素:"<< s.top( ) << endl;

    s.pop( );
    s.pop( );
    s.pop( );
    s.push( 7 );
    cout << "3.栈元素个数:" << s.size( ) << endl;
    cout << "3.栈顶元素:"<< s.top( ) << endl;

    s.pop( );
    s.pop( );
    s.pop( );
    cout << "4.栈元素个数:" << s.size( ) << endl;

    return 0;
} 
时间: 2024-10-30 23:28:17

Algorithm --> 两个栈实现队列和两个队列实现栈的相关文章

两个栈实现一个队列和两个队列实现一个栈【算法导论课后题】

关于两个栈实现一个队列和两个队列实现一个栈问题,网上有很多资料.这里只描述自己认为操作最少的方法. 两个栈实现一个队列 思想:假设两个栈分别为s1,s2.对s1进行入队,出队时,先判断s2是否为空,如果是则将s1中元素压入s2并弹出最上面元素,如果不是,则直接弹出s2最上面的元素. <span style="font-size:18px;">EnQueue(s1,s2,k){ push(s1,k)</span><span style="font-

两个栈模拟一个队列和两个队列模拟一个栈

此为网易的一道笔试题.到时候秀逗,不知所云.后来研究之后记录下,以备以后经常翻阅. 栈:先进后出 push和pop 队列:先进先出 offer和poll (1)两个栈模拟一个队列 即将先进后出实现先进先出.比较容易理解,只要所有数据先往一个栈里push,然后将该栈中的数据依次pop出来再push进第二个队列,则顺序自然颠倒过来了,则每次pop是从第二个队列中取数据. import java.util.*; public class StackQueue{ private Stack<Intege

用两个栈实现一个队列 &amp; 用两个队列实现一个栈

队列(先进先出)和栈(先进后出)都是常用的经常讨论的基本的数据结构,本文要讨论的是一对有趣的问题:如何用两个栈(队列)实现一个队列(栈),下面将分别说明,并附示例代码. 1.用两个栈实现一个队列 基本思路:初始有两个空栈s1和s2,当入队列是,将元素加入s1,而出队列则从s2出,当然s1与s2之间存在一定的交互. 入队:元素压入栈s1即可. 出队:首先看s2是否为空,若s2为空,则依次弹出s1的元素,加入s2中:若不为空,则不需额外处理: 之后弹出s2中的栈顶元素(即为队列的首元素)删除即可.

包含MIN函数的栈+一个数组实现两个堆栈+两个数组实现MIN栈

1.题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 思路:利用一个辅助栈来存放最小值 栈  3,4,2,5,1 辅助栈 3,2,1 每入栈一次,就与辅助栈顶比较大小,如果小就入栈,如果大就不入栈当前的辅助栈:当出栈时,辅助栈元素相等时也要出栈. class Solution { public: stack<int> mystack1;//辅助栈 stack<int> minstack;//最小栈 void push(int value) { if(

两栈共享空间的存储结构和入栈出栈操作

参考<大话数据结构>P95~96——两栈共享存储空间. 当两个栈的需求空间有相反关系时,也就是一个栈增长时,另一个栈在缩短,可以采用两栈共享空间结构.这是针对两个具有相同数据类型的栈的一个设计技巧. 举个简单的例子: 代码和解释如下(VS2012测试通过): 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 #define MAXSIZE 6 //本例中栈满共6个元素 6 typed

顺序栈的实现和两栈共享空间

顺序栈的实现和两栈共享空间 一.顺序栈的实现 栈(stack)是限定仅在表尾进行插入或删除操作的线性表.我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何 数据元素的栈称为空栈.栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构. 理解栈的定义需要注意: 首先他是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系.只不过他是一种特殊的线性表而已.定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底. 他的

Linux 进程间通信 消息队列 实现两个进程间通信

例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据 文件1 创建进程1 终端输入通过消息队列发送数据 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <s

使用java语言实现一个队列(两种实现比较)(数据结构)

一.什么是队列,换句话说,队列主要特征是什么? 四个字:先进先出 六个字:屁股进,脑袋出 脑补个场景:日常排队买饭,新来的排在后面,前面打完饭的走人,这就是队列: OK,思考一个问题,我为什么写了两种实现,它们的区别是什么,哪个性能更好一些? 我觉得学习一定要带着问题来学习: 二.队列的两种实现 1.数组队列 数组队列比较简单,基于之前写的动态数组所实现的,基本方法都是根据队列的特性从而选择性的调用动态数组的方法来实现的. public class ArrayQueue<E> implemen

数据结构-栈的顺序结构两种方式

第一种结构: 存储空间有限,适用于知道存储长度的情况下.操作实现很简单. 1 #include "stdio.h" 2 3 4 #define MAXSIZE 50 5 #define STACKINCREMENT 10 6 #define OK 1 7 #define ERROR 0 8 typedef int SElemType; 9 typedef int Status; 10 11 typedef struct 12 { 13 SElemType data[MAXSIZE];