理论基础
栈 --后进先出的线性表
栈顶元素:
唯一可访问的元素
入栈顺序和出栈顺序正好相反
栈的储存形式
数组实现: 顺序表的简化版
链表实现:用单链表方式存储,其中指针的方向是从栈顶向下链接
用途:
栈常用来处理递归结果的数据
- 深度优先搜索
- 表达式求值
- 操作系统函数调用的管理
队列:
先进先出的线性表 (两次后进先出等于一次先进先出)
优先队列(最大/最小堆值)
头尾元素:
队头: 删除操作
对尾: 插入操作
队列操作:
入队列: enQueue
出队列: deQueue
取队首元素: getFront
判断队列是否为空: isEmpty
队列的储存方式:
数组实现: 环形数组
链表实现: 用单链表方式存储, 队列中每个元素对于链表中的每一个节点
溢出处理
上溢(Overflow)
下溢(Underflow)
用途:
- 广度优先搜索
- 消息缓冲器
- 计算机的硬件设备之间的通信缓冲
- 操作系统的资源管理(优先管理)
题目:
1. 实现特殊顺序读取:
- "倾倒"实现特殊顺序
- 升序,将序排列
- 力扣高频题: 20,42, 173, 224,84, 239, 316, 402
用栈实现队列 Leetcode_232 难度:简单
这题基本没难点, peek的定义是
Stack. peek() method in Java is used to retrieve or fetch the first element of the Stack or the element present at the top of the Stack.
而在c++里,根据cpp reference,似乎只有用top来取第一个元素,用pop来去除第一个元素
class MyQueue {
public:
stack<int> src_stk;
/** Initialize your data structure here. */
MyQueue() {
//stack<int> src_stk;
}
/** Push element x to the back of queue. */
void push(int x) {
src_stk.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
stack<int> tmp_stk;
while(!src_stk.empty())
{
int head = src_stk.top();
src_stk.pop();
tmp_stk.push(head);
}
int rtn_val = tmp_stk.top();
tmp_stk.pop();
while(!tmp_stk.empty())
{
int head = tmp_stk.top();
tmp_stk.pop();
src_stk.push(head);
}
return rtn_val;
}
/** Get the front element. */
int peek() {
stack<int> tmp_stk;
while(!src_stk.empty())
{
int head = src_stk.top();
src_stk.pop();
tmp_stk.push(head);
}
int rtn_val = tmp_stk.top();
while(!tmp_stk.empty())
{
int head = tmp_stk.top();
tmp_stk.pop();
src_stk.push(head);
}
return rtn_val;
}
/** Returns whether the queue is empty. */
bool empty() {
return (src_stk.empty());
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
2. 次序问题:
- 元素具有优先级
- 动态排序
- 力扣高频题: 215, 347, 252, 253, 23
本题比较直接或者naive的方法是: 对于每个链表的头部进行遍历和更新,保证始终把所有链表中最小的第一个元素加入新的链表中, 然后, 对于该链表头进行更新.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<ListNode*> cur_list;
// for(int i=0;i<lists.size();i++)
// {
// cur_list.push_back(lists[i]);
// }
//get the smallest node
int cur_idx=-1;
bool is_empty=true;
ListNode* pre_node = new ListNode;
ListNode* cur_node = pre_node;
int min_val = 10000;
while(1&&lists.size())
{
for(int i=0;i<lists.size();i++)
{
if(lists[i])
{
is_empty= false;
if(lists[i]->val<min_val)
{
min_val= lists[i]->val;
cur_idx = i;
//cout<<"idx "<<i<<endl;
}
}
if (i==lists.size()-1)
{
if(is_empty)
{
return pre_node->next;
//break;
}
else
{
ListNode* tmp_node= lists[cur_idx];
lists[cur_idx]=lists[cur_idx]->next;
cur_node->next = tmp_node;
cur_node = cur_node->next;
is_empty=true;
min_val =10000;
}
}
}
}
return pre_node->next;
}
};
更高级的方法是使用mergesort,leetcode上有对应题解.
滑动窗口最大值 Leetcode_239
这题应用到了Priority queue这一数据结构.它的使用可以大大简化做题难度
深度优先和广度优先算法
- 深度优先: 栈
- 广度优先: 队列
- 力扣高频题: 102
栈和队列的C++标准库实现