用实例讲解栈和队列(C++)
2016-04-23 11:00
441 查看
一、栈和队列
1、实现一个新型的栈结构,具有pop、push、top、size和getMin操作。
解法:用两个普通栈实现。
class Solution {
public:
stack<int> data,minData;
void push(int value) {
data.push(value);
if (minData.empty())
minData.push(value);
if (value < minData.top())
minData.push(value);
else
minData.push(minData.top());
}
void pop() {
data.pop();
minData.pop();
}
int top() {
return data.top();
}
int min() {
return minData.top();
}
};
2、两个栈实现队列
3、实现栈的逆序
解法:在限定只能用递归和栈本身,而不能再申请别的数据结构的情况下。主要有两个递归过程。
①、getBase递归地获取栈底数据,并将栈底数据从栈中移除,栈中其他数据不变。
②、reverse递归地将每一次获得的栈底数据重新入栈,从而实现逆序。
4、双栈排序
解法:在最多只能再申请一个栈的情况下实现对栈内数据的排序。类似于插入排序,sort栈中存放已排好序的序列,将init栈的栈顶元素压入sort栈时要判断应该压入的位置,所以每次都得将init栈顶元素一一地与sort栈的栈顶元素比较,以找到其应该插入的位置。
class TwoStacks {
public:
void stackSort(vector<int> &init,vector<int> &sort) {
int temp;
sort.push_back(init.back());
init.pop_back();
while (!init.empty()) {
temp = init.back();
init.pop_back();
if (temp <= sort.back()) {
sort.push_back(temp);
}
else {
do {
init.push_back(sort.back());
sort.pop_back();
}while (!sort.empty() && temp > sort.back());
sort.push_back(temp);
}
}
return;
}
vector<int> twoStacksSort(vector<int> numbers) {
int n = numbers.size();
if (n < 2)
return numbers;
vector<int> sortNumbers;
stackSort(numbers,sortNumbers);
return sortNumbers;
}
};
5、滑动窗口问题
问题描述:有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
最优解法:用双端队列实现。队头保存遍历过的元素中最大元素的下标。
①每遍历一个新元素就将该元素和队尾对应的元素比较,小于则将其下标从队尾入队,大于则将队尾元素出队,继续与新的队尾对应元素比较,直到遇到比该元素大的队尾对应元素或者直到队空,然后将该元素下标从队尾入队。
②找到当前元素下标正确的入队位置并入队后,再判断当前队头元素是否处在当前窗口的范围内,是则记录队头对应元素,否则将队头出队,记录新的队头对应元素。
class SlideWindow {
public:
vector<int> slide(vector<int> arr, int n, int w) {
deque<int> index;
vector<int> winMax;
for (int i = 0;i < n;i++) {
if (!index.empty()) {
if (arr[i] >= arr[index.back()]) {
do {
index.pop_back();
}while (!index.empty() && arr[i] >= arr[index.back()]);
}
}
index.push_back(i);
if (index.back() >= w-1) {
if (index.back() - index.front() >= w) {
index.pop_front();
}
winMax.push_back(arr[index.front()]);
}
}
return winMax;
}
};
6、对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree。
问题描述:MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。
解法:对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。问题的关键在于求出每个元素对应的左边最大值和右边最大值。用栈可以实现。
class MaxTree {
public:
vector<int> findMax(vector<int> &A,int n,char dir) {
stack<int> fMax;
vector<int> max;
int k = (dir == 'l')?0:n-1;
for (;k < n && k >=0;) {
if (!fMax.empty()) {
if (A[k] >= A[fMax.top()]) {
do {
fMax.pop();
}while (!fMax.empty() && A[k] >= A[fMax.top()]);
}
}
max.push_back(fMax.empty()?-1:fMax.top());
fMax.push(k);
k = (dir == 'l')?k+1:k-1;
}
return max;
}
vector<int> buildMaxTree(vector<int> A, int n) {
vector<int> father;
if (n < 1)
return father;
vector<int> left = findMax(A,n,'l');
vector<int> right = findMax(A,n,'r');
for (int i = 0;i < n;i++) {
int j = n-i-1;
if (left[i] == -1 && right[j] == -1)
father.push_back(-1);
else if (left[i] != -1 && right[j] != -1)
father.push_back(A[left[i]] < A[right[j]]?left[i]:right[j]);
else
father.push_back(left[i] != -1?left[i]:right[j]);
}
return father;
}
};
推荐博文:
二叉树相关练习题(C++)
与字符串有关的一些典型问题的C++解法
一些可以用动态规划(DP)算法解决的问题(C++)
排列组合相关笔试面试题(C++)
与概率相关的算法题C++解法(附证明过程)
二分查找的巧妙运用(C++)
位运算在算法题中的使用(C++)
链表相关练习题(C++)
一些智力题的C++解法
1、实现一个新型的栈结构,具有pop、push、top、size和getMin操作。
解法:用两个普通栈实现。
class Solution {
public:
stack<int> data,minData;
void push(int value) {
data.push(value);
if (minData.empty())
minData.push(value);
if (value < minData.top())
minData.push(value);
else
minData.push(minData.top());
}
void pop() {
data.pop();
minData.pop();
}
int top() {
return data.top();
}
int min() {
return minData.top();
}
};
2、两个栈实现队列
class
TwoStack {
public
:
stack<
int
> pushStack,popStack;
vector<
int
> twoStack(vector<
int
> ope,
int
n) {
vector<
int
> q;
for
(
int
i =
0
;i < n;i++) {
if
(ope[i] >
0
) {
while
(!popStack.empty()) {
pushStack.push(popStack.top());
popStack.pop();
}
pushStack.push(ope[i]);
}
if
(ope[i] ==
0
) {
while
(!pushStack.empty()) {
popStack.push(pushStack.top());
pushStack.pop();
}
q.push_back(popStack.top());
popStack.pop();
}
}
return
q;
}
};
3、实现栈的逆序
解法:在限定只能用递归和栈本身,而不能再申请别的数据结构的情况下。主要有两个递归过程。
①、getBase递归地获取栈底数据,并将栈底数据从栈中移除,栈中其他数据不变。
②、reverse递归地将每一次获得的栈底数据重新入栈,从而实现逆序。
class
StackReverse {
public
:
int
getBase(stack<
int
> &s) {
int
base,top = s.top();
s.pop();
if
(!s.empty()) {
base = getBase(s);
s.push(top);
}
else
return
top;
return
base;
}
void
reverse(stack<
int
> &s) {
int
base = getBase(s);
if
(!s.empty())
reverse(s);
s.push(base);
return
;
}
vector<
int
> reverseStack(vector<
int
> A,
int
n) {
if
(A.empty() || n ==
1
)
return
A;
stack<
int
> s;
vector<
int
> reverseA;
for
(
int
i =n-
1
;i >=
0
;i--)
s.push(A[i]);
reverse(s);
do
{
reverseA.push_back(s.top());
s.pop();
}
while
(!s.empty());
return
reverseA;
}
};
4、双栈排序
解法:在最多只能再申请一个栈的情况下实现对栈内数据的排序。类似于插入排序,sort栈中存放已排好序的序列,将init栈的栈顶元素压入sort栈时要判断应该压入的位置,所以每次都得将init栈顶元素一一地与sort栈的栈顶元素比较,以找到其应该插入的位置。
class TwoStacks {
public:
void stackSort(vector<int> &init,vector<int> &sort) {
int temp;
sort.push_back(init.back());
init.pop_back();
while (!init.empty()) {
temp = init.back();
init.pop_back();
if (temp <= sort.back()) {
sort.push_back(temp);
}
else {
do {
init.push_back(sort.back());
sort.pop_back();
}while (!sort.empty() && temp > sort.back());
sort.push_back(temp);
}
}
return;
}
vector<int> twoStacksSort(vector<int> numbers) {
int n = numbers.size();
if (n < 2)
return numbers;
vector<int> sortNumbers;
stackSort(numbers,sortNumbers);
return sortNumbers;
}
};
5、滑动窗口问题
问题描述:有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
最优解法:用双端队列实现。队头保存遍历过的元素中最大元素的下标。
①每遍历一个新元素就将该元素和队尾对应的元素比较,小于则将其下标从队尾入队,大于则将队尾元素出队,继续与新的队尾对应元素比较,直到遇到比该元素大的队尾对应元素或者直到队空,然后将该元素下标从队尾入队。
②找到当前元素下标正确的入队位置并入队后,再判断当前队头元素是否处在当前窗口的范围内,是则记录队头对应元素,否则将队头出队,记录新的队头对应元素。
class SlideWindow {
public:
vector<int> slide(vector<int> arr, int n, int w) {
deque<int> index;
vector<int> winMax;
for (int i = 0;i < n;i++) {
if (!index.empty()) {
if (arr[i] >= arr[index.back()]) {
do {
index.pop_back();
}while (!index.empty() && arr[i] >= arr[index.back()]);
}
}
index.push_back(i);
if (index.back() >= w-1) {
if (index.back() - index.front() >= w) {
index.pop_front();
}
winMax.push_back(arr[index.front()]);
}
}
return winMax;
}
};
6、对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree。
问题描述:MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。
解法:对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。问题的关键在于求出每个元素对应的左边最大值和右边最大值。用栈可以实现。
class MaxTree {
public:
vector<int> findMax(vector<int> &A,int n,char dir) {
stack<int> fMax;
vector<int> max;
int k = (dir == 'l')?0:n-1;
for (;k < n && k >=0;) {
if (!fMax.empty()) {
if (A[k] >= A[fMax.top()]) {
do {
fMax.pop();
}while (!fMax.empty() && A[k] >= A[fMax.top()]);
}
}
max.push_back(fMax.empty()?-1:fMax.top());
fMax.push(k);
k = (dir == 'l')?k+1:k-1;
}
return max;
}
vector<int> buildMaxTree(vector<int> A, int n) {
vector<int> father;
if (n < 1)
return father;
vector<int> left = findMax(A,n,'l');
vector<int> right = findMax(A,n,'r');
for (int i = 0;i < n;i++) {
int j = n-i-1;
if (left[i] == -1 && right[j] == -1)
father.push_back(-1);
else if (left[i] != -1 && right[j] != -1)
father.push_back(A[left[i]] < A[right[j]]?left[i]:right[j]);
else
father.push_back(left[i] != -1?left[i]:right[j]);
}
return father;
}
};
推荐博文:
二叉树相关练习题(C++)
经典排序算法的C++实现
与字符串有关的一些典型问题的C++解法
一些可以用动态规划(DP)算法解决的问题(C++)
排列组合相关笔试面试题(C++)
与概率相关的算法题C++解法(附证明过程)
二分查找的巧妙运用(C++)
位运算在算法题中的使用(C++)
链表相关练习题(C++)
一些智力题的C++解法
相关文章推荐
- c语言:输入一行字符,统计其中的单词个数,单词之间用空格分开
- Leetcode 9. Palindrome Number
- C++中vector内存泄露问题
- C语言中的隐式转换
- C语言中不同类型的指针互相转换的注意点
- c++实现二叉树(递归)
- c++ 读书目录
- C语言基础及数据类型
- c语言中,scanf里面要是数组要不要加&?
- C++ 复杂链表的复制
- C# 调用C++工程生成的DLL
- 很好的c++和Python混合编程文章
- C++ 线程操作
- 使用C/C++扩展Python
- 设计模式 - 观察者模式(Observe pattern)C++实现
- c++中级 STL基础学习(二)
- 【UNREAL ENGINE 游戏开发】开篇之UE4的BLUEPRINT(蓝图)与C++(新童鞋必看)
- 【UNREAL ENGINE 游戏开发】开篇之UE4的BLUEPRINT(蓝图)与C++(新童鞋必看)
- C++进阶 面向对象基础(三)
- c++作业4