栈结构简介
1.栈其实也是一种线性表,而线性表有两种结构,一种是物理上的线性,另一种是逻辑上的线性
2.准确的定义 : 栈是限定仅在表尾进行插入和删除操作的线性表
3.我们把语序删除和插入的一端称为栈顶,另一端称为栈底
4.栈又称为后进先出的线性表,简称LIFO结构(Last in First Out)
栈的相关基本操作
1.插入操作 :void push(type val);
2.删除操作 :void pop();
3.返回栈顶元素:type top();
4.判断是否为空:bool empty();
5.输出当前栈内元素的个数:int size();
下面是自己手动实现的一个模板类,包含了这些基本操作
template<class type>
class Stack {
private:
struct Stack_node{
type val;
Stack_node* next = NULL;
Stack_node* last = NULL;
};
int length;
Stack_node* top;//栈顶元素的指针
public:
Stack() {
length = 0;
Stack_node* head = new Stack_node;
top = head;
}//栈的初始化操作
void push(type val);//栈的压入操作
void pop();//栈的删除操作
type first();//返回栈顶元素
int size();//返回栈的长度
bool empty();//判断栈是否为空的操作
};
template<class type>
void Stack<type>::push(type val) {
Stack_node* node = new Stack_node;
node->val = val;
top->next = node;
node->last = top;
top = top->next;
length++;
}
template<class type>
void Stack<type>::pop() {
top = top->last;
delete top->next;
top->next = NULL;
length--;
}
template<class type>
type Stack<type>::first() {
return top->val;
}
template<class type>
int Stack<type>::size() {
return length;
}
template<class type>
bool Stack<type>::empty() {
if (length != 0)return true;
else return false;
}
显然这是使用了逻辑上的线性,也就是链式结构
当然每次都这样实现栈实在是太麻烦了,c++的STL中给出了模板,可供直接使用
需要包含头文件< stack >,下面给出相关的操作
stack<int>s;
for (int i = 0; i < 10; i++) {
s.push(i + 1);
}
cout << s.size() << endl;
while (!s.empty()) {
cout << s.top() << " ";
s.pop();
}
cout << endl << s.size();
运行结果 :
10
10 9 8 7 6 5 4 3 2 1
0
应用举例 :
1.寻找栈中的最小元素
题目描述 :
现在有一个栈,你现在不停的在里面插入和删除元素( int ),而且我时不时的会问你,栈中的最小元素是多少
输入方式 :
第一行一个整数n,表示接下来的操作数。
接下来n行,每行一个指令,可能的指令如下:
1 num :表示压入元素 num
2 :表示删除栈顶元素
3 :表示输出当前栈内的最小值
输出方式 :
对于每次询问最小值的操作,单独输出一行。
示例 :
输入 : 输出 :
17
1 20
3 20
1 10
3 10
1 15
1 17
3 10
2
2
1 9
1 11
3 9
2
3 9
2
2
3 20
1<= n <= 2*10^7
|num| <= 10^9
代码实现 :
由于数据较大,所以采用快速读写的方法
#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
namespace fast_IO {
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
return x * f;
}
inline void write(int x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
};
using namespace fast_IO;
//快速读写
int main() {
stack<int>Stack_Data;//数据栈
stack<int>Stack_Min;//较小值栈
int n, temp, str;
n = read();
for (int i = 0; i < n; i++) {
str = read();
switch (str){
case 1:
temp = read();
Stack_Data.push(temp);
if (Stack_Min.empty()) {
Stack_Min.push(temp);
}
else if (temp <= Stack_Min.top()) {
Stack_Min.push(temp);
}
//向Min栈push数据的两个条件
break;
case 2:
if (Stack_Data.top() == Stack_Min.top())Stack_Min.pop();
//当满足这个条件的时候才Stack_Min.pop()
Stack_Data.pop();
//当pop时,Data栈是必须pop
break;
case 3:
write(Stack_Min.top());
putchar('\n');
break;
}
}
return 0;
}
实现思路:
建立一个Stack_Data来保存输入的数据,一个Stack_Min来保存最小值。
当Stack_Min为空时向里面push数据,或者,当向Stack_Data里面push数据的时候,将这个数据与Min的栈顶进行比较,如果小于或者等于该栈顶,则push。这样就保证了,Min栈顶是整个数据的最小值,而且输出的复杂度是O(1)
2.验证表达式
题目背景:
验证表达式有两种方式 :
第一种 : 只考虑优先级,即大括号{}应在最外层,接着是中括号[],然后是小括号(),尖括号<>应在最内层。应当注意的是,同级括号可以同时出现。
第二种 : 不考虑括号之间的优先级,括号的个数是否左右匹配
应当注意的是:无论哪一种匹配方式,只有相同的括号才可以匹配
输入方式:
第一行一个数字n,表示接下来要验证的表达式的个数
接下来n行,一行一个字符串和一个数字
要注意的是
字符串中不包含空格,仅包含数字、大小写字母、加(+)减(-)乘(*)除(/)取模(%)乘方(^)和四种括号;
数字表示检验标准:
1 表示你需要按照第一种标准检验;
2 表示你需要按照第二种标准检验;
输出方式:
输入: 输出:
6
{5+{4+{3*(2-(1*<<6-4>+<3-2>>))}}-9} 1 Yes
{5+{4+{3*(2-(1*<<6-4>+(3-2)>))}}-9} 1 No
{5+{4+{3*(2-(1*<<6-4>+(3-2)>))}}-9} 2 Yes
{5+{4+{3*(2-(1*<<6-4>+(3-2)>))}-9} 2 No
[1+(1+2]+3) 2 No
<([{[]}])> 2 Yes
代码实现:
#include <stack>
#include <string>
#include <iostream>
using namespace std;
char h[128]; //全局变量默认初始化为0
stack<int> s; //定义一个栈用来验证表达式
bool check(string str, int opt) {
while(!s.empty()) s.pop();//因为只有一个栈,所以每次用的时候都要清空这个栈
for (int k = 0; k < str.length(); ++k) {
int t = h[str[k]];
//t > 0 表示是左括号
if(t > 0) {
//第一种方式验证表达式,满足该条件就判断为No
if(opt == 1 && !s.empty() && t > s.top()) return false;
s.push(t);
}
if(t < 0) {
//右括号进入时没有左括号,就No
if(s.empty()) return false;
//括号不匹配就No
if(t + s.top()) return false;
//否则栈顶元素,即匹配的左括号弹出
s.pop();
}
}
//匹配结束后,如果是空栈,表明括号全部匹配
if(s.empty()) return true;
return false;
}
int main() {
h['<'] = 1; h['>'] = -1;
h['('] = 2; h[')'] = -2;
h['['] = 3; h[']'] = -3;
h['{'] = 4; h['}'] = -4;
//将这些要匹配的括号一一赋值
int n; cin >> n;
while(n--) {
string str; int opt;
cin >> str >> opt;
cout << (check(str, opt) ? "Yes" : "No") << endl;
}
return 0;
}
补充:
int a, b;
a = 1; b = -1;
if(a + b) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
输出结果: No
原因:if(a + b)表示如果 a + b != 0 的话