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

题目一:用两个栈实现队列,队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列的尾部插入节点和在队列的头部删除节点的功能。

template <class T>

class CQueue

{
  CQueue();

  ~CQueue();

  void appendTail(const T& node);

  T deleteHead();

private:

  stack<T> stack1;

  stack<T> stack2;

};

如上图所示:每次插入结点时都插入到stack1,例如依次插入a,b,c,然后为了达到队列的先进先出特性也就是要删除a,但是stack1只有栈的特性,只会先输出c,故需要把stack1中的数据依次的输出到stack2中,存入stack2的序列分别为c,b,a,此时stack2的栈顶是a,也就是我们需要输出的元素。也就是说每次的插入都需要在stack1中进行,删除操作首先需要检查stack2是否为空,若不为空,则直接输出stack2的栈顶,否则依次把stack1中的元素全部导入到stack2然后再输出。

故可以写出简单的代码如下:

 1 #include<iostream>
 2 #include<stack>
 3 using namespace std;
 4 template <class T>
 5 class CQueue{
 6     CQueue();
 7     ~CQueue();
 8     void appendTail(const T& node);
 9     T deleteHead();
10 private:
11     stack<T> stack1;
12     stack<T> stack2;
13 };
14 template <class T>
15 void CQueue<T>::appendTail(const T& node)
16 {
17     stack1.push(node);//入队列全放入stack1
18 }
19 template <class T>
20 T CQueue<T>::deleteHead()
21 {
22     if (stack2.size() <= 0)
23     {
24         if (stack1.size() <= 0)
25             throw exception("the queue is empty");//两个栈都为空
26         else{//stack1不为空,stack2为空,则stack1全部入stack2
27             while (stack1.size() > 0){
28                 T value = stack1.top();
29                 stack2.push(value);
30                 stack1.pop();
31             }
32         }
33     }//stack2不为空则直接输出
34     T r_value = stack2.top();
35     stack2.pop();
36     return r_value;
37 }

题目二:用两个队列实现栈,栈的声明如下,分别实现栈的push()函数和topAnddelete()函数,用来完成在栈的顶部插入和删除(返回栈顶值)的操作

template <class T>

class CStack{
  CStack();

  ~CStack();

  void push(const T& node);

  T topAnddelete();

private:

  queue<T> queue1;

  queue<T> queue2;

};

也就是说,根据上面的分析每次删除操作前,总有一个queue是空的,一个queue是满的(当然两个都为空时我们的删除操作直接抛出异常就可以了),然后满的那个queue一定是我们要在其上完成删除操作的,需要把满的queue除队尾元素之外的所有元素都移到另一个空的queue,然后再删除这个唯一的元素(删除后必然又有一个queue为空)。所以每次只需要检测哪个queue不为空然后完成相应的操作即可。

代码如下:

 1 #include<iostream>
 2 #include<queue>
 3 using namespace std;
 4 template <class T>
 5 class CStack{
 6 public:
 7         CStack();
 8         ~CStack();
 9         void push(const T& node);
10         T topAnddelete();
11 private:
12         queue<T> queue1;
13         queue<T> queue2;
14 };
15 template <class T>
16 void CStack<T>::push(const T &node)//每次都选择插入queue1
17 {
18     queue1.push(node);
19 }
20 template<class T>
21 T CStack<T>::topAnddelete()
22 {
23     if (queue1.empty() && queue2.empty()){//若为空抛出异常
24         throw exception("the stack is empty");
25     }
26     else if(!queue1.empty() && queue2.empty()){//queue1不为空,queue2为空
27         while (queue1.size() > 1){
28             T value = queue1.front();
29             queue2.push(value);
30             queue1.pop();
31         }
32         T r_value = queue1.front();
33         queue1.pop();
34         return r_value;
35     }
36     else{//queue2不为空,queue1为空
37         while (queue2.size() > 1){
38             T value = queue2.front();
39             queue1.push(value);
40             queue2.pop();
41         }
42         T r_value = queue2.front();
43         queue2.pop();
44         return r_value;
45     }
46 }
时间: 2024-10-13 13:53:59

用两个栈实现队列和用两个队列实现栈的相关文章

剑指Offer面试题7(Java版):用两个栈实现队列与用两个队列实现栈

题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deletedHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能. 我们通过一个具体的例子来分析该队列插入和删除元素的过程.首先插入一个元素a,不妨先把它插入到stack1,此时stack1 中的元素有{a},stack2为空.再压入两个元素b和c,还是插入到stack1中,此时stack1中的元素有{a,b,c},其中c位于栈顶,而stack2仍然为空. 这个时候,我们试着删除从队列中删除一个元素.

自定义栈的实现及使用两个栈模拟队列

一,使用单链表实现栈 ①栈需要一个栈顶指针 ②栈的基本操作有出栈和入栈,以及判断栈是否为空 ③单链表中每个结点表示一个栈元素,每个结点有指向下一个结点的指针.因此,在栈内部需要实现一个单链表.代码如下: public class Stack<T extends Comparable<? super T>>{ private class Node{ T ele; Node next; public Node(T ele) { this.ele = ele; } } Node top;

数据结构和算法之栈和队列一:两个栈模拟一个队列以及两个队列模拟一个栈

今天我们需要学习的是关于数据结构里面经常看到的两种结构,栈和队列.可以说我们是一直都在使用栈,比如说在前面递归所使用的的系统的栈,以及在链表倒序输出时介绍的自定义栈类Stack和使用系统的栈进行递归.那么,在这里我们就讲述一下这两个比较具有特色的或者说关系比较紧密的数据结构之间的互相实现问题. 一:两个栈模拟实现一个队列: 栈的特点是先进后出,然而队列的特点是先进先出. public class Queen(Stack s1,Stack s2){ //实现插入的方法 public void ad

队列ADT的两种简单实现

队列在书中说明的方式是两种,一种最简单的链表队列,判断情况比较简单,另一种是使用数组进行创建,限制较多,但是速度较快,也比较容易控制内存,不至于出现在链表实现上那么复杂的内存控制. 下面先是链表实现: ListQueue.cpp 1 #include "iostream" 2 #include "stdlib.h" 3 4 typedef struct _queue_ 5 { 6 int data; 7 struct _queue_ *next; 8 }queue;

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个被线程被唤醒 (notify)后,才会进入到就绪队列,等待获得锁. 当一开始线程a第一次执行account.add方法时,jvm会检查锁对象account 的就绪队列是否已经有线程在等待,如果有则表明account的锁已经被占用了,由于是第一次运行,account的就绪队列为空,所以线程a获得了锁, 执行account.add方法.如果恰好在这个时候,线程b要执行accoun

C语言使用栈实现String类型的两个大数相加

要开始找工作了,记录下学习的关于数据结构的应用~~从栈开始~~ 栈和指针的应用~~~ 实现String类型的两个大数相加 主要思想是通过C语言的栈来实现,栈是后进先出的特点,因此很适合做这类计算.建立四个栈,分别按字符串字符先后顺序入栈大数的整数部分和小数部分,然后先计算小数部分的,由于小数部分是高位对齐,因此一直出栈最长小数栈的字符并进入小数结果的栈,小数位数对齐后,两个小数栈出栈进行相加.然后进行整数栈相加,由于整数部分是按低位对齐,因此直接出栈相加即可,将每位相加结果入结果整数栈.比如字符

看数据结构写代码(16)顺序队列的实现(循环队列)

循环队列的基本结构如下: front 属性 表示 队头,rear 属性表示 队尾. 在队空时 :q.rear 和 q.front 都为0 ,其余时刻q.rear 指向 队尾的后继节点,q.front指向 队头. 当在队尾插入元素时,q.rear + 1 ,在删除 队头元素时 ,q.front + 1,这样的操作 会造成 "假溢出"问题. 图(d) 就是一种 假溢出 问题,q.rear 指向 空间的边界,再插入 会造成 溢出,但是 实际上 空间 并未满. 为了解决假溢出,将 队列 看成

bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&amp;&amp;bzoj1692[Usaco2007 Dec]队列变换*

bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换 bzoj1692[Usaco2007 Dec]队列变换 题意: 有一个奶牛队列.每次可以在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里.这样得到的队列,就是FJ拉去登记的最终的奶牛队列. 求对于给定的奶牛们的初始位置,计算出可能得到的字典序最小的队列.队列大小≤30000. 题解: 有一个结论:如果当前队列中的队首元素不等于队尾元

IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispatch_queue_t,队列名称在调试时辅助,无论什么队列和任务,线程的创建和回收不需要程序员操作,有队列负责. 串行队列:队列中的任务只会顺序执行(类似跑步) dispatch_queue_t q = dispatch_queue_create(“....”, DISPATCH_QUEUE_SER

13 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件  queue队列 生产者消费者模型 Queue队列 开发一个线程池

本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 操作系统发展史 手工操作(无操作系统) 1946年第一台计算机诞生--20世纪50年代中期,还未出现操作系统,计算机工作采用手工操作方式. 手工操作程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把