1.栈的定义
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
我们吧允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。又称后进先出(Last In First Out)的线性表,简称LIFO结构。
特点:后进先出。
栈的插入操作:称为进栈、入栈。
栈的删除操作:称为出栈。
入栈、出栈示意图:
2.栈的应用
栈适用于数据存储以后以相反的顺序来来检索的情况。
示例:匹配分隔符,比如圆括号“(”和“)”,方括号“[”和“]”,花括号“{”和“}”
(1)、算法
a.从程序中读取一个字符,如果该字符为左分隔符,则将其入栈。
如果该字符为右分隔符,则与栈中弹出的分隔符相比较。
b.如果两者匹配,则继续进行处理。
c.若不匹配,则中断处理,并提示出错。
d.到达程序末尾并且栈为空的话,就完成了对程序的处理。
delimiterMathching(file)
从file中读取字符ch;
while file 未结束:
if ch in "(","[","{"
将ch入栈;
else if ch in ")","[","{"
if ch与弹出的分隔符不匹配
出错;
else if ch is '/'
读下一个字符;
if 这个字符是‘*’
跳过“*/”之前所有字符,如果直到到达文件末尾仍没有遇到“*/”,就报告错误
else ch = 读入是字符;
continue; //回到循环的开始
//else 忽略其他的字符
从file中读入下一个字符ch;
if 栈为空
匹配成功
else
出错;
实际应用:
leetcode:
答案:
当长度为奇数时,直接返回false。
当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合。此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串 ss 无效,返回 \text{False}False。为了快速判断括号的类型,我们可以使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/valid-parentheses/solution/you-xiao-de-gua-hao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public:
bool isValid(string s) {
int n = s.size();
if (n % 2 == 1) {
return false;
}
unordered_map<char, char> pairs = {
{')', '('},
{']', '['},
{'}', '{'}
};
stack<char> stk;
for (char ch: s) {
if (pairs.count(ch)) {
if (stk.empty() || stk.top() != pairs[ch]) {
return false;
}
stk.pop();
}
else {
stk.push(ch);
}
}
return stk.empty();
}
3.栈的抽象数据类型
基本操作:
top():返回一个栈顶元素的引用,类型为T&。如果栈为空,返回值未定义。
push(const T& obj):可以将对象副本压入栈顶。
pop():删除栈顶元素,并返回其值。
size():返回栈中元素的个数。
empty():在栈中没有元素的情况下返回true。
4.栈的顺序存储结构及实现
普通栈:
进栈操作push,代码如下:
//插入元素e为新的栈顶元素
Status Push(SqStack * s, SElemType e)
{
if(s->top == MAXSIZE-1) //栈满
{
return ERROR;
}
s->top++; //栈顶指针增加一
s->data(s->top) = e; //将新插入的元素赋值给栈顶空间
return OK;
}
出栈操作pop,代码如下:
//若栈不空,则删除S的栈顶圆度,用e返回其值,并返回OK;否则返回ERROR
Status Pop(SqStack * s, SElemType * e)
{
if(s->top == 1)
{
return ERROR;
}
*e = s->data[s->top]; //将要删除的栈顶元素赋给e
s->top--; // 栈顶指针减一
return OK;
}