一。栈
1.概念:栈是限定在一端进行插入或删除操作的线性表。因此,对栈进行插入删除操作的这一端称为栈顶(top),另一端称为栈底。不含元素的栈称为空栈。栈中的元素遵循**后进先出的特性。**插入数据称为入栈/进栈,删除数据称为出栈
2.入栈和出栈顺序:顺序不一定,可以有很多出栈顺序,如下图:

看一道例题:

求以元素d开头的序列个数,就是出栈的第一个元素是d,那么abcd就要先入栈,然后d出栈,至于abce的出栈和e的入栈,分类讨论即可,如下图:

3.静态顺序栈和动态顺序栈结构
栈的顺序存储实现可以用静态数组,称为静态顺序栈。使用堆上动态申请数组实现,称为动态顺序栈。重点是动态顺序栈
(1)静态顺序栈的定义:

(2)动态顺序栈的定义:

(3)动态顺序栈的实现
注意:栈在初始化时,top=-1指向的是栈顶元素,入栈时要先++top,再把入栈元素放到top位置。top=0时指向的是栈顶元素的下一个位置,入栈时要先把入栈元素放到top的位置,再++top。
核心接口函数的实现:







补充:链式栈的实现(没有哨兵位)
(1)定义

(2)初始化和销毁

(3)元素入栈

关键点说明:

元素入栈就是在链式栈中头插元素。首先要修改newNode的指向,它要指向下一个节点,栈顶指针就是指向写一个元素,所以就要使newNode->next = s->topHead。然后新的节点称为栈顶指针,即s->topHead = newNode。
(4)元素出栈

关键点说明:元素出栈就是要修改元素之间的链接关系,也就是使头节点指向第二个元素,同时记录栈顶元素的地址(因为要确保链式存储结构不能断),即 LSNode* delNode = s->topHead 和 s->topHead = delNode->next。
(5)获取栈顶元素,栈中有效元素个数,检测栈是否为空,如果是空返回真,否则返回假

例题:给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路:如果遇到左括号,就入栈。如果是右括号,就依据有效字符串的规则与栈中元素进行比较

特殊情况1:如果给的样例全是左括号,例如"(((((",那么开辟的栈就是空栈,后续进行top访问时就会出错
特殊情况2:如果样例是"))))))))",会错误的判断为正确
反思:
(1)写代码要有边界思维,时刻注意特殊情况
(2)动态开辟的栈,要记得销毁
(3)知识点选取:栈的核心特性->后进先出,这是选用栈解决本题根本原因:最近打开的括号,必须最先闭合。例: ( ) ,最后出现的 ,最先遇到闭合 ,完美契合栈"后进先出"。结论:遇到"最近匹配"类问题,优先想到栈。