目录
栈
1.基本概念
2.提炼要点
3.概念选择题
4.栈的实现
栈初始化函数
入栈函数
出栈函数和栈顶函数
栈顶函数
栈销毁函数
栈
基本概念参见王爽老师的《汇编语言 第四版》第56和57页
节选一部分
1.基本概念
注意:这里提到的数据结构中的栈有别于操作系统的栈,后者是为函数开辟栈帧空间,局部变量存储等而服务的
2.提炼要点
1.定义:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作
2.进行数据插入和删除\操作的一端称为栈顶,另一端称为栈底
3.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
4.压栈(push):栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶;出栈(pop):栈的删除操作叫做出栈,出数据也在栈顶
★★5.两种顺序:一边入栈,一边出栈;先入栈后出栈(这里容易出概念选择题)
3.概念选择题
若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是( )
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1
答案:选C
4.栈的实现
可使用数组或链表
显然用数组更容易实现,数组具有在内存中连续存放的特点,缓存的命中率比链表高!
栈顶插入(STPush函数)
栈初始化函数
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc");
return;
}
ps->capacity = 4;
ps->top = 0;//top栈顶元素的下一个位置
}
一次性malloc开辟了16个字节(int*4),ps->a存储开辟空间的首地址,定义capacity=4确保之后判断push不越界
初始化时,栈中没有元素,因此ps->top=0;等待push
入栈函数
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
先判断是否越界,如果ps->top == ps->capacity,则开辟两倍的空间,将新开辟空间的指针tmp交给ps->a,ps->a[ps->top] = x;以数组的形式访问栈,ps->top++;移向下个要push的位置
出栈函数和栈顶函数
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));//确保不越界
ps->top--;
}
出栈直接改变栈指针top
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
如果assert断言通过,返回ps->a[ps->top - 1](指的是压入栈的最后一个元素,即栈顶元素(注意有-1))
while (!STEmpty(&st))
{
printf("%d ", STTop(&st));//必须先访问栈顶元素,严格执行后进先出
STPop(&st);
}
ps不为NULL时,返回 ps->top == 0;
则 while (!STEmpty(&st))变成 while (!(ps->top == 0))
注意执行的顺序:先打印栈顶元素,再将其出栈
栈顶函数
STDataType STTop(ST* ps)//访问栈顶元素
{
assert(ps);
assert(!STEmpty(ps));//确保不越界
return ps->a[ps->top - 1];
}
栈销毁函数
void STDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
free(ps->a);一次性销毁所有动态开辟的空间
将ps->a=NULL防止野指针,其余参数(top和capacity)置0恢复原样