zoukankan      html  css  js  c++  java
  • 数据结构-使用两个栈实现一个队列

    1:如何只使用stack实现queue呢?我们知道stack是先进后出的(FIFO),而queue是先进先出的(FIFO)。也就是说,stack进行了一次反向。如果进行两次反向,就能实现queue的功能,所以我们需要两个stack实现queue。

        下面是具体思路。

    假设有两个栈A和B,且都为空。可以认为栈A为提供入队列的功能,栈B提供出队列的功能。

    (1)如果栈B不为空,直接弹出栈B的数据。

    (2)如果栈B为空,则依次弹出栈A的数据,放入到栈B中,再弹出栈B的数据。

    代码如下:

    #include "stdafx.h"
    #include<malloc.h>
    #include <iostream>
    #include <assert.h>
    using namespace std;
    
    /*单链表的节点,data表示节点的数据域,next指向下一个节点*/
    class MyData
    {
    public:
        MyData() :data(0), next(NULL) {};//默认构造函数,这样表示后,主体中不用再写这个函数了
        MyData(int value) :data(value), next(NULL) {};//带参数的构造函数
        int data;//数据域
        MyData *next;//下一个节点
    };
    
    /*表示栈的定义,其中public成员top表示栈顶,由于不能直接操作栈底,因此这里没有定义栈底的指针。
    在默认构造函数中,把栈顶指针top置空,表示此时栈为空栈。*/
    class MyStack
    {
    public:
        MyStack() :top(NULL) {};//默认构造函数
        void push(MyData data);//进栈
        void pop(MyData *pData);//出栈
        bool IsEmpty();//是否为空栈
        MyData *top;//栈顶
    };
    
    class MyQueue
    {
    public:
        void enqueue(MyData data);//入队
        void dequeue(MyData &data);//出队
        bool IsEmpty();//是否为空队
    private:
        MyStack s1;//用于入队
        MyStack s2;//用于出队
    };
    
    //进栈
    void MyStack::push(MyData data)
    {
        MyData *pData = NULL;
        pData = new MyData(data.data);//生成新节点
        pData->next = top;
        top = pData;
    }
    
    //判断栈是否为空
    bool MyStack::IsEmpty()
    {
        return(top == NULL);//如果top为空,则返回1,否则返回0
    }
    
    //出栈
    void MyStack::pop(MyData *data)//将删除的节点保存到data中
    {
        if (IsEmpty())//如果栈为空,直接返回
        {
            return;
        }
        data->data = top->data;//给传出的参数赋值
        MyData *p = top;//临时保存原栈顶节点
        top = top->next;//移动栈顶,指向下一个节点
        delete p;//释放原栈顶节点内存
    }
    
    
    //入队
    void MyQueue::enqueue(MyData data)
    {
        s1.push(data);//只对s1进行操作
    }
    
    //出队
    void MyQueue::dequeue(MyData &data)
    {
        MyData temp(0);//局部变量,用于临时存储
        if (s2.IsEmpty())
        {
            while (!s1.IsEmpty())//如果s2为空,把s1的所有元素push到s2中
            {
                s1.pop(&temp);//弹出s1的元素
                s2.push(temp);//压入s2中
            }
        }
        if (!s2.IsEmpty())
        {
            s2.pop(&data);//此时s2不为空,则弹出s2的栈顶元素
        }
    }
    
    //队列判空
    bool MyQueue::IsEmpty()
    {
        //如果两个栈都为空,则返回1,否则返回0
        return(s1.IsEmpty() && s2.IsEmpty());
    }
    int main()
    {
        MyData data(0);//定义一个节点
        MyQueue q;
    
        q.enqueue(MyData(1));
        q.enqueue(MyData(2));
        q.enqueue(MyData(3));
    
        q.dequeue(data);
        cout << "dequeue" << data.data << endl;
        q.dequeue(data);
        cout << "dequeue" << data.data << endl;
        q.dequeue(data);
        cout << "dequeue" << data.data << endl;
        cout << "IsEmpty:" << q.IsEmpty() << endl;
    
    
        return 0;
    }
    View Code

    运行结果:

  • 相关阅读:
    二叉树--转换二叉树(leetcode 108,leetcode 109)
    二叉树--层序遍历(leetcode 102
    二叉树--对称二叉树(leetcode 101
    数据库事务隔离
    二叉树--后序遍历的递归和非递归(leetcode 145
    二叉树--中序遍历的递归和非递归(leetcode 94
    二叉树--先序遍历的递归和非递归(leetcode 144
    链表--排序链表(leetcode 148
    接口的调用
    查锁表以及杀进程
  • 原文地址:https://www.cnblogs.com/lovemi93/p/7607203.html
Copyright © 2011-2022 走看看