赞
踩
目录
一. 栈的概念
栈(Stack)是一种重要的抽象数据类型(ADT),也是一种特殊的顺序表,用于存储有序的元素集合。它的最大特点是后进先出(Last In First Out, LIFO)。这意味着在这个数据结构中,最后添加的元素将是第一个被移除的。
栈的原型:其中进行数据插入的和删除操作的一端称为栈顶,另一端称为栈底。
栈的原则:栈中的数据元素遵守 后进先出(LIFO)的原则
栈的两个典型操作:
压栈:栈的插入操作叫做 进栈 / 压栈 / 入栈 (入数据在栈顶)
出栈:栈的删除操作叫做出栈。(出数据也在栈顶)
二. 栈的结构
三. 栈的实现
针对栈的实现,我们可以使用之前学习过的链表 、顺序表都可以实现栈,但是我们需要考虑的什到底要用哪种方式实现栈呢?
优点:
缺点:
优点:
缺点:
std::vector
或 Java 的 ArrayList
)来解决这个问题,但这可能导致复杂的扩容操作和潜在的性能损耗。总的来说,没有绝对的“更好”,只有更适合特定需求的实现。例如,如果你预期栈会频繁变化大小,且不太关心随机访问性能,链表可能是一个好的选择。相反,如果你需要高性能和最优的空间利用,且栈的大小相对稳定,使用数组实现的顺序表可能更合适。
需要用结构体创建一个栈,这个结构体需要包括栈的基本内容(栈,栈顶,栈的容量)。
- typedef int STDataType;
- typedef struct Stack
- {
- STDataType* a; // 指向动态数组的指针,用于存储栈中的元素
- int top; // 栈顶的索引,指向栈顶元素
- int capacity; // 栈的容量,表示栈数组可以容纳的最大元素数量
- } Stack;
主要是给 栈 一个地址空间,将栈中的数据数据全部清空,与便于后续的操作方便。
- void StackInit(Stack* ps)
- {
- assert(ps);
- ps->a = NULL;
- ps->capacity = 0;
- // 这里需要注意的是当 top=0 时指向的是栈顶元素的下一个位置
- // top=-1 时指向的是栈顶元素
- // 这里也可以理解为顺序表中 size 有效数据的意思
- ps->top = 0;
- }
栈的销毁,需要将动态数组的头指针 free 掉,结构体其他元素置0.
- void StackDestroy(Stack* ps)
- {
- assert(ps); // 确保传入的栈指针不为空,防止未定义行为
- free(ps->a); // 释放栈使用的动态数组内存
- ps->a = NULL; // 将指向动态数组的指针设为NULL,避免悬挂指针(dangling pointer)
- ps->top = 0; // 将栈顶索引重置为0
- ps->capacity = 0; // 将栈的容量设置为0
-
- // 注意:此处没有释放栈结构本身的内存,仅释放了其内部的动态数组
- }
需要判断 栈的容量是否已满,满了就取扩容,没满,则向栈顶插入数据即可
- void STPush(Stack* ps, STDataType x)
- {
- // 此时需要保证传入的栈,不是空
- assert(ps);
-
- // 扩容
- // 判断是否需要扩容
- if (ps->top == ps->capacity)
- {
- int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
- STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
- // 防止返回的是空指针
- if (temp == NULL)
- {
- perror("realloc fail!");
- exit(-1);
- }
- ps->a = temp;
- ps->capacity = newcapacity;
- }
- // 进行尾插数据
- ps->a[ps->top] = x;
- ps->top++;
- }
只需要将栈顶的数据移除即可。
注意:一定要保证栈顶有数据
- void StackPop(Stack* ps)
- {
- assert(ps);
- assert(!StackEmpty(ps));//检测栈是否为空
-
- ps->top--;//栈顶下移
- }
获取栈顶元素,即获取栈的最上方的元素。若栈为空,则不能获取。
- STDataType StackTop(Stack* ps)
- {
- assert(ps); // 确保传入的栈指针非空
- assert(!StackEmpty(ps)); // 确保栈不为空,防止访问空栈
-
- return ps->a[ps->top - 1]; // 返回栈顶元素
- //ps->a[ps->top - 1]:这部分代码访问栈中的数组 a,并获取栈顶元素。
- //这里使用 ps->top - 1 是因为 top 通常表示下一个可插入元素的位置,
- //所以栈顶的实际元素位于 top - 1 的位置。
- }
判断栈是否为空的函数通常检查栈顶指针top的值。如果top为0,则表示栈中没有元素,即栈为空
- bool StackEmpty(Stack* ps)
- {
- assert(ps); // 断言检查,确保传入的栈指针非空
- return ps->top == 0; // 返回栈是否为空的判断结果
- }
因为top记录的是栈顶,使用top的值便代表栈中有效元素的个数。
- int StackSize(Stack* ps)
- {
- assert(ps);
-
- return ps->top;//top的值便是栈中有效元素的个数
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。