一、栈的相关概念
栈的定义
栈(Stack)是限定仅在表尾进行插入或删除操作的线性表。因此,对于栈来说,表尾端有着特殊含义,称为栈顶(top),相应地,表头段称为栈底(bottom)。不含元素的空表叫做空栈。
栈顶:线性表允许进行插入删除的那一端。
栈底:固定的,不允许进行插入和删除的一端。
空栈:不含任何元素的空表。
栈的操作特性:后进先出(Last In First Out)
假设某个栈S=(a1,a2,…,an),则称a1为栈底元素,an为栈顶元素。
栈中的元素按照a1,a2,…,an的顺序进栈,退栈的第一个元素应为栈顶元素。
换句话说,栈的修改是按后进先出的原则进行的,可以简称为LIFO;
栈的示意图:
栈的数学特性
n个不同的元素进栈,出栈元素不同的排列的个数为 1 n + 1 C 2 n n \frac{1}{n+1}C_{2n}^n n+11C2nn。该公式称为卡特兰数。
二、栈的基本操作
InitStack(*S)
:构造一个空栈SStackEmpty(S)
:若栈S为空栈,则返回TRUE,否则为FALSE。Push(*S,e)
:插入元素e为新的栈顶元素Pop(*S,*e)
:删除S的栈顶元素,并用e返回其值。StackLength(S)
:返回栈S的元素个数,即栈的长度。GetTop(S,*e)
:用e返回栈顶元素StackTraverse(S)
:从栈底到栈顶依次遍历栈S,打印其中的元素DestoryStack(*S)
:销毁栈ClearStack(*S)
:栈S清为空栈
接下来便分为栈的顺序存储和链式存储来实现这些操作。
三、顺序栈
采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素。
3.1 顺序栈的定义
顺序栈实际上也就是操作受限的顺序表,我们这里采用动态分配的方式。关于顺序表的内容,可以查看顺序表(线性表的顺序存储)—C语言版
仍旧使用该例子,我们要如何存储该表呢?
id | name | description |
---|---|---|
1 | 史强 | 最强辅助 |
2 | 章北海 | 我不需要钢印,我是自己思想的主人 |
3 | 罗辑 | 人类不感谢罗辑 |
4 | 维德 | 失去人性,失去很多。失去兽性,失去一切 |
步骤一:声明数据元素类型
首先我们使用结构体声明数据元素(对应表中的一行数据)的类型
typedef struct{
int id;//对应表中的id
char name[100];//对应表中的姓名
char description[200];//对应表中的描述
}SElemType;//此处的SElemType是个类型名
步骤二:顺序栈的定义
#define InitSize 10;//栈的初始长度
#define ListIncrement 2;//扩容时的分配增量
typedef struct{
SElemType *base;//栈的基地址,指示动态分配的数组的指针
SElemType *top;//栈顶指针
int MaxSize;//当前栈的最大存储长度
}SqStack;//顺序栈的类型定义
3.2 顺序栈的操作
- 栈结构不存在:
base==NULL;
- 栈为空:
base==top
- 入栈:
*top=e; top++;
先赋值再加一 - 出栈:
top--; *e=*top;
先减一再返回
InitStack(*S)
:构造一个空栈S
/*初始化*/
int InitStack(SqStack *S){
S->base=(SElemType *)malloc(sizeof(SElemType)*InitSize); //给栈分配存储空间
if(!S->base) return FALSE; //分配失败返回FALSE
S