栈的数学性质:
n 个不同的元素进栈,出栈元素不同排列的个数为
1 n + 1 C 2 n n \frac{1}{n+1}C_{2n}^{n} n+11C2nn
上述公式称为 卡特兰数
栈的常考题型:
有时初始时将 S.top 定义为0,即规定top指向栈顶元素的下一个存储单元。
另一种方式(初始时 S.top = 0):
两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延申
回顾链表
链栈的定义:
带头结点:
// 链表结点定义
typedef struct LinkNode{
int data;
struct LinkNode *next;
} LNode, *LiStack;
// 带头结点的初始化
bool InitStack(LiStack &L){
L = (LNode*)malloc(sizeof(LNode));
if(L == NULL)
return false;
L -> next = NULL;
return true;
}
// 进栈
bool InsertNextNode(LiStack L, int e){
if(L == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s == NULL)
return false;
s -> data = e;
s -> next = L -> next;
L -> next = s;
return true;
}
// 出栈
bool DeleteNextNode(LiStack L){
if(L -> next == NULL)
return false;
LNode *q = L -> next;
L -> next = q -> next;
free(q);
return true;
}
// 获取栈顶元素
bool GetTop(LiStack L, int &e){
if(L -> next == NULL)
return false;
e = L -> next -> data;
return true;
}
// 判断空
bool isEmpty(LiStack L){
if(L -> next == NULL)
return true;
return false;
}
不带头结点:
// 链表结点定义
typedef struct LinkNode{
int data;
struct LinkNode *next;
} LNode, *LiStack;
// 不带头结点的初始化
bool InitStack(LiStack &L){
L = NULL;
return true;
}
// 进栈
bool InsertNextNode(LiStack L, int e){
if(L == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s == NULL)
return false;
s = L -> next;
}
// 出栈
bool DeleteNextNode(LiStack L){
if(L -> next == NULL)
return false;
LNode *q = L -> next;
L -> next = q -> next;
free(q);
return true;
}
// 获取栈顶元素
bool GetTop(LiStack L, int &e){
if(L -> next == NULL)
return false;
e = L -> next -> data;
return true;
}
// 判断空
bool isEmpty(LiStack L){
if(L == NULL)
return true;
return false;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mA6RMDGV-1661179873646)(C:/Users/G/AppData/Roaming/Typora/typora-user-images/image-20220822193852648.png)]
输入受限
输出受限:
例:
即:
如:
-扫到除号时,乘号弹出;由于此时无法确定右侧式子中是否有括号,此时栈中的减号不弹出
另一个带有括号的例子:
–
树的层次遍历(见树章节)
图的广度优先遍历(见图章节)
在操作系统中的应用
行优先存储:
列优先存储:
出题方法:
下三角:
上三角: