Use stack (LIFO) to simulate queue (FIFO)

原创转载请注明出处:http://agilestyle.iteye.com/blog/2360962

 

Solution

1. Using 2 stacks

1.1. One stack to accept incoming values in FILO manner

1.2. The other stack to reverse the values in first stack, so LIFO+LIFO becomes FIFO for value retrieval

 

2. An example

2.1. Incoming order: (1,2,3)

2.2. Stack 1 storage order(top to bottom): (3,2,1)

2.3. Stack 2 after pushing and popping all values in Stack 1:(top to bottom): (1,2,3)

 

3. One important thing

The reverse of all values in Stack 1 to stack 2 happens only stack 2 is empty!!!

 

package org.fool.java.test;

import java.util.Stack;

public class MyStackQueueTest {
    public static void main(String[] args) throws Exception {
        MyStackQueue<Integer> q = new MyStackQueue<>();
        q.enQueue(1);
        q.enQueue(2);
        q.enQueue(3);
        q.enQueue(4);

        System.out.println(q.deQueue());
        System.out.println(q.deQueue());
        System.out.println(q.deQueue());
        System.out.println(q.deQueue());

        q.enQueue(5);
        q.enQueue(6);
        q.enQueue(7);

        System.out.println(q.deQueue());
        System.out.println(q.deQueue());
        System.out.println(q.deQueue());
    }
}

class MyStackQueue<T> {
    Stack<T> s1 = new Stack<>();
    Stack<T> s2 = new Stack<>();

    public void enQueue(T k) {
        s1.push(k);
    }

    public T deQueue() throws Exception {
        if(s2.isEmpty() && s1.isEmpty()) {  // if no elements at all
            throw new Exception("no elements!");
        } else if(s2.isEmpty()) {   // get all elements in s1 and save to s2
            while (!s1.isEmpty()) {
                s2.push(s1.pop());
            }
        }

        return s2.pop();
    }
}

Console Output


 

Reference

https://www.youtube.com/watch?v=fPHXQP3Flno&list=PLlhDxqlV_-vkak9feCSrnjlrnzzzcopSG&index=31&spfreload=10 

 

<think>好的,我现在需要回答用户关于栈的LIFO特性和队列的FIFO特性的对比及其应用场景的问题。首先,我得回顾一下之前提供的引用内容,确保准确理解两者的定义和实现方式。 用户提到了引用[1]、[2]、[3]、[4]、[5],这些引用中详细说明了栈和队列的基本概念、代码实现以及它们的操作方式。比如,引用[4]提到栈是后进先出,而队列是先进先出。引用[2]和[5]分别用Python和JavaScript代码示例展示了队列和栈的操作,比如push和pop(对于栈)以及shift(对于队列)。此外,引用[3]中的C语言代码展示了队列的出队操作和栈的实现。 接下来,我需要对比LIFOFIFO的特性。栈的LIFO意味着最后插入的元素最先被移除,而队列的FIFO则是先进入的元素先被处理。这种结构差异导致它们的应用场景不同。例如,栈常用于需要回溯操作的场景,如函数调用栈、括号匹配等,而队列适用于任务排队、广度优先搜索等需要按顺序处理的场景。 我需要考虑如何组织这些信息,使其结构清晰。可能分成几个部分:特性对比、应用场景、具体实例。同时,用户希望看到对比表格和实际代码示例,这样更直观。另外,要确保使用正确的中文表达,符合LaTeX格式要求,比如数学公式用$...$,独立公式用$$...$$。 需要注意的是,用户之前的问题是关于图的遍历算法,但当前问题转向数据结构的基础,所以可能需要调整引用中的相关内容,比如栈在DFS中的应用,队列在BFS中的应用,作为例子说明两者的应用差异。此外,用户可能对实际代码示例感兴趣,所以需要从引用中提取相关代码,比如栈的入栈出栈操作,队列的入队出队操作。 还要检查是否有遗漏的应用场景,比如栈用于撤销操作、表达式求值,队列用于打印任务调度、消息队列等。确保覆盖这些内容,并结合引用中的信息进行说明。例如,引用[5]提到队列的shift方法,可以用来解释FIFO的具体实现。 最后,生成相关问题,帮助用户进一步理解。问题需要围绕栈和队列的区别、实现方式、应用场景展开,比如如何用栈实现队列,或者在特定场景下选择哪种结构更合适。 总结一下,回答的结构应该是:引言、特性对比(表格)、应用场景(分栈和队列)、代码示例、总结,最后相关问题。需要确保每个部分都参考了提供的引用内容,正确标注引用标识,并保持语言自然流畅。</think>#### 栈的LIFO与队列的FIFO特性对比及应用场景 --- ### 一、核心特性对比 | **特性** | **栈(LIFO)** | **队列(FIFO)** | |-------------------|-------------------------------------------------------|------------------------------------------------------| | **操作原则** | 后进先出(Last In First Out)[^4] | 先进先出(First In First Out)[^2] | | **插入/删除位置** | 仅在栈顶操作(入栈`push`,出栈`pop`)[^4] | 插入在队尾(入队`enqueue`),删除在队头(出队`dequeue`)[^3] | | **数据结构实现** | 数组或链表(数组更优,尾插尾删时间复杂度$O(1)$[^4]) | 循环顺序队列或链队列(避免假溢出问题)[^3] | | **典型操作** | 括号匹配、函数调用栈 | 任务调度、广度优先搜索(BFS)[^2] | --- ### 二、应用场景分析 #### **栈(LIFO)的典型应用** 1. **函数调用栈** 递归调用时,系统用栈保存函数返回地址和局部变量。例如斐波那契递归实现[^1]: ```c int Fbi(int i) { if(i < 2) return i == 0 ? 0 : 1; return Fbi(i-1) + Fbi(i-2); // 递归调用依赖栈结构 } ``` 2. **括号匹配检测** 通过压栈和弹栈操作验证括号嵌套合法性: ```python def is_valid(s): stack = [] mapping = {')':'(', ']':'[', '}':'{'} for char in s: if char in mapping: top = stack.pop() if stack else '#' if mapping[char] != top: return False else: stack.append(char) return not stack ``` 3. **撤销操作(Undo)** 文本编辑器中,用户操作按LIFO顺序存储,撤销时弹出最近操作。 #### **队列(FIFO)的典型应用** 1. **广度优先搜索(BFS)** 图的遍历中,队列按层级保存待访问节点[^2]: ```cpp void BFS(Graph G, int v) { queue<int> q; q.push(v); visited[v] = true; while (!q.empty()) { int u = q.front(); q.pop(); for (auto w : G.adj[u]) { if (!visited[w]) { visited[w] = true; q.push(w); } } } } ``` 2. **任务调度** 操作系统使用队列管理进程调度,保证公平性(如打印任务队列)。 3. **消息队列** 异步通信中,消息按接收顺序处理(如RabbitMQ、Kafka)。 --- ### 三、代码实现对比 #### **栈的LIFO操作(C语言动态栈实现)[^4]** ```c typedef struct Stack { int* data; int top; int capacity; } Stack; void StackPush(Stack* ps, int val) { if (ps->top == ps->capacity) { // 动态扩容 ps->capacity *= 2; ps->data = realloc(ps->data, ps->capacity * sizeof(int)); } ps->data[ps->top++] = val; // 入栈操作 } int StackPop(Stack* ps) { assert(ps->top > 0); return ps->data[--ps->top]; // 出栈操作(LIFO) } ``` #### **队列的FIFO操作(Python实现)[^5]** ```python class MyQueue: def __init__(self): self.queue = [] def enqueue(self, num): self.queue.append(num) # 队尾插入 def dequeue(self): return self.queue.pop(0) if self.queue else None # 队头删除(FIFO) ``` --- ### 四、核心总结 1. **结构差异**:栈的LIFO适合回溯操作,队列的FIFO保证顺序公平性[^4][^2]。 2. **性能考量**:栈的尾操作效率高($O(1)$),队列需维护头尾指针。 3. **选择依据**: - 需要“最近相关性”时选栈(如递归、撤销); - 需要“历史顺序性”时选队列(如任务调度、BFS)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值