java操作两个stack实现一个queue(并发下)

本文介绍了一种使用两个栈来实现队列的方法。通过详细解释两种实现思路,一是传统方式,涉及频繁倒栈操作;二是优化方案,在出队时按需倒栈,减少不必要的开销。文中还提供了Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果有一天你遇到这个问题、切忌浅尝辄止,提问题之人,肯定是想考察你思考问题的深度、头脑灵活清醒程度,一定要深究下去。其实这个问题实现很简单,主要是其中的具体细节难把握。情急之下,的确很难想完整(已排除天资聪颖之辈)。此篇文章只阐述两种思路。
具体思路这篇博客已经写的很详细了,此篇文章只是实现其思想,并指明在并发下情况下,该注意的地方。
(一)第一种方法应该是大多数人看到此题后的自然而然想到的对策。
这里写图片描述
如上图所示,
入队:将元素压入S1
出队:先把S1的所有元素倒入S2,将S2的头部元素弹出,然后将S2剩余元素再次倒入S1.代码实现如下

import java.util.Stack;

public class CustomQueue<T> {
    private Stack<T> stack1=new Stack<T>();
    private Stack<T> stack2=new Stack<T>();

    public synchronized void enque(T item){

        stack1.push(item);
    }

    public synchronized T deque(){

        T result=null;
        //把S1的元素倒入
        while(!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
        //弹出S2栈顶元素
        if(!stack2.isEmpty()){
            result=stack2.pop();
        }
        //把S2的元素倒回
        while(!stack2.isEmpty()){
            stack1.push(stack2.pop());
        }
        return result;

    }

    public static void main(String[] args){
        final CustomQueue<Integer> customQueue=new CustomQueue<Integer>();
        new Thread(new Runnable() {
            public void run() {
                while(true){
                    Integer m=customQueue.deque();
                    if(m!=null){
                        System.out.println(m);
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                for(int i=0;i<1000;i++){
                    customQueue.enque(i+1);
                }
                System.out.println(customQueue.stack1.toString());

            }
        }).start();


    }
}

需注意的是入队以及出队方法必须加锁,因为在多线程环境下会造成死循环或者队列元素无序,比如两个线程同时执行入队、出队方法。当出队操作中弹出栈顶元素后,往S1里倒回剩余元素时,因为入队操作同时往S1中添加元素,所以会出现【3,2,1,5,6,7】,显然是无序的数据。

此种思想有一个小细节的改善,就是当把S1中的元素倒入S2时,可以只倒入S1.size()-1的元素,直接把剩余的那一个元素弹出即可。deque()方法可以如下改善。

    public synchronized T deque(){

        T result=null;
        if(!stack1.isEmpty()){
            for(int i=0;i<stack1.size()-1;i++){
                stack2.push(stack1.pop());
                i--;
            }
            result=stack1.pop();

        }

        while(!stack2.isEmpty()){
            stack1.push(stack2.pop());
        }
        return result;

    }

(二)第二种方法
1)入队时,将元素压入s1。
2)出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。这个思路,避免了反复“倒”栈,仅在需要时才“倒”一次。

import java.util.Stack;

public class CustomQueue<T> {
    private Stack<T> stack1=new Stack<T>();
    private Stack<T> stack2=new Stack<T>();

    public synchronized void enque(T item){

        stack1.push(item);
    }

    public synchronized T deque(){

        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
        }
        if(!stack2.isEmpty()){
            return stack2.pop();
        }
        return null;

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值