1 栈和队列区别
栈:先进后出
队列:先进先出
2 栈和队列的实现
栈:可以采用数组或链表实现。如果采用数组实现可将数组尾部作为栈顶,保存数组尾部元素下标进行压栈和出栈操作;如果采用链表实现可采用头插法,保存头指针进行压栈和出栈操作;
typedef int STDataType;
typedef struct Stack
{
STDataType* array;
int capacity;
int top; // 栈顶位置的下一个位置的下标
}Stack;
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestory(Stack* ps);
//压栈
void StackPush(Stack* ps, STDataType x);
//出栈
void StackPop(Stack* ps);
//获取栈顶数据
STDataType StackTop(Stack* ps);
//栈的大小
int StackSize(Stack* ps);
//栈是否为空
bool StackEmpty(Stack* ps);
队列:采用链表实现。采用尾插法,并保存尾指针,入队插入链表尾部,出队从链表头进行出队;
//数据类型
typedef int QDataType;
//队列结点
typedef struct QueueNode
{
QDataType val;
struct QueueNode* next;
}QueueNode;
//队列结构体
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
int size;
}Queue;
//初始化队列
void QueueInit(Queue* pq);
//销毁队列
void QueueDestory(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//队列是否为空
bool QueueEmpty(Queue* pq);
//队列的大小
int QueueSize(Queue* pq);
3 栈和队列的应用场景
栈和队列是两种重要的数据结构,它们在计算机科学和软件工程中有着广泛的应用。栈是一种后进先出(LIFO)的数据结构,而队列是一种先进先出(FIFO)的数据结构。它们各自具有独特的特性和应用场景,下面将详细介绍这些应用场景。
3.1 栈的应用场景
- 撤销操作:在许多软件应用程序中,每当用户执行一个操作(如添加、删除或修改),相关信息会被推入栈中。当用户选择撤销时,程序将从栈中弹出最近的操作并还原到上一个状态。12
- 后退/前进功能:网页浏览器中的后退和前进按钮使用栈来实现。每次访问一个新页面时,页面信息被推入栈中。点击后退按钮时,程序从栈中弹出最近的访问页面,显示上一个页面。12
- 递归算法:递归算法也使用栈来实现。每次递归调用时,函数的当前状态(包括参数和局部变量)被推入栈中。当递归函数结束时,栈会弹出并还原上一个状态。
- 表达式求值:在算术表达式的求值中,栈用于处理运算符的优先级和处理括号匹配等问题。34
- 括号匹配:在编译器的语法分析阶段,栈用于检查源代码中的括号是否正确匹配。
3.2 队列的应用场景
- 网络流量管理:在计算机网络中,路由器使用队列来管理数据包的到达和发送。数据包按照先到先服务的原则排队,从队列中出队发送到目的地。1
- 广度优先搜索算法:在图论和算法领域,广度优先搜索算法使用队列来实现。该算法通过逐层遍历图中的节点,并使用队列来存储待访问的节点。
- 批处理任务处理:在系统设计中,队列经常用于处理批处理任务。任务被排队进入队列,通过一个或多个处理器逐个处理。
- 网络请求队列:在高并发的网络环境中,服务器使用队列来控制请求的处理顺序,避免服务器因请求过多而崩溃。3
- 消息队列:消息队列是一种常见的异步通信机制,常用于解耦和提高系统的可伸缩性。发送者将消息放入队列中,接收者从队列中获取消息并进行处理。
通过上述应用场景的介绍,可以看出栈和队列在计算机科学和软件工程中的重要性。它们不仅在基础算法和数据结构中扮演着关键角色,而且在实现各种功能和应用时提供了极大的便利。