在简单算法中对栈和队列进行比较

(题目来源:力扣LeetCode)

包括:225、用队列实现一个栈      232、用栈实现一个队列

写在前面:队列和栈的特点刚好相反

队列(Queue)先进先出(First-in First-out);  

栈(Stack)后进先出(Last-in First-out)


问题:如何是转换两者呢?答:使用两个队列/栈


题目:请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通队列的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。

int pop() 移除并返回栈顶元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。


示例:

输入:

["MyStack", "push", "push", "top", "pop", "empty"]

[[], [1], [2], [], [], []]

输出:

[null, null, null, 2, 2, false]

解释:

MyStack myStack = new MyStack();

myStack.push(1);

myStack.push(2);

myStack.top(); // 返回 2

myStack.pop(); // 返回 2

myStack.empty(); // 返回 False


详解:

class MyStack {

//类的属性

    Queue<Integer> queue1;

    Queue<Integer> queue2;

//初始化构造函数

    public MyStack() {

        queue1= new LinkedList<Integer>();

        queue2= new LinkedList<Integer>();

    }

//入栈方法

    public void push(int x) {

        queue2.offer(x);

        while(!queue1.isEmpty()){

            queue2.offer(queue1.poll());

        }

//精髓,交换队列(空间换时间)

        Queue<Integer> temp = queue1;

        queue1  = queue2;

        queue2  = temp;

    }

//出栈方法

    public int pop() {

        return queue1.poll();

    }

//查看栈顶元素

    public int top() {

        return queue1.peek();

    }

//判断为空

    public boolean empty() {

        return queue1.isEmpty();

    }

}

本题小结:

本题用了一个主队列和一个辅助队列实现了,栈的操作。其实就是当元素入队时对当前元素进行重新排序,使队列从先进先出的顺序变成先进后出的顺序。

在实现入栈方法的时候,将新入队的元素放入辅助队列中,并且进行重新排序使元素的顺序反转,然后使用了temp直接交换两个队列,而不是通过遍历交换两队列中的元素,使用空间换了时间。


题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false


示例:

输入:

["MyQueue", "push", "push", "peek", "pop", "empty"]

[[], [1], [2], [], [], []]

输出:

[null, null, null, 1, 1, false]

解释:

MyQueue myQueue = new MyQueue();

myQueue.push(1); // queue is: [1]

myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)

myQueue.peek(); // return 1

myQueue.pop(); // return 1, queue is [2]

myQueue.empty(); // return false

详解:

class MyQueue {

    Stack<Integer> instack;

    Stack<Integer> outstack;


    public MyQueue() {

        instack=new Stack<>();

        outstack=new Stack<>();

    }



    public void push(int x) {

        instack.push(x);

    }



    public int pop() {

        if(outstack.isEmpty()){

            while(!instack.isEmpty())

            outstack.push(instack.pop());

        }

        return outstack.pop();

    }



    public int peek() {

        if(outstack.isEmpty()){

            while(!instack.isEmpty())

            outstack.push(instack.pop());

        }

        return outstack.peek();

    }


    public boolean empty() {

        return instack.isEmpty() && outstack.isEmpty();

    }

}

本题小结:本题是使用栈实现队列的相关方法,思想与上一题类似,不过也有不同的解法。本题可以使用栈的使用,可以用两个栈,直接对栈内所有的元素进行反转。

比如:元素的入栈顺序是1,2,3.那么他们在经过第一个栈的出栈之后就变成了3,2,1.此时从第一个栈内出栈的元素再进第二个栈,那么此时的入栈顺序就是3,2,1.经过第二个栈的出栈之后就是1,2,3了。如此就完成了栈内元素的反转了。

值得注意的是,当第二个栈中有元素时,又需要新添加元素,必须先将第二个栈中的元素弹出,直到第二个栈为空时,才能将新元素放入第二个栈中


总结:

1、队列和栈的特点相反,队列先进先;栈先进后出,,在一定的情况下可以相互转换,比如:用队列实现栈,或者用栈实现队列。

2、想要熟悉栈和队列的话,那么二者的常用方法的使用以及实现一定要熟悉

比如:队列的常用方法有:

1)入队:使用offer/add都可以但是二者也有区别:

一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。

2)出队:pop/remove:

remove() 和 poll() 方法都是从队列中删除第一个元素。

remove()方法在失败的时候会抛出异常

poll() 方法在用空集合调用时不是抛出异常,只是返回 null。

3)查看队首元素:peek/element:

element() 和 peek() 用于在队列的头部查询元素。

在队列为空时, element() 抛出一个异常,而 peek() 返回 null。


栈的常用方法有:

1)入栈:push

//压栈操作(插入元素)(O(1))

public void push(long x){

stackArray[++top]=x;

}


2)出栈:pop

//出栈操作(删除元素)(O(1))

public long pop(){

return stackArray[top--];

}


3)访问栈顶元素:peek

//访问栈顶元素(O(1))

public long peek(){

return stackArray[top];

}


4)判断栈是否为空:isEmpty

//判断栈是否为空

public boolean isEmpty(){

return (top==-1);

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容