算法--栈和队列互相实现

数据结构与算法

1栈与队列的区别

  1. 队列先进先出FIFO,栈先进后出FILO
  2. 对插入和删除操作的”限定”。 栈是限定只能在表的一端进行插入和删除操作的线性表。 队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
  3. 遍历数据速度不同
  4. java中:Stack是类继承Vector。Queue是一个接口实现了Collection,Iterable。

2 栈和队列方法概要

Java语言。

2.1 栈(Stack)方法概要

方法 作用 返回值
empty() 测试堆栈是否为空 boolean
peek() 查看堆栈顶部的对象,但不从堆栈中移除它。 E
pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。 E
push(E item) 把项压入堆栈顶部。 E
search(Object o) 返回对象在堆栈中的位置,以 1 为基数。使用 equals 方法比较 o 与堆栈中的项。 int

2.2 队列(Queue)方法概要

方法 作用 返回值
offer(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于add(E),后者可能无法插入元素,而只是抛出一个异常。 boolean
poll() 获取并移除此队列的头,如果此队列为空,则返回 null E
peek() 获取但不移除此队列的头;如果此队列为空,则返回 null。 E
add(E e) 将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。 boolean
element() 获取,但是不移除此队列的头 E
remove() 获取并移除此队列的头。 E

3 由两个栈实现一个队列 (✭✭✩✩✩)

实现一个队列主要是实现其方法。

3.1 分析

164c2a5b494d9d73.jpeg

3.2 撸码

public static class TwoStackQueue<E> {
    private Stack<E> stackA;
    private Stack<E> stackB;

    public TwoStackQueue() {
        stackA = new Stack<>();
        stackB = new Stack<>();
    }

    /**
     * 添加元素逻辑
     *
     * @param e 要添加的元素
     * @return 这里只是遵循 Queue 的习惯,这里简单处理返回 true 即可
     */
    public boolean add(E e) {
        stackA.push(e);
        return true;
    }

    /**
     * 去除元素的时候需要判断两个地方,StackA & StackB 是否都为空
     * StackB 为空的时候讲StackA中的元素全部依次压入 StackB
     *
     * @return 返回队列中的元素 如果队列为空返回 null
     */
    public E poll() {
        //如果队列中没有元素则直接返回空,也可以选择抛出异常
        if (stackB.isEmpty() && stackA.isEmpty()) {
            return null;
        }

        if (stackB.isEmpty()) {
            while (!stackA.isEmpty()) {
                stackB.add(stackA.pop());
            }
        }

        return stackB.pop();
    }

    /**
     * peek 操作不取出元素,只返回队列头部的元素值
     *
     * @return 队列头部的元素值
     */
    public E peek() {
        //如果队列中没有元素则直接返回空,也可以选择抛出异常
        if (stackB.isEmpty() && stackA.isEmpty()) {
            return null;
        }

        if (stackB.isEmpty()) {
            while (!stackA.isEmpty()) {
                stackB.add(stackA.pop());
            }
        }

        return stackB.peek();
    }
}

3.3用两个栈模拟实现一个队列,其最大容量是多少?

如果这两个堆栈的容量分别是m和n(m>n),你的方法能保证队列的最大容量是多少?

分析:栈的特点是“后进先出(LIFO)”,而队列的特点是“先进先出(FIFO)”。用两个栈模拟实现一个队列的基本思路是:用一个栈作为存储空间,另一个栈作为输出缓冲区,入队时把元素按顺序压入两栈模拟的队列,出队时按入队的顺序出栈即可

如下图,用容量为m(较大的)的栈作为存储空间,容量为n的栈作为输出缓冲区,先将入队的前n个元素push进存储空间栈


20200307205856303.png

随后对存储空间栈中的每个元素进行出栈(pop)操作,继而压入(push)输出缓冲区栈,如下图所示


20200307205951587.png

对于剩余入队的前n+1个元素,将他们压入存储空间栈,两个栈的状态如下图:


20200307210024814.png

此时已经入队了2n+1个元素,若此时进行出队操作,先将输出缓冲区栈中的元素出栈(pop)并输出:Q1,Q2 ,……,Qn,再对存储空间栈中的n个元素进行出栈(pop)并压入输入缓冲区栈,状态图如下:


20200307210325571.png

然后对存储空间栈进行一次出栈(pop)操作并输出:Qn+1,最后再对输出缓冲区栈中的所有元素进行出栈(pop)操作并输出Qn+2,Qn+3,......,Q2n,Q2n+1这样两个栈 总的输出序列为

即在已经入队了2n+1个元素的情况下,还要继续向队列中添加更多的元素,将无法满足按入队的顺序出队。
综上所述,两个栈所模拟的队列的最大容量为2n+1

4 两个队列实现一个栈 (✭✭✩✩✩)

4.1 解析

164c2a5b49e8e71b.jpeg

4.2 撸码

public static class TwoQueueStack<E> {
   private Queue<E> queueA;
   private Queue<E> queueB;

   public TwoQueueStack() {
       queueA = new LinkedList<>();
       queueB = new LinkedList<>();
   }

   /**
    * 选一个非空的队列入队
    *
    * @param e
    * @return
    */
   public E push(E e) {
       if (queueA.size() != 0) {
           System.out.println("从 queueA 入队 " + e);
           queueA.add(e);
       } else if (queueB.size() != 0) {
           System.out.println("从 queueB 入队 " + e);
           queueB.add(e);
       } else {
           System.out.println("从 queueA 入队 " + e);
           queueA.add(e);
       }
       return e;
   }

   public E pop() {
       if (queueA.size() == 0 && queueB.size() == 0) {
           return null;
       }

       E result = null;
       if (queueA.size() != 0) {
           while (queueA.size() > 0) {
               result = queueA.poll();
               if (queueA.size() != 0) {
                   System.out.println("从 queueA 出队 并 queueB 入队 " + result);
                   queueB.add(result);
               }
           }
           System.out.println("从 queueA 出队 " + result);

       } else {
           while (queueB.size() > 0) {
               result = queueB.poll();
               if (queueB.size() != 0) {
                   System.out.println("从 queueB 出队 并 queueA 入队 " + result);
                   queueA.add(result);
               }
           }
           System.out.println("从 queueB 出队" + result);
       }
       return result;
   }
}

参考

2018年Android面试题含答案--适合中高级(下)
算法之美:栈和队列

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容